Import translations. DO NOT MERGE
am: 984f7fb960  -s ours

* commit '984f7fb9603b55d3031f7df04fa37010513b712c':
  Import translations. DO NOT MERGE
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 3601b39..d308d43 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -48,11 +48,12 @@
 
     // Keyboard layouts configuration.
     KeyboardLayout[] getKeyboardLayouts();
+    KeyboardLayout[] getKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
     KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor);
     String getCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier);
     void setCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
             String keyboardLayoutDescriptor);
-    String[] getKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
+    String[] getEnabledKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
     void addKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
             String keyboardLayoutDescriptor);
     void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 618864f..4934752 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -471,6 +471,29 @@
     }
 
     /**
+     * Gets information about all supported keyboard layouts appropriate
+     * for a specific input device.
+     * <p>
+     * The input manager consults the built-in keyboard layouts as well
+     * as all keyboard layouts advertised by applications using a
+     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
+     * </p>
+     *
+     * @return A list of all supported keyboard layouts for a specific
+     * input device.
+     *
+     * @hide
+     */
+    public KeyboardLayout[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
+        try {
+            return mIm.getKeyboardLayoutsForInputDevice(identifier);
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Could not get list of keyboard layouts for input device.", ex);
+            return new KeyboardLayout[0];
+        }
+    }
+
+    /**
      * Gets the keyboard layout with the specified descriptor.
      *
      * @param keyboardLayoutDescriptor The keyboard layout descriptor, as returned by
@@ -548,13 +571,13 @@
      * @return The keyboard layout descriptors.
      * @hide
      */
-    public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
+    public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
         if (identifier == null) {
             throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
         }
 
         try {
-            return mIm.getKeyboardLayoutsForInputDevice(identifier);
+            return mIm.getEnabledKeyboardLayoutsForInputDevice(identifier);
         } catch (RemoteException ex) {
             Log.w(TAG, "Could not get keyboard layouts for input device.", ex);
             return ArrayUtils.emptyArray(String.class);
diff --git a/core/java/android/hardware/input/KeyboardLayout.java b/core/java/android/hardware/input/KeyboardLayout.java
index ed51402..584008c 100644
--- a/core/java/android/hardware/input/KeyboardLayout.java
+++ b/core/java/android/hardware/input/KeyboardLayout.java
@@ -19,6 +19,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Locale;
+
 /**
  * Describes a keyboard layout.
  *
@@ -30,6 +32,9 @@
     private final String mLabel;
     private final String mCollection;
     private final int mPriority;
+    private final Locale[] mLocales;
+    private final int mVendorId;
+    private final int mProductId;
 
     public static final Parcelable.Creator<KeyboardLayout> CREATOR =
             new Parcelable.Creator<KeyboardLayout>() {
@@ -41,11 +46,19 @@
         }
     };
 
-    public KeyboardLayout(String descriptor, String label, String collection, int priority) {
+    public KeyboardLayout(String descriptor, String label, String collection, int priority,
+            Locale[] locales, int vid, int pid) {
         mDescriptor = descriptor;
         mLabel = label;
         mCollection = collection;
         mPriority = priority;
+        if (locales != null) {
+            mLocales = locales;
+        } else {
+            mLocales = new Locale[0];
+        }
+        mVendorId = vid;
+        mProductId = pid;
     }
 
     private KeyboardLayout(Parcel source) {
@@ -53,6 +66,13 @@
         mLabel = source.readString();
         mCollection = source.readString();
         mPriority = source.readInt();
+        int N = source.readInt();
+        mLocales = new Locale[N];
+        for (int i = 0; i < N; i++) {
+            mLocales[i] = Locale.forLanguageTag(source.readString());
+        }
+        mVendorId = source.readInt();
+        mProductId = source.readInt();
     }
 
     /**
@@ -83,6 +103,33 @@
         return mCollection;
     }
 
+    /**
+     * Gets the locales that this keyboard layout is intended for.
+     * This may be empty if a locale has not been assigned to this keyboard layout.
+     * @return The keyboard layout's intended locale.
+     */
+    public Locale[] getLocales() {
+        return mLocales;
+    }
+
+    /**
+     * Gets the vendor ID of the hardware device this keyboard layout is intended for.
+     * Returns -1 if this is not specific to any piece of hardware.
+     * @return The hardware vendor ID of the keyboard layout's intended device.
+     */
+    public int getVendorId() {
+        return mVendorId;
+    }
+
+    /**
+     * Gets the product ID of the hardware device this keyboard layout is intended for.
+     * Returns -1 if this is not specific to any piece of hardware.
+     * @return The hardware product ID of the keyboard layout's intended device.
+     */
+    public int getProductId() {
+        return mProductId;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -94,6 +141,16 @@
         dest.writeString(mLabel);
         dest.writeString(mCollection);
         dest.writeInt(mPriority);
+        if (mLocales != null) {
+            dest.writeInt(mLocales.length);
+            for (Locale l : mLocales) {
+                dest.writeString(l.toLanguageTag());
+            }
+        } else {
+            dest.writeInt(0);
+        }
+        dest.writeInt(mVendorId);
+        dest.writeInt(mProductId);
     }
 
     @Override
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5994d4f..bb09829 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -163,6 +163,16 @@
      */
     void setScreenCaptureDisabled(int userId, boolean disabled);
 
+    /**
+     * Cancels the window transitions for the given task.
+     */
+    void cancelTaskWindowTransition(int taskId);
+
+    /**
+     * Cancels the thumbnail transitions for the given task.
+     */
+    void cancelTaskThumbnailTransition(int taskId);
+
     // These can only be called with the SET_ORIENTATION permission.
     /**
      * Update the current screen rotation based on the current state of
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 94e9c4e..361e7d2 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -70,8 +70,11 @@
          (the screen is in landscape). This may be either a fraction or a dimension.-->
     <item type="dimen" name="dialog_fixed_height_minor">90%</item>
 
-    <!-- Height of the bottom navigation bar in portrait; on sw600dp devices
-         this is a bit taller -->
+    <!-- Height of the bottom navigation / system bar. -->
+    <dimen name="navigation_bar_height">56dp</dimen>
+    <!-- Height of the bottom navigation bar in landscape; often the same as @dimen/navigation_bar_height -->
+    <dimen name="navigation_bar_height_landscape">56dp</dimen>
+    <!-- Height of the bottom navigation bar in portrait -->
     <dimen name="navigation_bar_height_portrait">56dp</dimen>
 
     <!-- Preference fragment padding, sides -->
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 67abe8d..2e574aa 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7675,6 +7675,12 @@
         <attr name="label" />
         <!-- The key character map file resource. -->
         <attr name="keyboardLayout" format="reference" />
+        <!-- The locales the given keyboard layout corresponds to. -->
+        <attr name="locale" format="string" />
+        <!-- The vendor ID of the hardware the given layout corresponds to. @hide -->
+        <attr name="vendorId" format="integer" />
+        <!-- The product ID of the hardware the given layout corresponds to. @hide -->
+        <attr name="productId" format="integer" />
     </declare-styleable>
 
     <declare-styleable name="MediaRouteButton">
diff --git a/packages/BackupRestoreConfirmation/res/values-ne-rNP/strings.xml b/packages/BackupRestoreConfirmation/res/values-ne-rNP/strings.xml
index 473802e..66d340c 100644
--- a/packages/BackupRestoreConfirmation/res/values-ne-rNP/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-ne-rNP/strings.xml
@@ -21,14 +21,14 @@
     <string name="backup_confirm_text" msgid="1878021282758896593">"एउटा जोडिएको डेस्कटप कम्प्युटरमा सबै डेटाको एउटा पूर्ण जगेडाको अनुरोध गरिएको छ। के तपाईँ यो हुन दिन चाहनुहुन्छ? \n\nयदि तपाईँले जगेडाको लागि आफैँ अनुरोध गर्नु भएन भने प्रक्रियालाई अगाडि बढ्न अनुमति नदिनुहोस्।"</string>
     <string name="allow_backup_button_label" msgid="4217228747769644068">"मेरो डेटा ब्याकअप गर्नुहोस्"</string>
     <string name="deny_backup_button_label" msgid="6009119115581097708">"जगेडा नगर्नुहोस्"</string>
-    <string name="restore_confirm_text" msgid="7499866728030461776">"एउटा जडित डेस्कटप कम्प्युटरबाट सबै डेटाको पूर्ण पुनःबहाली अनुरोध गरियो। के तपाईं यो हुन अनुमति दिनुहुन्छ?\n\nयदि तपाईं आफैं पुनःबहाली अनुरोध गर्नुहुन्न भने अपरेसनलाई अघि बढाउन अनुमति नदिनुहोस्। यसले उपकरणमा भएको कुनै पनि डेटालाई बदल्ने छ!"</string>
+    <string name="restore_confirm_text" msgid="7499866728030461776">"एउटा जडित डेस्कटप कम्प्युटरबाट सबै डेटाको पूर्ण पुनःबहाली अनुरोध गरियो। के तपाईँ यो हुन अनुमति दिनुहुन्छ?\n\nयदि तपाईँ आफैं पुनःबहाली अनुरोध गर्नुहुन्न भने अपरेसनलाई अघि बढाउन अनुमति नदिनुहोस्। यसले उपकरणमा भएको कुनै पनि डेटालाई बदल्ने छ!"</string>
     <string name="allow_restore_button_label" msgid="3081286752277127827">"मेरो डेटा पुनःबहाली गर्नुहोस्"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"पुन:स्थापना नगर्नुहोस्"</string>
     <string name="current_password_text" msgid="8268189555578298067">"कृपया तल तपाईंको हालको ब्याकअप पासवर्ड प्रविष्टि गर्नुहोस्:"</string>
     <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया तल तपाईंको उपकरण एन्क्रिप्सन पासवर्ड प्रविष्टि गर्नुहोस्:"</string>
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया तल तपाईंको उपकरण एन्क्रिप्सन पासवर्ड प्रविष्टि गर्नुहोस्: यो ब्याकप सँग्रह एन्क्रिप्ट गर्न पनि प्रयोग हुने छ।"</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"ब्याकप डेटालाई encrypt गर्न पासवर्ड प्रविष्टि गर्नुहोस्, यदि यो खालि छोडिएको खण्डमा तपाईको पुरानै पासवर्ड प्रयोग हुने छ।"</string>
-    <string name="backup_enc_password_optional" msgid="1350137345907579306">"यदि तपाईं पूर्ण ब्याकअप डेटा इन्क्रिप्ट गर्न चाहनु हुन्छ भने तल पासवर्ड प्रविष्टि गर्नुहोस्।"</string>
+    <string name="backup_enc_password_optional" msgid="1350137345907579306">"यदि तपाईँ पूर्ण ब्याकअप डेटा इन्क्रिप्ट गर्न चाहनु हुन्छ भने तल पासवर्ड प्रविष्टि गर्नुहोस्।"</string>
     <string name="backup_enc_password_required" msgid="7889652203371654149">"तपाईँको उपकरण गुप्तिकरण गरिए देखि, तपाईंले आफ्नो जगेडा गुप्तिकरण गर्न आवश्यक छ। कृपया तल पासवर्ड प्रविष्ट गर्नुहोस्:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"यदि पुनःबहाली डेटा इन्क्रिप्ट छ भने कृपया तल पासवर्ड प्रविष्टि गर्नुहोस्:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"जगेडा राख्न सुरु हुँदै..."</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-ro/strings.xml b/packages/BackupRestoreConfirmation/res/values-ro/strings.xml
index 6a7dbbd..b762059 100644
--- a/packages/BackupRestoreConfirmation/res/values-ro/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-ro/strings.xml
@@ -35,5 +35,5 @@
     <string name="toast_backup_ended" msgid="3818080769548726424">"Copierea de rezervă a fost finalizată"</string>
     <string name="toast_restore_started" msgid="7881679218971277385">"Se porneşte restabilirea..."</string>
     <string name="toast_restore_ended" msgid="1764041639199696132">"Restabilirea s-a încheiat"</string>
-    <string name="toast_timeout" msgid="5276598587087626877">"Operaţia a expirat"</string>
+    <string name="toast_timeout" msgid="5276598587087626877">"Operația a expirat"</string>
 </resources>
diff --git a/packages/Keyguard/res/values-ne-rNP/strings.xml b/packages/Keyguard/res/values-ne-rNP/strings.xml
index d18d0f2..4a5907e0 100644
--- a/packages/Keyguard/res/values-ne-rNP/strings.xml
+++ b/packages/Keyguard/res/values-ne-rNP/strings.xml
@@ -82,22 +82,22 @@
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"तपाईँले तपाईँको अनलक ढाँचा गलत तरिकाले <xliff:g id="NUMBER_0">%d</xliff:g> पटक खिच्नु भएको छ। \n\n <xliff:g id="NUMBER_1">%d</xliff:g> सेकेन्डमा फेरि कोसिस गर्नुहोस्।"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="8774056606869646621">"तपाईंले गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नु भएको छ<xliff:g id="NUMBER_0">%d</xliff:g>पटक।  <xliff:g id="NUMBER_1">%d</xliff:g> थप असफल प्रयासहरूपछि, यो ट्याब्लेट रिसेट हुनेछ जसले आफ्नो सम्पूर्ण डेटा मेट्नेछ।"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="1843331751334128428">"तपाईंले गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नु भएको छ <xliff:g id="NUMBER_0">%d</xliff:g> पटक। पछि <xliff:g id="NUMBER_1">%d</xliff:g> थप असफल प्रयासहरूपछि, यो फोन  रिसेट हुनेछ जसले सम्पूर्ण डेटा मेटाउनेछ।।"</string>
-    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="258925501999698032">"तपाईं गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नु भएको छ <xliff:g id="NUMBER">%d</xliff:g> पटक। यो ट्याब्लेट रिेसेट गरिनेछ जसले सम्पूर्ण डेटा मेट्नेछ।"</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="258925501999698032">"तपाईँ गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नु भएको छ <xliff:g id="NUMBER">%d</xliff:g> पटक। यो ट्याब्लेट रिेसेट गरिनेछ जसले सम्पूर्ण डेटा मेट्नेछ।"</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="7154028908459817066">"तपाईंले गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नु भएको छ <xliff:g id="NUMBER">%d</xliff:g> पटक। यो फोन रिसेट गरिनेछ जसले सम्पूर्ण डेटा मेट्नेछ।"</string>
     <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="6159955099372112688">"तपाईंले गलत तरिकाले  ट्याब्लेट अनलक गर्ने प्रयास गर्नु भएको छ<xliff:g id="NUMBER_0">%d</xliff:g> पटक।  <xliff:g id="NUMBER_1">%d</xliff:g> थप असफल प्रयासहरूपछि, यो प्रयोगकर्ता हटाइनेछ जसले सम्पूर्ण प्रयोगकर्ता डेटा मेट्नेछ।"</string>
     <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="6945823186629369880">"तपाईंले गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नु भएको छ <xliff:g id="NUMBER_0">%d</xliff:g> पटक। <xliff:g id="NUMBER_1">%d</xliff:g> थप असफल प्रयासहरूपछि, यो प्रयोगकर्ता हटाइनेछ जसले  सबै प्रयोगकर्ता डेटा मेट्नेछ।"</string>
     <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="3963486905355778734">"तपाईंले गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नु भएको छ<xliff:g id="NUMBER">%d</xliff:g> पटक। यो प्रयोगकर्ता हटाइनेछ जसले सम्पूर्ण प्रयोगकर्ता डेटा मेट्नेछ ।"</string>
     <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="7729009752252111673">"तपाईंले गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नु भएको छ<xliff:g id="NUMBER">%d</xliff:g> पटक। यो प्रयोगकर्ता हटाइनेछ जसले सम्पूर्ण प्रयोगकर्ता डेटा मेट्नेछ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="4621778507387853694">"तपाईं गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नु भएको छ<xliff:g id="NUMBER_0">%d</xliff:g> पटक। <xliff:g id="NUMBER_1">%d</xliff:g> थप असफल प्रयासहरूपछि, काम प्रोफाइल हटाइनेछ जसले सबै प्रोफाइल डेटा मेट्नेछ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="4621778507387853694">"तपाईँ गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नु भएको छ<xliff:g id="NUMBER_0">%d</xliff:g> पटक। <xliff:g id="NUMBER_1">%d</xliff:g> थप असफल प्रयासहरूपछि, काम प्रोफाइल हटाइनेछ जसले सबै प्रोफाइल डेटा मेट्नेछ।"</string>
     <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="6853071165802933545">"तपाईंले गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नु भएको छ <xliff:g id="NUMBER_0">%d</xliff:g> पटक। <xliff:g id="NUMBER_1">%d</xliff:g> थप असफल प्रयासहरूपछि , काम प्रोफाइल हटाइनेछ जसले सबै प्रोफाइल डेटा मेट्नेछ।"</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4686386497449912146">"तपाईं गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नु भएको छ<xliff:g id="NUMBER">%d</xliff:g> पटक। काम प्रोफाइल हटाइनेछ जसले सम्पूर्ण  प्रोफाइल डेटा मेट्नेछ ।"</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4686386497449912146">"तपाईँ गलत तरिकाले ट्याब्लेट अनलक गर्ने प्रयास गर्नु भएको छ<xliff:g id="NUMBER">%d</xliff:g> पटक। काम प्रोफाइल हटाइनेछ जसले सम्पूर्ण  प्रोफाइल डेटा मेट्नेछ ।"</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4951507352869831265">"तपाईंले गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नु भएको छ <xliff:g id="NUMBER">%d</xliff:g> पटक। काम प्रोफाइल हटाइनेछ जसले सम्पूर्ण प्रोफाइल डेटा मेट्नेछ।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"तपाईंले गलत तरिकाले आफ्नो अनलक ढाँचा <xliff:g id="NUMBER_0">%d</xliff:g> पटक कोर्नुभयो। <xliff:g id="NUMBER_1">%d</xliff:g> विफल प्रयत्नहरू पछि, तपाईंलाई आफ्नो ट्याब्लेट इमेल खाता प्रयोग गरेर अनलक गर्न सोधिने छ।\n\n फेरि प्रयास गर्नुहोस् <xliff:g id="NUMBER_2">%d</xliff:g> सेकेन्डहरूमा।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"तपाईँले आफ्नो अनलक ढाँचा गलत रूपमा <xliff:g id="NUMBER_0">%d</xliff:g> पटक तान्नु भएको छ। <xliff:g id="NUMBER_1">%d</xliff:g> धेरै असफल प्रयासहरूपछि, तपाईँलाई एउटा इमेल खाताको प्रयोग गरेर तपाईँको फोन अनलक गर्न सोधिने छ।\n\n फेरि <xliff:g id="NUMBER_2">%d</xliff:g> सेकेन्डमा प्रयास गर्नुहोस्।"</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM PIN कोड गलत छ। अब तपाईंले अाफ्नो उपकरण खोल्नलाई तपाईंको वाहकसँग सम्पर्क गर्नै पर्दर।"</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
-      <item quantity="other"> गलत SIM PIN कोड, तपाईं सँग <xliff:g id="NUMBER_1">%d</xliff:g> पटक प्रयास बाँकी छ।</item>
-      <item quantity="one">SIM PIN कोड गलत छ, तपाईंले अाफ्नो यन्त्र खोल्नलाई तपाईंको वाहकसँग सम्पर्क गर्नै पर्न अघि तपाईंसँग <xliff:g id="NUMBER_0">%d</xliff:g> पटक प्रयास बाँकी छ।</item>
+      <item quantity="other"> गलत SIM PIN कोड, तपाईँ सँग <xliff:g id="NUMBER_1">%d</xliff:g> पटक प्रयास बाँकी छ।</item>
+      <item quantity="one">SIM PIN कोड गलत छ, तपाईँले अाफ्नो यन्त्र खोल्नलाई तपाईँको वाहकसँग सम्पर्क गर्नै पर्न अघि तपाईँसँग <xliff:g id="NUMBER_0">%d</xliff:g> पटक प्रयास बाँकी छ।</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM प्रयोग बिहिन छ। तपाईंको वाहकलाई सम्पर्क गर्नुहोस्।"</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 1a319e6..e21e833 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -69,7 +69,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gunakan untuk audio ponsel"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gunakan untuk transfer file"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gunakan untuk masukan"</string>
-    <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pasangan"</string>
+    <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sandingkan"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SANDINGKAN"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Batal"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Penyandingan memberi akses ke kontak dan riwayat panggilan saat tersambung"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index a89e958..ae737b8 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -69,7 +69,7 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Użyj dla funkcji audio telefonu"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Użyj do transferu plików"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Użyj do wprowadzania"</string>
-    <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Powiąż"</string>
+    <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sparuj"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SPARUJ"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anuluj"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Parowanie spowoduje przyznanie dostępu do historii połączeń i Twoich kontaktów w trakcie połączenia."</string>
diff --git a/packages/Shell/res/values-sv/strings.xml b/packages/Shell/res/values-sv/strings.xml
index 47ee2f7..8b72938 100644
--- a/packages/Shell/res/values-sv/strings.xml
+++ b/packages/Shell/res/values-sv/strings.xml
@@ -18,7 +18,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="3701846017049540910">"Skal"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Felrapporten har skapats"</string>
-    <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Dra till vänster om du vill dela felrapporten"</string>
+    <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Svep åt vänster om du vill dela felrapporten"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Tryck om du vill dela felrapporten"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Felrapporter innehåller data från systemets olika loggfiler, inklusive personliga och privata uppgifter. Dela bara felrapporter med personer du litar på."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Visa det här meddelandet nästa gång"</string>
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 47e24e8..2b8ca89 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -10,6 +10,16 @@
   public void setGlowScale(float);
 }
 
+-keep class com.android.systemui.recents.views.TaskView {
+  public void setHighlightProgress(float);
+  public float getHighlightProgress();
+}
+
+-keep class com.android.systemui.recents.views.TaskViewHeader {
+  public void setFocusProgress(float);
+  public float getFocusProgress();
+}
+
 -keep class com.android.systemui.statusbar.phone.PhoneStatusBar
 -keep class com.android.systemui.statusbar.tv.TvStatusBar
 -keep class com.android.systemui.recents.*
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
index 3d73184..b790d71 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp/ic_ime_switcher_default.xml b/packages/SystemUI/res/drawable-sw600dp/ic_ime_switcher_default.xml
new file mode 100644
index 0000000..535336b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp/ic_ime_switcher_default.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="28.0dp"
+        android:height="28.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M20.000000,5.000000L4.000000,5.000000C2.900000,5.000000 2.000000,5.900000 2.000000,7.000000l0.000000,10.000000c0.000000,1.100000 0.900000,2.000000 2.000000,2.000000l16.000000,0.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L22.000000,7.000000C22.000000,5.900000 21.100000,5.000000 20.000000,5.000000zM11.000000,8.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,8.000000zM11.000000,11.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,11.000000zM8.000000,8.000000l2.000000,0.000000l0.000000,2.000000L8.000000,10.000000L8.000000,8.000000zM8.000000,11.000000l2.000000,0.000000l0.000000,2.000000L8.000000,13.000000L8.000000,11.000000zM7.000000,13.000000L5.000000,13.000000l0.000000,-2.000000l2.000000,0.000000L7.000000,13.000000zM7.000000,10.000000L5.000000,10.000000L5.000000,8.000000l2.000000,0.000000L7.000000,10.000000zM16.000000,17.000000L8.000000,17.000000l0.000000,-2.000000l8.000000,0.000000L16.000000,17.000000zM16.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L16.000000,13.000000zM16.000000,10.000000l-2.000000,0.000000L14.000000,8.000000l2.000000,0.000000L16.000000,10.000000zM19.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L19.000000,13.000000zM19.000000,10.000000l-2.000000,0.000000L17.000000,8.000000l2.000000,0.000000L19.000000,10.000000z"
+        android:fillColor="@color/navigation_bar_icon_color"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
old mode 100644
new mode 100755
index 987aac5..fbdc93c
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
old mode 100644
new mode 100755
index 433e5a74..419518c
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
old mode 100644
new mode 100755
index 0e2a14d..a2406b1
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
old mode 100644
new mode 100755
index 69a018d..50043eb
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
old mode 100644
new mode 100755
index f810704..c449449
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index 9912343..87da189 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -42,19 +42,15 @@
 
             <!-- navigation controls -->
             <View
-                android:layout_width="@dimen/navigation_extra_key_width"
                 android:layout_height="match_parent"
+                android:layout_width="@dimen/navigation_side_padding"
                 android:layout_weight="0"
-                android:layout_marginStart="2dp"
                 android:visibility="invisible"
                 />
-            <Space
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
                 android:layout_height="match_parent"
                 android:src="@drawable/ic_sysbar_back"
                 android:scaleType="centerInside"
@@ -63,7 +59,9 @@
                 android:contentDescription="@string/accessibility_back"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
-                android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
                 android:layout_height="match_parent"
                 android:src="@drawable/ic_sysbar_home"
                 android:scaleType="centerInside"
@@ -72,44 +70,55 @@
                 android:layout_weight="0"
                 android:contentDescription="@string/accessibility_home"
                 />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
-                android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
-                android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_recent"
-                android:scaleType="centerInside"
-                android:layout_weight="0"
-                android:contentDescription="@string/accessibility_recent"
-                />
             <Space
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1"
                 />
             <FrameLayout
-                android:layout_width="@dimen/navigation_extra_key_width"
+                android:layout_width="@dimen/navigation_key_width"
                 android:layout_height="match_parent"
                 android:layout_weight="0"
-                android:layout_marginEnd="2dp" >
+                android:clipChildren="false"
+                android:clipToPadding="false" >
                 <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_width="@dimen/navigation_key_width"
                     android:layout_height="match_parent"
+                    android:paddingStart="@dimen/navigation_key_padding"
+                    android:paddingEnd="@dimen/navigation_key_padding"
                     android:src="@drawable/ic_sysbar_menu"
                     android:scaleType="centerInside"
-                    android:layout_marginEnd="2dp"
                     systemui:keyCode="82"
                     android:visibility="invisible"
                     android:contentDescription="@string/accessibility_menu"
                     />
                 <com.android.systemui.statusbar.policy.KeyButtonView
                     android:id="@+id/ime_switcher"
-                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_width="@dimen/navigation_key_width"
                     android:layout_height="match_parent"
-                    android:layout_marginEnd="2dp"
+                    android:paddingStart="@dimen/navigation_key_padding"
+                    android:paddingEnd="@dimen/navigation_key_padding"
                     android:scaleType="centerInside"
                     android:src="@drawable/ic_ime_switcher_default"
                     android:visibility="invisible"
                     android:contentDescription="@string/accessibility_ime_switch_button" />
             </FrameLayout>
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_recent"
+                android:scaleType="centerInside"
+                android:layout_weight="0"
+                android:contentDescription="@string/accessibility_recent"
+                />
+            <View
+                android:layout_height="match_parent"
+                android:layout_width="@dimen/navigation_side_padding"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                />
         </LinearLayout>
 
         <!-- lights out layout to match exactly -->
@@ -120,41 +129,52 @@
             android:id="@+id/lights_out"
             android:visibility="gone"
             >
-            <Space
-                android:layout_width="match_parent"
+            <View
                 android:layout_height="match_parent"
-                android:layout_weight="1"
+                android:layout_width="@dimen/navigation_side_padding"
+                android:layout_weight="0"
+                android:visibility="invisible"
                 />
             <ImageView
-                android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
                 android:layout_height="match_parent"
-                android:layout_marginStart="40dp"
                 android:src="@drawable/ic_sysbar_lights_out_dot_small"
                 android:scaleType="center"
                 android:layout_weight="0"
                 android:contentDescription="@string/accessibility_back"
                 />
             <ImageView
-                android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
                 android:layout_height="match_parent"
                 android:src="@drawable/ic_sysbar_lights_out_dot_large"
                 android:scaleType="center"
                 android:layout_weight="0"
                 android:contentDescription="@string/accessibility_home"
                 />
+            <Space
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                />
             <ImageView
-                android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
-                android:layout_marginEnd="40dp"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
                 android:layout_height="match_parent"
                 android:src="@drawable/ic_sysbar_lights_out_dot_small"
                 android:scaleType="center"
                 android:layout_weight="0"
                 android:contentDescription="@string/accessibility_recent"
                 />
-            <Space
-                android:layout_width="match_parent"
+            <View
                 android:layout_height="match_parent"
-                android:layout_weight="1"
+                android:layout_width="@dimen/navigation_side_padding"
+                android:layout_weight="0"
+                android:visibility="invisible"
                 />
         </LinearLayout>
 
@@ -190,19 +210,15 @@
 
             <!-- navigation controls -->
             <View
-                android:layout_width="@dimen/navigation_extra_key_width"
                 android:layout_height="match_parent"
+                android:layout_width="@dimen/navigation_side_padding"
                 android:layout_weight="0"
-                android:layout_marginStart="2dp"
                 android:visibility="invisible"
                 />
-            <Space
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
                 android:layout_height="match_parent"
                 android:src="@drawable/ic_sysbar_back"
                 android:scaleType="centerInside"
@@ -211,7 +227,9 @@
                 android:contentDescription="@string/accessibility_back"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
-                android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
                 android:layout_height="match_parent"
                 android:src="@drawable/ic_sysbar_home"
                 android:scaleType="centerInside"
@@ -220,28 +238,21 @@
                 android:layout_weight="0"
                 android:contentDescription="@string/accessibility_home"
                 />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
-                android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
-                android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_recent"
-                android:scaleType="centerInside"
-                android:layout_weight="0"
-                android:contentDescription="@string/accessibility_recent"
-                />
             <Space
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1"
                 />
             <FrameLayout
-                android:layout_width="@dimen/navigation_extra_key_width"
+                android:layout_width="@dimen/navigation_key_width"
                 android:layout_height="match_parent"
-                android:layout_marginEnd="2dp"
-                android:layout_weight="0" >
+                android:clipChildren="false"
+                android:clipToPadding="false" >
                 <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_width="@dimen/navigation_key_width"
                     android:layout_height="match_parent"
-                    android:layout_marginEnd="2dp"
+                    android:paddingStart="@dimen/navigation_key_padding"
+                    android:paddingEnd="@dimen/navigation_key_padding"
                     android:src="@drawable/ic_sysbar_menu"
                     android:scaleType="centerInside"
                     systemui:keyCode="82"
@@ -249,14 +260,31 @@
                     android:contentDescription="@string/accessibility_menu" />
                 <com.android.systemui.statusbar.policy.KeyButtonView
                     android:id="@+id/ime_switcher"
-                    android:layout_width="@dimen/navigation_extra_key_width"
+                    android:layout_width="@dimen/navigation_key_width"
                     android:layout_height="match_parent"
-                    android:layout_marginEnd="2dp"
+                    android:paddingStart="@dimen/navigation_key_padding"
+                    android:paddingEnd="@dimen/navigation_key_padding"
                     android:src="@drawable/ic_ime_switcher_default"
                     android:visibility="invisible"
                     android:contentDescription="@string/accessibility_ime_switch_button"
                     android:scaleType="centerInside" />
             </FrameLayout>
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_recent"
+                android:scaleType="centerInside"
+                android:layout_weight="0"
+                android:contentDescription="@string/accessibility_recent"
+                />
+            <View
+                android:layout_height="match_parent"
+                android:layout_width="@dimen/navigation_side_padding"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                />
         </LinearLayout>
 
         <!-- lights out layout to match exactly -->
@@ -267,41 +295,52 @@
             android:id="@+id/lights_out"
             android:visibility="gone"
             >
-            <Space
-                android:layout_width="match_parent"
+            <View
                 android:layout_height="match_parent"
-                android:layout_weight="1"
+                android:layout_width="@dimen/navigation_side_padding"
+                android:layout_weight="0"
+                android:visibility="invisible"
                 />
             <ImageView
-                android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
                 android:layout_height="match_parent"
-                android:layout_marginStart="40dp"
                 android:src="@drawable/ic_sysbar_lights_out_dot_small"
                 android:scaleType="center"
                 android:layout_weight="0"
                 android:contentDescription="@string/accessibility_back"
                 />
             <ImageView
-                android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
                 android:layout_height="match_parent"
                 android:src="@drawable/ic_sysbar_lights_out_dot_large"
                 android:scaleType="center"
                 android:layout_weight="0"
                 android:contentDescription="@string/accessibility_home"
                 />
+            <Space
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                />
             <ImageView
-                android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
-                android:layout_marginEnd="40dp"
+                android:layout_width="@dimen/navigation_key_width"
+                android:paddingStart="@dimen/navigation_key_padding"
+                android:paddingEnd="@dimen/navigation_key_padding"
                 android:layout_height="match_parent"
                 android:src="@drawable/ic_sysbar_lights_out_dot_small"
                 android:scaleType="center"
                 android:layout_weight="0"
                 android:contentDescription="@string/accessibility_recent"
                 />
-            <Space
-                android:layout_width="match_parent"
+            <View
                 android:layout_height="match_parent"
-                android:layout_weight="1"
+                android:layout_width="@dimen/navigation_side_padding"
+                android:layout_weight="0"
+                android:visibility="invisible"
                 />
         </LinearLayout>
 
diff --git a/packages/SystemUI/res/layout-sw600dp/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout-sw600dp/screen_pinning_request_buttons.xml
new file mode 100644
index 0000000..cb3a972
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/screen_pinning_request_buttons.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<!--
+     This layout matches the structure of navigation_bar.xml and will need
+     to be kept up to sync with changes there.
+     On sw600dp, dimensions are changed to be large enough such that the
+     empty views between the buttons is reduced to nothing, if (nav bar)
+     sw600dp layout is changed then this will likely have to be adjusted
+     and possibly need a sw600dp specific one.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/screen_pinning_buttons"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/screen_pinning_request_button_height"
+    android:background="@color/screen_pinning_request_bg" >
+
+    <View
+        android:layout_width="@dimen/screen_pinning_request_side_width"
+        android:layout_height="match_parent"
+        android:layout_weight="0"
+        android:visibility="invisible" />
+
+    <FrameLayout
+        android:id="@+id/screen_pinning_back_group"
+        android:layout_width="@dimen/screen_pinning_request_button_width"
+        android:layout_height="@dimen/screen_pinning_request_button_height"
+        android:layout_weight="0"
+        android:paddingStart="@dimen/screen_pinning_request_frame_padding"
+        android:paddingEnd="@dimen/screen_pinning_request_frame_padding" >
+
+        <ImageView
+            android:id="@+id/screen_pinning_back_bg_light"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:scaleType="matrix"
+            android:src="@drawable/screen_pinning_light_bg_circ" />
+
+        <ImageView
+            android:id="@+id/screen_pinning_back_bg"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:paddingEnd="@dimen/screen_pinning_request_inner_padding"
+            android:paddingStart="@dimen/screen_pinning_request_inner_padding"
+            android:paddingTop="@dimen/screen_pinning_request_inner_padding"
+            android:scaleType="matrix"
+            android:src="@drawable/screen_pinning_bg_circ" />
+
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding"
+            android:paddingStart="@dimen/screen_pinning_request_nav_side_padding"
+            android:paddingTop="@dimen/screen_pinning_request_nav_icon_padding"
+            android:scaleType="center"
+            android:src="@drawable/ic_sysbar_back" />
+    </FrameLayout>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:visibility="invisible" />
+
+    <FrameLayout
+        android:id="@+id/screen_pinning_home_group"
+        android:layout_width="@dimen/screen_pinning_request_button_width"
+        android:layout_height="@dimen/screen_pinning_request_button_height"
+        android:paddingStart="@dimen/screen_pinning_request_frame_padding"
+        android:paddingEnd="@dimen/screen_pinning_request_frame_padding"
+        android:layout_weight="0"
+        android:visibility="invisible" >
+
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding"
+            android:paddingStart="@dimen/screen_pinning_request_nav_side_padding"
+            android:paddingTop="@dimen/screen_pinning_request_nav_icon_padding"
+            android:scaleType="center"
+            android:src="@drawable/ic_sysbar_home" />
+    </FrameLayout>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:visibility="invisible" />
+
+    <FrameLayout
+        android:id="@+id/screen_pinning_recents_group"
+        android:layout_width="@dimen/screen_pinning_request_button_width"
+        android:layout_height="@dimen/screen_pinning_request_button_height"
+        android:layout_weight="0"
+        android:paddingStart="@dimen/screen_pinning_request_frame_padding"
+        android:paddingEnd="@dimen/screen_pinning_request_frame_padding" >
+
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:scaleType="matrix"
+            android:src="@drawable/screen_pinning_light_bg_circ" />
+
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:paddingEnd="@dimen/screen_pinning_request_inner_padding"
+            android:paddingStart="@dimen/screen_pinning_request_inner_padding"
+            android:paddingTop="@dimen/screen_pinning_request_inner_padding"
+            android:scaleType="matrix"
+            android:src="@drawable/screen_pinning_bg_circ" />
+
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding"
+            android:paddingStart="@dimen/screen_pinning_request_nav_side_padding"
+            android:paddingTop="@dimen/screen_pinning_request_nav_icon_padding"
+            android:scaleType="center"
+            android:src="@drawable/ic_sysbar_recent" />
+    </FrameLayout>
+
+    <View
+        android:layout_width="@dimen/screen_pinning_request_side_width"
+        android:layout_height="match_parent"
+        android:layout_weight="0"
+        android:visibility="invisible" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/screen_pinning_request_buttons_land.xml b/packages/SystemUI/res/layout-sw600dp/screen_pinning_request_buttons_land.xml
new file mode 100644
index 0000000..653069e
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/screen_pinning_request_buttons_land.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<!-- Note all width/height dimensions are switched here to handle landspace
+     rather than duplicating them all.
+     This layout matches the structure of navigation_bar.xml (rot90) and
+     will need to be kept up to sync with changes there.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/screen_pinning_buttons"
+    android:layout_height="match_parent"
+    android:layout_width="@dimen/screen_pinning_request_button_height"
+    android:background="@color/screen_pinning_request_bg"
+    android:orientation="vertical" >
+
+    <View
+        android:layout_height="@dimen/screen_pinning_request_side_width"
+        android:layout_width="match_parent"
+        android:layout_weight="0"
+        android:visibility="invisible" />
+
+    <FrameLayout
+        android:id="@+id/screen_pinning_recents_group"
+        android:layout_height="@dimen/screen_pinning_request_button_width"
+        android:layout_width="@dimen/screen_pinning_request_button_height"
+        android:layout_weight="0" >
+
+        <ImageView
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:scaleType="matrix"
+            android:src="@drawable/screen_pinning_light_bg_circ" />
+
+        <ImageView
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:scaleType="matrix"
+            android:paddingLeft="@dimen/screen_pinning_request_inner_padding"
+            android:paddingTop="@dimen/screen_pinning_request_inner_padding"
+            android:paddingBottom="@dimen/screen_pinning_request_inner_padding"
+            android:src="@drawable/screen_pinning_bg_circ" />
+
+        <ImageView
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:scaleType="center"
+            android:paddingLeft="@dimen/screen_pinning_request_nav_icon_padding"
+            android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
+            android:paddingBottom="@dimen/screen_pinning_request_nav_side_padding"
+            android:src="@drawable/ic_sysbar_recent" />
+    </FrameLayout>
+
+    <View
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:layout_weight="1"
+        android:visibility="invisible" />
+
+    <FrameLayout
+        android:id="@+id/screen_pinning_home_group"
+        android:layout_height="@dimen/screen_pinning_request_button_width"
+        android:layout_width="@dimen/screen_pinning_request_button_height"
+        android:layout_weight="0"
+        android:visibility="invisible" >
+
+        <ImageView
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:scaleType="center"
+            android:paddingLeft="@dimen/screen_pinning_request_nav_icon_padding"
+            android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
+            android:paddingBottom="@dimen/screen_pinning_request_nav_side_padding"
+            android:src="@drawable/ic_sysbar_home" />
+    </FrameLayout>
+
+    <View
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:layout_weight="1"
+        android:visibility="invisible" />
+
+    <FrameLayout
+        android:id="@+id/screen_pinning_back_group"
+        android:layout_height="@dimen/screen_pinning_request_button_width"
+        android:layout_width="@dimen/screen_pinning_request_button_height"
+        android:layout_weight="0" >
+
+        <ImageView
+            android:id="@+id/screen_pinning_back_bg_light"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:scaleType="matrix"
+            android:src="@drawable/screen_pinning_light_bg_circ" />
+
+        <ImageView
+            android:id="@+id/screen_pinning_back_bg"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:scaleType="matrix"
+            android:paddingLeft="@dimen/screen_pinning_request_inner_padding"
+            android:paddingTop="@dimen/screen_pinning_request_inner_padding"
+            android:paddingBottom="@dimen/screen_pinning_request_inner_padding"
+            android:src="@drawable/screen_pinning_bg_circ" />
+
+        <ImageView
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:scaleType="center"
+            android:paddingLeft="@dimen/screen_pinning_request_nav_icon_padding"
+            android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
+            android:paddingBottom="@dimen/screen_pinning_request_nav_side_padding"
+            android:src="@drawable/ic_sysbar_back" />
+    </FrameLayout>
+
+    <View
+        android:layout_height="@dimen/screen_pinning_request_side_width"
+        android:layout_width="match_parent"
+        android:layout_weight="0"
+        android:visibility="invisible" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 195fdb1..aacb878 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -29,8 +29,17 @@
     <!-- Height of search panel including navigation bar height -->
     <dimen name="navbar_search_panel_height">280dip</dimen>
 
-    <!-- The width of the view containing the menu/ime navigation bar icons -->
-    <dimen name="navigation_extra_key_width">48dip</dimen>
+    <!-- The padding on the side of the navigation bar. -->
+    <dimen name="navigation_side_padding">16dp</dimen>
+
+    <!-- The maximum width of the navigation bar ripples. -->
+    <dimen name="key_button_ripple_max_width">76dp</dimen>
+
+    <!-- The width of the view containing navigation buttons -->
+    <dimen name="navigation_key_width">80dp</dimen>
+
+    <!-- The padding around the navigation buttons -->
+    <dimen name="navigation_key_padding">5dp</dimen>
 
     <!-- Size of application thumbnail -->
     <dimen name="status_bar_recents_thumbnail_width">200dp</dimen>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 0dcbe88..3438502 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -26,6 +26,7 @@
     <color name="notification_panel_solid_background">#ff000000</color>
     <drawable name="status_bar_recents_app_thumbnail_background">#88000000</drawable>
     <color name="status_bar_recents_app_label_color">#ffffffff</color>
+    <color name="status_bar_recents_highlight_color">#ff009688</color>
     <drawable name="status_bar_notification_row_background_color">#ff090909</drawable>
     <color name="notification_list_shadow_top">#80000000</color>
     <drawable name="recents_callout_line">#99ffffff</drawable>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 5d06768..e00b1f4 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -167,7 +167,7 @@
     <integer name="recents_enter_from_app_transition_duration">325</integer>
 
     <!-- The duration for animating the task decorations in after transitioning from an app. -->
-    <integer name="recents_task_enter_from_app_duration">200</integer>
+    <integer name="recents_task_enter_from_app_duration">350</integer>
 
     <!-- The duration for animating the task decorations out before transitioning to an app. -->
     <integer name="recents_task_exit_to_app_duration">125</integer>
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index 96ee397..696c55f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -70,17 +70,19 @@
     // time for us to receive the signal that it's starting.
     private static final long BLUETOOTH_START_DELAY_MILLIS = 10 * 1000;
 
+    // We will be scanning up to 30 seconds, after which we'll stop.
+    private static final long BLUETOOTH_SCAN_TIMEOUT_MILLIS = 30 * 1000;
+
     private static final int STATE_NOT_ENABLED = -1;
     private static final int STATE_UNKNOWN = 0;
     private static final int STATE_WAITING_FOR_BOOT_COMPLETED = 1;
     private static final int STATE_WAITING_FOR_TABLET_MODE_EXIT = 2;
     private static final int STATE_WAITING_FOR_DEVICE_DISCOVERY = 3;
     private static final int STATE_WAITING_FOR_BLUETOOTH = 4;
-    private static final int STATE_WAITING_FOR_STATE_PAIRED = 5;
-    private static final int STATE_PAIRING = 6;
-    private static final int STATE_PAIRED = 7;
-    private static final int STATE_USER_CANCELLED = 8;
-    private static final int STATE_DEVICE_NOT_FOUND = 9;
+    private static final int STATE_PAIRING = 5;
+    private static final int STATE_PAIRED = 6;
+    private static final int STATE_USER_CANCELLED = 7;
+    private static final int STATE_DEVICE_NOT_FOUND = 8;
 
     private static final int MSG_INIT = 0;
     private static final int MSG_ON_BOOT_COMPLETED = 1;
@@ -92,6 +94,7 @@
     private static final int MSG_ON_BLE_SCAN_FAILED = 7;
     private static final int MSG_SHOW_BLUETOOTH_DIALOG = 8;
     private static final int MSG_DISMISS_BLUETOOTH_DIALOG = 9;
+    private static final int MSG_BLE_ABORT_SCAN = 10;
 
     private volatile KeyboardHandler mHandler;
     private volatile KeyboardUIHandler mUIHandler;
@@ -107,6 +110,7 @@
     private long mBootCompletedTime;
 
     private int mInTabletMode = InputManager.SWITCH_STATE_UNKNOWN;
+    private int mScanAttempt = 0;
     private ScanCallback mScanCallback;
     private BluetoothDialog mDialog;
 
@@ -328,6 +332,9 @@
             .build();
         mScanCallback = new KeyboardScanCallback();
         scanner.startScan(Arrays.asList(filter), settings, mScanCallback);
+
+        Message abortMsg = mHandler.obtainMessage(MSG_BLE_ABORT_SCAN, ++mScanAttempt, 0);
+        mHandler.sendMessageDelayed(abortMsg, BLUETOOTH_SCAN_TIMEOUT_MILLIS);
     }
 
     private void stopScanning() {
@@ -338,6 +345,19 @@
     }
 
     // Should only be called on the handler thread
+    private void bleAbortScanInternal(int scanAttempt) {
+        if (mState == STATE_WAITING_FOR_DEVICE_DISCOVERY && scanAttempt == mScanAttempt) {
+            if (DEBUG) {
+                Slog.d(TAG, "Bluetooth scan timed out");
+            }
+            stopScanning();
+            // FIXME: should we also try shutting off bluetooth if we enabled
+            // it in the first place?
+            mState = STATE_DEVICE_NOT_FOUND;
+        }
+    }
+
+    // Should only be called on the handler thread
     private void onDeviceAddedInternal(CachedBluetoothDevice d) {
         if (mState == STATE_WAITING_FOR_DEVICE_DISCOVERY && d.getName().equals(mKeyboardName)) {
             stopScanning();
@@ -425,6 +445,12 @@
                     } else {
                         mState = STATE_USER_CANCELLED;
                     }
+                    break;
+                }
+                case MSG_BLE_ABORT_SCAN: {
+                    int scanAttempt = msg.arg1;
+                    bleAbortScanInternal(scanAttempt);
+                    break;
                 }
                 case MSG_ON_BLUETOOTH_STATE_CHANGED: {
                     int bluetoothState = msg.arg1;
@@ -555,8 +581,6 @@
                 return "STATE_WAITING_FOR_DEVICE_DISCOVERY";
             case STATE_WAITING_FOR_BLUETOOTH:
                 return "STATE_WAITING_FOR_BLUETOOTH";
-            case STATE_WAITING_FOR_STATE_PAIRED:
-                return "STATE_WAITING_FOR_STATE_PAIRED";
             case STATE_PAIRING:
                 return "STATE_PAIRING";
             case STATE_PAIRED:
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index a4acf83..2307f1a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -41,8 +41,8 @@
             public static final boolean EnableDismissAll = false;
             // Enables debug mode
             public static final boolean EnableDebugMode = false;
-            // Enables the search bar layout
-            public static final boolean EnableSearchLayout = true;
+            // Enables the search bar integration
+            public static final boolean EnableSearchBar = false;
             // Enables the thumbnail alpha on the front-most task
             public static final boolean EnableThumbnailAlphaOnFrontmost = false;
             // Enables all system stacks to show up in the same recents stack
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d0876fa..9e00b7aa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -248,15 +248,19 @@
                 mEmptyView = mEmptyViewStub.inflate();
             }
             mEmptyView.setVisibility(View.VISIBLE);
-            mRecentsView.setSearchBarVisibility(View.GONE);
+            if (Constants.DebugFlags.App.EnableSearchBar) {
+                mRecentsView.setSearchBarVisibility(View.GONE);
+            }
         } else {
             if (mEmptyView != null) {
                 mEmptyView.setVisibility(View.GONE);
             }
-            if (mRecentsView.hasValidSearchBar()) {
-                mRecentsView.setSearchBarVisibility(View.VISIBLE);
-            } else {
-                refreshSearchWidgetView();
+            if (Constants.DebugFlags.App.EnableSearchBar) {
+                if (mRecentsView.hasValidSearchBar()) {
+                    mRecentsView.setSearchBarVisibility(View.VISIBLE);
+                } else {
+                    refreshSearchWidgetView();
+                }
             }
         }
 
@@ -349,7 +353,9 @@
         mConfig = RecentsConfiguration.reinitialize(this, ssp);
 
         // Initialize the widget host (the host id is static and does not change)
-        mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
+        if (Constants.DebugFlags.App.EnableSearchBar) {
+            mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
+        }
 
         // Set the Recents layout
         setContentView(R.layout.recents);
@@ -364,12 +370,16 @@
         inflateDebugOverlay();
 
         // Bind the search app widget when we first start up
-        mSearchWidgetInfo = ssp.getOrBindSearchAppWidget(this, mAppWidgetHost);
+        if (Constants.DebugFlags.App.EnableSearchBar) {
+            mSearchWidgetInfo = ssp.getOrBindSearchAppWidget(this, mAppWidgetHost);
+        }
 
         // Register the broadcast receiver to handle messages when the screen is turned off
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SCREEN_OFF);
-        filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
+        if (Constants.DebugFlags.App.EnableSearchBar) {
+            filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
+        }
         registerReceiver(mSystemBroadcastReceiver, filter);
     }
 
@@ -475,7 +485,9 @@
         unregisterReceiver(mSystemBroadcastReceiver);
 
         // Stop listening for widget package changes if there was one bound
-        mAppWidgetHost.stopListening();
+        if (Constants.DebugFlags.App.EnableSearchBar) {
+            mAppWidgetHost.stopListening();
+        }
     }
 
     public void onEnterAnimationTriggered() {
@@ -484,20 +496,22 @@
         ViewAnimation.TaskViewEnterContext ctx = new ViewAnimation.TaskViewEnterContext(t);
         mRecentsView.startEnterRecentsAnimation(ctx);
 
-        if (mSearchWidgetInfo != null) {
-            final WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks> cbRef =
-                    new WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks>(
-                            RecentsActivity.this);
-            ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
-                @Override
-                public void run() {
-                    // Start listening for widget package changes if there is one bound
-                    RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks cb = cbRef.get();
-                    if (cb != null) {
-                        mAppWidgetHost.startListening(cb);
+        if (Constants.DebugFlags.App.EnableSearchBar) {
+            if (mSearchWidgetInfo != null) {
+                final WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks> cbRef =
+                        new WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks>(
+                                RecentsActivity.this);
+                ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+                    @Override
+                    public void run() {
+                        // Start listening for widget package changes if there is one bound
+                        RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks cb = cbRef.get();
+                        if (cb != null) {
+                            mAppWidgetHost.startListening(cb);
+                        }
                     }
-                }
-            });
+                });
+            }
         }
 
         // Animate the SystemUI scrim views
@@ -519,6 +533,15 @@
                 boolean hasRepKeyTimeElapsed = (SystemClock.elapsedRealtime() -
                         mLastTabKeyEventTime) > mConfig.altTabKeyDelay;
                 if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
+                    // As we iterate to the next/previous task, cancel any current/lagging window
+                    // transition animations
+                    if (mConfig.launchedToTaskId != -1) {
+                        SystemServicesProxy ssp =
+                                RecentsTaskLoader.getInstance().getSystemServicesProxy();
+                        ssp.cancelThumbnailTransition(getTaskId());
+                        ssp.cancelWindowTransition(mConfig.launchedToTaskId);
+                    }
+
                     // Focus the next task in the stack
                     final boolean backward = event.isShiftPressed();
                     mRecentsView.focusNextTask(!backward);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index dfe7e96..6646508 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -327,7 +327,8 @@
             taskStackBounds.set(0, topInset, windowWidth - rightInset, windowHeight);
         } else {
             // In portrait, the search bar appears on the top (which already has the inset)
-            taskStackBounds.set(0, searchBarBounds.bottom, windowWidth, windowHeight);
+            int top = searchBarBounds.isEmpty() ? topInset : 0;
+            taskStackBounds.set(0, searchBarBounds.bottom + top, windowWidth, windowHeight);
         }
     }
 
@@ -338,13 +339,18 @@
     public void getSearchBarBounds(int windowWidth, int windowHeight, int topInset,
             Rect searchBarSpaceBounds) {
         // Return empty rects if search is not enabled
-        int searchBarSize = searchBarSpaceHeightPx;
-        if (isLandscape && hasTransposedSearchBar) {
-            // In landscape, the search bar appears on the left
-            searchBarSpaceBounds.set(0, topInset, searchBarSize, windowHeight);
+        if (!Constants.DebugFlags.App.EnableSearchBar) {
+            searchBarSpaceBounds.set(0, 0, 0, 0);
+            return;
         } else {
-            // In portrait, the search bar appears on the top
-            searchBarSpaceBounds.set(0, topInset, windowWidth, topInset + searchBarSize);
+        int searchBarSize = searchBarSpaceHeightPx;
+            if (isLandscape && hasTransposedSearchBar) {
+                // In landscape, the search bar appears on the left
+                searchBarSpaceBounds.set(0, topInset, searchBarSize, windowHeight);
+            } else {
+                // In portrait, the search bar appears on the top
+                searchBarSpaceBounds.set(0, topInset, windowWidth, topInset + searchBarSize);
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index d5c9253..51bb00b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -59,6 +59,7 @@
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.app.AssistUtils;
@@ -321,6 +322,29 @@
         return mAm.isInHomeStack(taskId);
     }
 
+    /**
+     * Cancels the current window transtion to/from Recents for the given task id.
+     */
+    public void cancelWindowTransition(int taskId) {
+        if (mWm == null) return;
+
+        try {
+            WindowManagerGlobal.getWindowManagerService().cancelTaskWindowTransition(taskId);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void cancelThumbnailTransition(int taskId) {
+        if (mWm == null) return;
+
+        try {
+            WindowManagerGlobal.getWindowManagerService().cancelTaskThumbnailTransition(taskId);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
     /** Returns the top task thumbnail for the given task id */
     public Bitmap getTaskThumbnail(int taskId) {
         if (mAm == null) return null;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 947c19c..4214558 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents.views;
 
+import android.app.Activity;
 import android.app.ActivityOptions;
 import android.app.TaskStackBuilder;
 import android.content.Context;
@@ -25,6 +26,7 @@
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -35,6 +37,7 @@
 import android.view.View;
 import android.view.WindowInsets;
 import android.view.WindowManagerGlobal;
+import android.view.animation.AnimationUtils;
 import android.widget.FrameLayout;
 
 import com.android.internal.logging.MetricsLogger;
@@ -160,7 +163,7 @@
 
     /** Gets the next task in the stack - or if the last - the top task */
     public Task getNextTaskOrTopTask(Task taskToSearch) {
-        Task returnTask = null; 
+        Task returnTask = null;
         boolean found = false;
         List<TaskStackView> stackViews = getTaskStackViews();
         int stackCount = stackViews.size();
@@ -199,6 +202,7 @@
                 Task task = tv.getTask();
                 if (tv.isFocusedTask()) {
                     onTaskViewClicked(stackView, tv, stack, task, false);
+                    tv.unsetFocusedTask();
                     return true;
                 }
             }
@@ -368,7 +372,7 @@
                     searchBarSpaceBounds.right, searchBarSpaceBounds.bottom);
         }
 
-        // Layout each TaskStackView with the full width and height of the window since the 
+        // Layout each TaskStackView with the full width and height of the window since the
         // transition view is a child of that stack view
         List<TaskStackView> stackViews = getTaskStackViews();
         int stackCount = stackViews.size();
@@ -405,7 +409,7 @@
         // Get the first stack view
         List<TaskStackView> stackViews = getTaskStackViews();
         if (!stackViews.isEmpty()) {
-            stackViews.get(0).focusNextTask(forward, true);
+            stackViews.get(0).focusNextTask(forward);
         }
     }
 
@@ -501,6 +505,29 @@
     }
     /**** TaskStackView.TaskStackCallbacks Implementation ****/
 
+    /**
+     * Cancels any running window transitions for the launched task (the task animating into
+     * Recents).
+     */
+    private void cancelLaunchedTaskWindowTransitionWithDelay(final Task task, long delay) {
+        final SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+        if (mConfig.launchedToTaskId != -1 &&
+                mConfig.launchedToTaskId != task.key.id) {
+            final Handler handler = new Handler();
+            handler.postDelayed(new Runnable() {
+              @Override
+              public void run() {
+                  ssp.cancelThumbnailTransition(((Activity) getContext()).getTaskId());
+                  ssp.cancelWindowTransition(mConfig.launchedToTaskId);
+              }
+            }, delay);
+        }
+    }
+
+    private void cancelLaunchedTaskWindowTransition(final Task task) {
+        cancelLaunchedTaskWindowTransitionWithDelay(task, 0);
+    }
+
     @Override
     public void onTaskViewClicked(final TaskStackView stackView, final TaskView tv,
                                   final TaskStack stack, final Task task, final boolean lockToTask) {
@@ -532,6 +559,9 @@
         // Compute the thumbnail to scale up from
         final SystemServicesProxy ssp =
                 RecentsTaskLoader.getInstance().getSystemServicesProxy();
+               final long enterDuration =
+                       AnimationUtils.loadAnimation(getContext(), R.anim.recents_from_unknown_enter)
+                       .getDuration();
         ActivityOptions opts = null;
         if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
                 task.thumbnail.getHeight() > 0) {
@@ -541,6 +571,10 @@
                     boolean mTriggered = false;
                     @Override
                     public void onAnimationStarted() {
+                        // If we are launching into another task, cancel the previous task's
+                        // window transition
+                        cancelLaunchedTaskWindowTransitionWithDelay(task, enterDuration / 2);
+
                         if (!mTriggered) {
                             postDelayed(new Runnable() {
                                 @Override
@@ -552,7 +586,10 @@
                         }
                     }
                 };
+            } else {
+                cancelLaunchedTaskWindowTransitionWithDelay(task, enterDuration / 2);
             }
+
             if (tv != null) {
                 postDrawHeaderThumbnailTransitionRunnable(tv, offsetX, offsetY, transform,
                         animStartedListener);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 0068f84..571a9ef 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -218,6 +218,8 @@
             mUIDozeTrigger.resetTrigger();
         }
         mStackScroller.reset();
+
+        mStartEnterAnimationCompleted = false;
     }
 
     /** Requests that the views be synchronized with the model */
@@ -500,26 +502,34 @@
     }
 
     /** Focuses the task at the specified index in the stack */
-    void focusTask(int taskIndex, boolean scrollToNewPosition, final boolean animateFocusedState) {
+    void focusTask(int taskIndex, boolean scrollToNewPosition) {
         // Return early if the task is already focused
         if (taskIndex == mFocusedTaskIndex) return;
 
         if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
+            resetFocusedTask();
             mFocusedTaskIndex = taskIndex;
             mPrevAccessibilityFocusedIndex = taskIndex;
 
             // Focus the view if possible, otherwise, focus the view after we scroll into position
+            Runnable postScrollRunnable = null;
             final Task t = mStack.getTasks().get(mFocusedTaskIndex);
-            Runnable postScrollRunnable = new Runnable() {
-                @Override
-                public void run() {
-                    TaskView tv = getChildViewForTask(t);
-                    if (tv != null) {
-                        tv.setFocusedTask(animateFocusedState);
-                        tv.requestAccessibilityFocus();
+            final TaskView tv = getChildViewForTask(t);
+            if (tv != null) {
+                tv.setFocusedTask();
+                tv.requestAccessibilityFocus();
+            } else {
+                postScrollRunnable = new Runnable() {
+                    @Override
+                    public void run() {
+                        TaskView tv = getChildViewForTask(t);
+                        if (tv != null) {
+                            tv.setFocusedTask();
+                            tv.requestAccessibilityFocus();
+                        }
                     }
-                }
-            };
+                };
+            }
 
             // Scroll the view into position (just center it in the curve)
             if (scrollToNewPosition) {
@@ -574,17 +584,20 @@
      *                            the change in focus, as well as whether to scroll to fit the
      *                            task into view.
      */
-    public void focusNextTask(boolean forward, boolean animateFocusedState) {
+    public void focusNextTask(boolean forward) {
         // Find the next index to focus
         int numTasks = mStack.getTaskCount();
         if (numTasks == 0) return;
 
         int direction = (forward ? -1 : 1);
         int newIndex = mFocusedTaskIndex + direction;
-        if (newIndex >= 0 && newIndex <= (numTasks - 1)) {
-            newIndex = Math.max(0, Math.min(numTasks - 1, newIndex));
-            focusTask(newIndex, true, animateFocusedState);
+        if (newIndex < 0) {
+            newIndex = numTasks - 1;
+        } else if (newIndex > (numTasks - 1)) {
+            newIndex = 0;
         }
+
+        focusTask(newIndex, true);
     }
 
     /** Dismisses the focused task. */
@@ -660,14 +673,14 @@
             switch (action) {
                 case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
                     if (mPrevAccessibilityFocusedIndex > 0) {
-                        focusNextTask(true, false);
+                        focusNextTask(true);
                         return true;
                     }
                 }
                 break;
                 case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
                     if (mPrevAccessibilityFocusedIndex < mStack.getTaskCount() - 1) {
-                        focusNextTask(false, false);
+                        focusNextTask(false);
                         return true;
                     }
                 }
@@ -866,11 +879,9 @@
         // enter animation).
         if (mConfig.launchedWithAltTab) {
             if (mConfig.launchedFromAppWithThumbnail) {
-                focusTask(Math.max(0, mStack.getTaskCount() - 2), false,
-                        mConfig.launchedHasConfigurationChanged);
+                focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
             } else {
-                focusTask(Math.max(0, mStack.getTaskCount() - 1), false,
-                        mConfig.launchedHasConfigurationChanged);
+                focusTask(Math.max(0, mStack.getTaskCount() - 1), false);
             }
         }
 
@@ -945,7 +956,7 @@
                             0 <= mFocusedTaskIndex && mFocusedTaskIndex < tasks.size()) {
                         TaskView tv = getChildViewForTask(tasks.get(mFocusedTaskIndex));
                         if (tv != null) {
-                            tv.setFocusedTask(true);
+                            tv.setFocusedTask();
                         }
                     }
 
@@ -1401,7 +1412,7 @@
                 if (nextTv != null) {
                     // Focus the next task, and only animate the visible state if we are launched
                     // from Alt-Tab
-                    nextTv.setFocusedTask(mConfig.launchedWithAltTab);
+                    nextTv.setFocusedTask();
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index be618e2..25fb71e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -420,11 +420,11 @@
                     float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
                     if (vScroll > 0) {
                         if (mSv.ensureFocusedTask(true)) {
-                            mSv.focusNextTask(true, false);
+                            mSv.focusNextTask(true);
                         }
                     } else {
                         if (mSv.ensureFocusedTask(true)) {
-                            mSv.focusNextTask(false, false);
+                            mSv.focusNextTask(false);
                         }
                     }
                     return true;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index cbfe842..55aba75 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,7 +26,11 @@
 import android.view.View;
 import android.view.ViewOutlineProvider;
 import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.OvershootInterpolator;
 import android.widget.FrameLayout;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.recents.Constants;
@@ -47,7 +51,6 @@
         public void onTaskViewDismissed(TaskView tv);
         public void onTaskViewClipStateChanged(TaskView tv);
         public void onTaskViewFocusChanged(TaskView tv, boolean focused);
-
         public void onTaskResize(TaskView tv);
     }
 
@@ -75,6 +78,22 @@
     View mActionButtonView;
     TaskViewCallbacks mCb;
 
+    // Focus animation
+    float mHighlightProgress;
+    Paint mHighlightPaint = new Paint();
+    int mHighlightColor = 0xff009688;
+    int mHighlightAlpha = 0x50;
+    static Interpolator sHighlightInInterpolator = new OvershootInterpolator(2);
+    static Interpolator sHighlightInRadiusInterpolator = new DecelerateInterpolator();
+    static Interpolator sHighlightOutInterpolator = new DecelerateInterpolator();
+    ObjectAnimator mHighlightAnimator;
+    static long sHighlightInDurationMs = 350;
+    static long sHighlightOutDurationMs = 200;
+    float mHighlightInCircleRadiusProgress;
+    int mHighlightInFillAlpha;
+    int mHighlightInCircleAlpha;
+    int mHighlightOutFillAlpha;
+
     // Optimizations
     ValueAnimator.AnimatorUpdateListener mUpdateDimListener =
             new ValueAnimator.AnimatorUpdateListener() {
@@ -84,7 +103,6 @@
                 }
             };
 
-
     public TaskView(Context context) {
         this(context, null);
     }
@@ -109,6 +127,11 @@
             setBackground(new FakeShadowDrawable(context.getResources(), mConfig));
         }
         setOutlineProvider(mViewBounds);
+
+        mHighlightAnimator = ObjectAnimator.ofFloat(this, "highlightProgress", 1f);
+        mHighlightColor =
+                context.getResources().getColor(R.color.status_bar_recents_highlight_color);
+        mHighlightPaint.setColor(mHighlightColor);
     }
 
     /** Set callback */
@@ -184,7 +207,7 @@
     }
 
     void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration,
-                                             ValueAnimator.AnimatorUpdateListener updateCallback) {
+            ValueAnimator.AnimatorUpdateListener updateCallback) {
         // Apply the transform
         toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator, false,
                 !mConfig.fakeShadows, updateCallback);
@@ -234,10 +257,12 @@
         fromTransform.alpha = 0f;
     }
 
-    /** Prepares this task view for the enter-recents animations.  This is called earlier in the
-     * first layout because the actual animation into recents may take a long time. */
+    /**
+     * Prepares this task view for the enter-recents animations. This is called earlier in the
+     * first layout because the actual animation into recents may take a long time.
+     */
     void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask,
-                                             boolean occludesLaunchTarget, int offscreenY) {
+            boolean occludesLaunchTarget, int offscreenY) {
         int initialDim = getDim();
         if (mConfig.launchedHasConfigurationChanged) {
             // Just load the views as-is
@@ -298,7 +323,8 @@
             } else {
                 // Animate the task up if it was occluding the launch target
                 if (ctx.currentTaskOccludesLaunchTarget) {
-                    setTranslationY(transform.translationY + mConfig.taskViewAffiliateGroupEnterOffsetPx);
+                    setTranslationY(transform.translationY
+                            + mConfig.taskViewAffiliateGroupEnterOffsetPx);
                     setAlpha(0f);
                     animate().alpha(1f)
                             .translationY(transform.translationY)
@@ -423,13 +449,15 @@
             // If this is another view in the task grouping and is in front of the launch task,
             // animate it away first
             if (occludesLaunchTarget) {
-                animate().alpha(0f)
-                    .translationY(getTranslationY() + mConfig.taskViewAffiliateGroupEnterOffsetPx)
-                    .setStartDelay(0)
-                    .setUpdateListener(null)
-                    .setInterpolator(mConfig.fastOutLinearInInterpolator)
-                    .setDuration(mConfig.taskViewExitToAppDuration)
-                    .start();
+                animate()
+                        .alpha(0f)
+                        .translationY(
+                                getTranslationY() + mConfig.taskViewAffiliateGroupEnterOffsetPx)
+                        .setStartDelay(0)
+                        .setUpdateListener(null)
+                        .setInterpolator(mConfig.fastOutLinearInInterpolator)
+                        .setDuration(mConfig.taskViewExitToAppDuration)
+                        .start();
             }
         }
     }
@@ -440,23 +468,23 @@
         setClipViewInStack(false);
 
         animate().translationX(mConfig.taskViewRemoveAnimTranslationXPx)
-            .alpha(0f)
-            .setStartDelay(delay)
-            .setUpdateListener(null)
-            .setInterpolator(mConfig.fastOutSlowInInterpolator)
-            .setDuration(mConfig.taskViewRemoveAnimDuration)
-            .withEndAction(new Runnable() {
-                @Override
-                public void run() {
-                    if (r != null) {
-                        r.run();
-                    }
+                .alpha(0f)
+                .setStartDelay(delay)
+                .setUpdateListener(null)
+                .setInterpolator(mConfig.fastOutSlowInInterpolator)
+                .setDuration(mConfig.taskViewRemoveAnimDuration)
+                .withEndAction(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (r != null) {
+                            r.run();
+                        }
 
-                    // Re-enable clipping with the stack (we will reuse this view)
-                    setClipViewInStack(true);
-                }
-            })
-            .start();
+                        // Re-enable clipping with the stack (we will reuse this view)
+                        setClipViewInStack(true);
+                    }
+                })
+                .start();
     }
 
     /** Enables/disables handling touch on this task view. */
@@ -469,12 +497,18 @@
         mHeaderView.startNoUserInteractionAnimation();
     }
 
-    /** Mark this task view that the user does has not interacted with the stack after a certain time. */
+    /**
+     * Mark this task view that the user does has not interacted with the stack after a certain
+     * time.
+     */
     void setNoUserInteractionState() {
         mHeaderView.setNoUserInteractionState();
     }
 
-    /** Resets the state tracking that the user has not interacted with the stack after a certain time. */
+    /**
+     * Resets the state tracking that the user has not interacted with the stack after a certain
+     * time.
+     */
     void resetNoUserInteractionState() {
         mHeaderView.resetNoUserInteractionState();
     }
@@ -511,6 +545,47 @@
         }
     }
 
+    @Override
+    public void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        if (mIsFocused) {
+            final int x = getWidth() / 2;
+            final int y = getHeight() / 2;
+            final float hypot = (float) Math.hypot(x, y);
+            final float radius = hypot * mHighlightInCircleRadiusProgress;
+
+            mHighlightPaint.setAlpha(mHighlightInFillAlpha);
+            canvas.drawRect(0, 0, getWidth(), getHeight(), mHighlightPaint);
+
+            mHighlightPaint.setAlpha(mHighlightInCircleAlpha);
+            canvas.drawCircle(x, y, radius, mHighlightPaint);
+        } else {
+            mHighlightPaint.setAlpha(mHighlightOutFillAlpha);
+            canvas.drawRect(0, 0, getWidth(), getHeight(), mHighlightPaint);
+        }
+    }
+
+    public void setHighlightProgress(float progress) {
+        mHighlightProgress = progress;
+        if (mIsFocused) {
+            final float interpolatedProgress = sHighlightInInterpolator.getInterpolation(progress);
+            mHighlightInCircleRadiusProgress =
+                    0.5f + sHighlightInRadiusInterpolator.getInterpolation(progress);
+            mHighlightInCircleAlpha = (int) (mHighlightAlpha * interpolatedProgress);
+            mHighlightInFillAlpha =
+                    (mHighlightAlpha / 4) + (int) ((mHighlightAlpha / 2) * interpolatedProgress);
+        } else {
+            final float interpolatedProgress = sHighlightOutInterpolator.getInterpolation(progress);
+            mHighlightOutFillAlpha = (int) (mHighlightAlpha * (1 - interpolatedProgress));
+        }
+
+        invalidate();
+    }
+
+    public float getHighlightProgress() {
+        return mHighlightProgress;
+    }
+
     /** Sets the current task progress. */
     public void setTaskProgress(float p) {
         mTaskProgress = p;
@@ -582,12 +657,13 @@
      * if the view is not currently visible, or we are in touch state (where we still want to keep
      * track of focus).
      */
-    public void setFocusedTask(boolean animateFocusedState) {
-        mIsFocused = true;
-        if (mFocusAnimationsEnabled) {
-            // Focus the header bar
-            mHeaderView.onTaskViewFocusChanged(true, animateFocusedState);
+    public void setFocusedTask() {
+        if (mIsFocused) {
+            return;
         }
+        mIsFocused = true;
+
+        performFocusAnimation();
         // Update the thumbnail alpha with the focus
         mThumbnailView.onFocusChanged(true);
         // Call the callback
@@ -603,14 +679,31 @@
         invalidate();
     }
 
+    private void performFocusAnimation() {
+        if (mFocusAnimationsEnabled) {
+            // Focus the header bar
+            mHeaderView.onTaskViewFocusChanged(true);
+
+            mHighlightAnimator.setDuration(sHighlightInDurationMs);
+            mHighlightAnimator.start();
+        }
+    }
+
     /**
      * Unsets the focused task explicitly.
      */
     void unsetFocusedTask() {
+        if (!mIsFocused) {
+            return;
+        }
+
         mIsFocused = false;
         if (mFocusAnimationsEnabled) {
             // Un-focus the header bar
-            mHeaderView.onTaskViewFocusChanged(false, true);
+            mHeaderView.onTaskViewFocusChanged(false);
+
+            mHighlightAnimator.setDuration(sHighlightOutDurationMs);
+            mHighlightAnimator.start();
         }
 
         // Update the thumbnail alpha with the focus
@@ -637,16 +730,16 @@
      * Returns whether we have explicitly been focused.
      */
     public boolean isFocusedTask() {
-        return mIsFocused || isFocused();
+        return mIsFocused;
     }
 
     /** Enables all focus animations. */
     void enableFocusAnimations() {
         boolean wasFocusAnimationsEnabled = mFocusAnimationsEnabled;
         mFocusAnimationsEnabled = true;
-        if (mIsFocused && !wasFocusAnimationsEnabled) {
+        if (mIsFocused) {
             // Re-notify the header if we were focused and animations were not previously enabled
-            mHeaderView.onTaskViewFocusChanged(true, true);
+            performFocusAnimation();
         }
     }
 
@@ -718,7 +811,7 @@
     /**** View.OnClickListener Implementation ****/
 
     @Override
-     public void onClick(final View v) {
+    public void onClick(final View v) {
         final TaskView tv = this;
         final boolean delayViewClick = (v != this) && (v != mActionButtonView);
         if (delayViewClick) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 6db4020..cfe5a4e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -42,6 +42,7 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
+
 import com.android.systemui.R;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
@@ -50,13 +51,16 @@
 import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.Task;
 
-
 /* The task bar view */
 public class TaskViewHeader extends FrameLayout {
 
     RecentsConfiguration mConfig;
     private SystemServicesProxy mSsp;
 
+    Task mTask;
+    boolean mIsFocused;
+    float mFocusProgress;
+
     // Header views
     ImageView mMoveTaskButton;
     ImageView mDismissButton;
@@ -71,7 +75,7 @@
     Drawable mDarkDismissDrawable;
     RippleDrawable mBackground;
     GradientDrawable mBackgroundColorDrawable;
-    AnimatorSet mFocusAnimator;
+    ValueAnimator mFocusAnimator;
     String mDismissContentDescription;
 
     // Static highlight that we draw at the top of each view
@@ -123,6 +127,8 @@
             sHighlightPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
             sHighlightPaint.setAntiAlias(true);
         }
+
+        mFocusAnimator = ObjectAnimator.ofFloat(this, "focusProgress", 1f);
     }
 
     @Override
@@ -180,14 +186,9 @@
         }
     }
 
-    /** Returns the secondary color for a primary color. */
-    int getSecondaryColor(int primaryColor, boolean useLightOverlayColor) {
-        int overlayColor = useLightOverlayColor ? Color.WHITE : Color.BLACK;
-        return Utilities.getColorWithOverlay(primaryColor, overlayColor, 0.8f);
-    }
-
     /** Binds the bar view to the task */
     public void rebindToTask(Task t) {
+        mTask = t;
         // If an activity icon is defined, then we use that as the primary icon to show in the bar,
         // otherwise, we fall back to the application icon
         if (t.activityIcon != null) {
@@ -256,6 +257,12 @@
 
     /** Unbinds the bar view from the task */
     void unbindFromTask() {
+        mBackground.jumpToCurrentState();
+
+        if (mFocusAnimator != null) {
+            mFocusAnimator.cancel();
+        }
+
         mApplicationIcon.setImageDrawable(null);
     }
 
@@ -286,7 +293,10 @@
         }
     }
 
-    /** Mark this task view that the user does has not interacted with the stack after a certain time. */
+    /**
+     * Mark this task view that the user does has not interacted with the stack after a certain
+     * time.
+     */
     void setNoUserInteractionState() {
         if (mDismissButton.getVisibility() != View.VISIBLE) {
             mDismissButton.animate().cancel();
@@ -295,7 +305,10 @@
         }
     }
 
-    /** Resets the state tracking that the user has not interacted with the stack after a certain time. */
+    /**
+     * Resets the state tracking that the user has not interacted with the stack after a certain
+     * time.
+     */
     void resetNoUserInteractionState() {
         mDismissButton.setVisibility(View.INVISIBLE);
     }
@@ -330,92 +343,43 @@
         setLayerType(LAYER_TYPE_NONE, null);
     }
 
+    public void setFocusProgress(float progress) {
+        mFocusProgress = progress;
+        final ArgbEvaluator colorEvaluator = new ArgbEvaluator();
+        int desaturatedColor = calculateDesaurateColor(mBackgroundColor);
+        int color = (Integer) colorEvaluator.evaluate(progress, mBackgroundColor,
+                mIsFocused ? desaturatedColor : mTask.colorPrimary);
+        mBackgroundColorDrawable.setColor(color);
+        mBackgroundColor = color;
+
+        TaskViewHeader.this.setTranslationZ((mIsFocused ? progress : (1 - progress)) * 4);
+    }
+
+    private int calculateDesaurateColor(int saturatedColor) {
+        final float red = 0.2126f * Color.red(saturatedColor);
+        final float green = 0.7152f * Color.green(saturatedColor);
+        final float blue = 0.0722f * Color.blue(saturatedColor);
+        final int sum = (int) (red + green + blue);
+
+        return Color.argb(255, sum, sum, sum);
+    }
+
+    public float getFocusProgress() {
+        return mFocusProgress;
+    }
+
     /** Notifies the associated TaskView has been focused. */
-    void onTaskViewFocusChanged(boolean focused, boolean animateFocusedState) {
-        // If we are not animating the visible state, just return
-        if (!animateFocusedState) return;
+    void onTaskViewFocusChanged(final boolean focused) {
+        mIsFocused = focused;
 
-        boolean isRunning = false;
-        if (mFocusAnimator != null) {
-            isRunning = mFocusAnimator.isRunning();
-            Utilities.cancelAnimationWithoutCallbacks(mFocusAnimator);
-        }
-
-        if (focused) {
-            int currentColor = mBackgroundColor;
-            int secondaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
-            int[][] states = new int[][] {
-                    new int[] {},
-                    new int[] { android.R.attr.state_enabled },
-                    new int[] { android.R.attr.state_pressed }
-            };
-            int[] newStates = new int[]{
-                    0,
-                    android.R.attr.state_enabled,
-                    android.R.attr.state_pressed
-            };
-            int[] colors = new int[] {
-                    currentColor,
-                    secondaryColor,
-                    secondaryColor
-            };
-            mBackground.setColor(new ColorStateList(states, colors));
-            mBackground.setState(newStates);
-            // Pulse the background color
-            int lightPrimaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
-            ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
-                    currentColor, lightPrimaryColor);
-            backgroundColor.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    mBackground.setState(new int[]{});
-                }
-            });
-            backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    int color = (int) animation.getAnimatedValue();
-                    mBackgroundColorDrawable.setColor(color);
-                    mBackgroundColor = color;
-                }
-            });
-            backgroundColor.setRepeatCount(ValueAnimator.INFINITE);
-            backgroundColor.setRepeatMode(ValueAnimator.REVERSE);
-            // Pulse the translation
-            ObjectAnimator translation = ObjectAnimator.ofFloat(this, "translationZ", 15f);
-            translation.setRepeatCount(ValueAnimator.INFINITE);
-            translation.setRepeatMode(ValueAnimator.REVERSE);
-
-            mFocusAnimator = new AnimatorSet();
-            mFocusAnimator.playTogether(backgroundColor, translation);
-            mFocusAnimator.setStartDelay(150);
-            mFocusAnimator.setDuration(750);
-            mFocusAnimator.start();
-        } else {
-            if (isRunning) {
-                // Restore the background color
-                int currentColor = mBackgroundColor;
-                ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
-                        currentColor, mCurrentPrimaryColor);
-                backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-                    @Override
-                    public void onAnimationUpdate(ValueAnimator animation) {
-                        int color = (int) animation.getAnimatedValue();
-                        mBackgroundColorDrawable.setColor(color);
-                        mBackgroundColor = color;
-                    }
-                });
-                // Restore the translation
-                ObjectAnimator translation = ObjectAnimator.ofFloat(this, "translationZ", 0f);
-
-                mFocusAnimator = new AnimatorSet();
-                mFocusAnimator.playTogether(backgroundColor, translation);
-                mFocusAnimator.setDuration(150);
-                mFocusAnimator.start();
-            } else {
-                mBackground.setState(new int[] {});
-                setTranslationZ(0f);
-            }
-        }
+        mFocusAnimator.setDuration(
+                mIsFocused ?
+                        TaskView.sHighlightInDurationMs :
+                        TaskView.sHighlightOutDurationMs);
+        mFocusAnimator.setInterpolator(
+                mIsFocused ?
+                        TaskView.sHighlightInRadiusInterpolator :
+                        TaskView.sHighlightOutInterpolator);
+        mFocusAnimator.start();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 117a7d3..d5862bc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -18,7 +18,9 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapShader;
@@ -32,6 +34,11 @@
 import android.graphics.Shader;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.OvershootInterpolator;
+
+import com.android.systemui.R;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.Task;
@@ -57,8 +64,8 @@
     // Thumbnail alpha
     float mThumbnailAlpha;
     ValueAnimator mThumbnailAlphaAnimator;
-    ValueAnimator.AnimatorUpdateListener mThumbnailAlphaUpdateListener
-            = new ValueAnimator.AnimatorUpdateListener() {
+    ValueAnimator.AnimatorUpdateListener mThumbnailAlphaUpdateListener =
+            new ValueAnimator.AnimatorUpdateListener() {
         @Override
         public void onAnimationUpdate(ValueAnimator animation) {
             mThumbnailAlpha = (float) animation.getAnimatedValue();
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 0205a20..38e6a32 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -69,7 +69,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
-import android.util.Log;
+import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
@@ -93,9 +93,11 @@
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 
 import libcore.io.Streams;
 import libcore.util.Objects;
@@ -708,40 +710,35 @@
         mTempInputDevicesChangedListenersToNotify.clear();
 
         // Check for missing keyboard layouts.
-        if (mNotificationManager != null) {
-            final int numFullKeyboards = mTempFullKeyboards.size();
-            boolean missingLayoutForExternalKeyboard = false;
-            boolean missingLayoutForExternalKeyboardAdded = false;
-            boolean multipleMissingLayoutsForExternalKeyboardsAdded = false;
-            InputDevice keyboardMissingLayout = null;
-            synchronized (mDataStore) {
-                for (int i = 0; i < numFullKeyboards; i++) {
-                    final InputDevice inputDevice = mTempFullKeyboards.get(i);
-                    final String layout =
-                            getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
-                    if (layout == null) {
-                        missingLayoutForExternalKeyboard = true;
-                        if (i < numFullKeyboardsAdded) {
-                            missingLayoutForExternalKeyboardAdded = true;
-                            if (keyboardMissingLayout == null) {
-                                keyboardMissingLayout = inputDevice;
-                            } else {
-                                multipleMissingLayoutsForExternalKeyboardsAdded = true;
-                            }
-                        }
+        List<InputDevice> keyboardsMissingLayout = new ArrayList<>();
+        final int numFullKeyboards = mTempFullKeyboards.size();
+        synchronized (mDataStore) {
+            for (int i = 0; i < numFullKeyboards; i++) {
+                final InputDevice inputDevice = mTempFullKeyboards.get(i);
+                String layout =
+                    getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
+                if (layout == null) {
+                    layout = getDefaultKeyboardLayout(inputDevice);
+                    if (layout != null) {
+                        setCurrentKeyboardLayoutForInputDevice(
+                                inputDevice.getIdentifier(), layout);
                     }
                 }
+                if (layout == null) {
+                    keyboardsMissingLayout.add(inputDevice);
+                }
             }
-            if (missingLayoutForExternalKeyboard) {
-                if (missingLayoutForExternalKeyboardAdded) {
-                    if (multipleMissingLayoutsForExternalKeyboardsAdded) {
-                        // We have more than one keyboard missing a layout, so drop the
-                        // user at the generic input methods page so they can pick which
-                        // one to set.
-                        showMissingKeyboardLayoutNotification(null);
-                    } else {
-                        showMissingKeyboardLayoutNotification(keyboardMissingLayout);
-                    }
+        }
+
+        if (mNotificationManager != null) {
+            if (!keyboardsMissingLayout.isEmpty()) {
+                if (keyboardsMissingLayout.size() > 1) {
+                    // We have more than one keyboard missing a layout, so drop the
+                    // user at the generic input methods page so they can pick which
+                    // one to set.
+                    showMissingKeyboardLayoutNotification(null);
+                } else {
+                    showMissingKeyboardLayoutNotification(keyboardsMissingLayout.get(0));
                 }
             } else if (mKeyboardLayoutNotificationShown) {
                 hideMissingKeyboardLayoutNotification();
@@ -750,6 +747,78 @@
         mTempFullKeyboards.clear();
     }
 
+    private String getDefaultKeyboardLayout(final InputDevice d) {
+        final Locale systemLocale = mContext.getResources().getConfiguration().locale;
+        // If our locale doesn't have a language for some reason, then we don't really have a
+        // reasonable default.
+        if (TextUtils.isEmpty(systemLocale.getLanguage())) {
+            return null;
+        }
+        final List<KeyboardLayout> layouts = new ArrayList<>();
+        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
+            @Override
+            public void visitKeyboardLayout(Resources resources,
+                    int keyboardLayoutResId, KeyboardLayout layout) {
+                // Only select a default when we know the layout is appropriate. For now, this
+                // means its a custom layout for a specific keyboard.
+                if (layout.getVendorId() != d.getVendorId()
+                        || layout.getProductId() != d.getProductId()) {
+                    return;
+                }
+                for (Locale l : layout.getLocales()) {
+                    if (isCompatibleLocale(systemLocale, l)) {
+                        layouts.add(layout);
+                        break;
+                    }
+                }
+            }
+        });
+
+        if (layouts.isEmpty()) {
+            return null;
+        }
+
+        // First sort so that ones with higher priority are listed at the top
+        Collections.sort(layouts);
+        // Next we want to try to find an exact match of language, country and variant.
+        final int N = layouts.size();
+        for (int i = 0; i < N; i++) {
+            KeyboardLayout layout = layouts.get(i);
+            for (Locale l : layout.getLocales()) {
+                if (l.getCountry().equals(systemLocale.getCountry())
+                        && l.getVariant().equals(systemLocale.getVariant())) {
+                    return layout.getDescriptor();
+                }
+            }
+        }
+        // Then try an exact match of language and country
+        for (int i = 0; i < N; i++) {
+            KeyboardLayout layout = layouts.get(i);
+            for (Locale l : layout.getLocales()) {
+                if (l.getCountry().equals(systemLocale.getCountry())) {
+                    return layout.getDescriptor();
+                }
+            }
+        }
+
+        // Give up and just use the highest priority layout with matching language
+        return layouts.get(0).getDescriptor();
+    }
+
+    private static boolean isCompatibleLocale(Locale systemLocale, Locale keyboardLocale) {
+        // Different languages are never compatible
+        if (!systemLocale.getLanguage().equals(keyboardLocale.getLanguage())) {
+            return false;
+        }
+        // If both the system and the keyboard layout have a country specifier, they must be equal.
+        if (!TextUtils.isEmpty(systemLocale.getCountry())
+                && !TextUtils.isEmpty(keyboardLocale.getCountry())
+                && !systemLocale.getCountry().equals(keyboardLocale.getCountry())) {
+            return false;
+        }
+        return true;
+    }
+
     @Override // Binder call & native callback
     public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
             int surfaceRotation) {
@@ -899,9 +968,9 @@
         final HashSet<String> availableKeyboardLayouts = new HashSet<String>();
         visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
             @Override
-            public void visitKeyboardLayout(Resources resources, String descriptor, String label,
-                    String collection, int keyboardLayoutResId, int priority) {
-                availableKeyboardLayouts.add(descriptor);
+            public void visitKeyboardLayout(Resources resources,
+                    int keyboardLayoutResId, KeyboardLayout layout) {
+                availableKeyboardLayouts.add(layout.getDescriptor());
             }
         });
         synchronized (mDataStore) {
@@ -933,9 +1002,35 @@
         final ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
         visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
             @Override
-            public void visitKeyboardLayout(Resources resources, String descriptor, String label,
-                    String collection, int keyboardLayoutResId, int priority) {
-                list.add(new KeyboardLayout(descriptor, label, collection, priority));
+            public void visitKeyboardLayout(Resources resources,
+                    int keyboardLayoutResId, KeyboardLayout layout) {
+                list.add(layout);
+            }
+        });
+        return list.toArray(new KeyboardLayout[list.size()]);
+    }
+
+    @Override
+    public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
+            final InputDeviceIdentifier identifier) {
+        final ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
+        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
+            boolean mHasSeenDeviceSpecificLayout;
+
+            @Override
+            public void visitKeyboardLayout(Resources resources,
+                    int keyboardLayoutResId, KeyboardLayout layout) {
+                if (layout.getVendorId() == identifier.getVendorId()
+                        && layout.getProductId() == identifier.getProductId()) {
+                    if (!mHasSeenDeviceSpecificLayout) {
+                        mHasSeenDeviceSpecificLayout = true;
+                        list.clear();
+                    }
+                    list.add(layout);
+                } else if (layout.getVendorId() == -1 && layout.getProductId() == -1
+                        && !mHasSeenDeviceSpecificLayout) {
+                    list.add(layout);
+                }
             }
         });
         return list.toArray(new KeyboardLayout[list.size()]);
@@ -950,13 +1045,13 @@
         final KeyboardLayout[] result = new KeyboardLayout[1];
         visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
             @Override
-            public void visitKeyboardLayout(Resources resources, String descriptor,
-                    String label, String collection, int keyboardLayoutResId, int priority) {
-                result[0] = new KeyboardLayout(descriptor, label, collection, priority);
+            public void visitKeyboardLayout(Resources resources,
+                    int keyboardLayoutResId, KeyboardLayout layout) {
+                result[0] = layout;
             }
         });
         if (result[0] == null) {
-            Log.w(TAG, "Could not get keyboard layout with descriptor '"
+            Slog.w(TAG, "Could not get keyboard layout with descriptor '"
                     + keyboardLayoutDescriptor + "'.");
         }
         return result[0];
@@ -997,7 +1092,7 @@
 
         int configResId = metaData.getInt(InputManager.META_DATA_KEYBOARD_LAYOUTS);
         if (configResId == 0) {
-            Log.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS
+            Slog.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS
                     + "' on receiver " + receiver.packageName + "/" + receiver.name);
             return;
         }
@@ -1034,8 +1129,16 @@
                             int keyboardLayoutResId = a.getResourceId(
                                     com.android.internal.R.styleable.KeyboardLayout_keyboardLayout,
                                     0);
+                            String languageTags = a.getString(
+                                    com.android.internal.R.styleable.KeyboardLayout_locale);
+                            Locale[] locales = getLocalesFromLanguageTags(languageTags);
+                            int vid = a.getInt(
+                                    com.android.internal.R.styleable.KeyboardLayout_vendorId, -1);
+                            int pid = a.getInt(
+                                    com.android.internal.R.styleable.KeyboardLayout_productId, -1);
+
                             if (name == null || label == null || keyboardLayoutResId == 0) {
-                                Log.w(TAG, "Missing required 'name', 'label' or 'keyboardLayout' "
+                                Slog.w(TAG, "Missing required 'name', 'label' or 'keyboardLayout' "
                                         + "attributes in keyboard layout "
                                         + "resource from receiver "
                                         + receiver.packageName + "/" + receiver.name);
@@ -1043,15 +1146,18 @@
                                 String descriptor = KeyboardLayoutDescriptor.format(
                                         receiver.packageName, receiver.name, name);
                                 if (keyboardName == null || name.equals(keyboardName)) {
-                                    visitor.visitKeyboardLayout(resources, descriptor,
-                                            label, collection, keyboardLayoutResId, priority);
+                                    KeyboardLayout layout = new KeyboardLayout(
+                                            descriptor, label, collection, priority,
+                                            locales, vid, pid);
+                                    visitor.visitKeyboardLayout(
+                                            resources, keyboardLayoutResId, layout);
                                 }
                             }
                         } finally {
                             a.recycle();
                         }
                     } else {
-                        Log.w(TAG, "Skipping unrecognized element '" + element
+                        Slog.w(TAG, "Skipping unrecognized element '" + element
                                 + "' in keyboard layout resource from receiver "
                                 + receiver.packageName + "/" + receiver.name);
                     }
@@ -1060,11 +1166,23 @@
                 parser.close();
             }
         } catch (Exception ex) {
-            Log.w(TAG, "Could not parse keyboard layout resource from receiver "
+            Slog.w(TAG, "Could not parse keyboard layout resource from receiver "
                     + receiver.packageName + "/" + receiver.name, ex);
         }
     }
 
+    private static Locale[] getLocalesFromLanguageTags(String languageTags) {
+        if (TextUtils.isEmpty(languageTags)) {
+            return new Locale[0];
+        }
+        String[] tags = languageTags.split("\\|");
+        Locale[] locales = new Locale[tags.length];
+        for (int i = 0; i < tags.length; i++) {
+            locales[i] = Locale.forLanguageTag(tags[i]);
+        }
+        return locales;
+    }
+
     /**
      * Builds a layout descriptor for the vendor/product. This returns the
      * descriptor for ids that aren't useful (such as the default 0, 0).
@@ -1130,7 +1248,7 @@
     }
 
     @Override // Binder call
-    public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
+    public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
         String key = getLayoutDescriptor(identifier);
         synchronized (mDataStore) {
             String[] layouts = mDataStore.getKeyboardLayouts(key);
@@ -1660,10 +1778,10 @@
         final String[] result = new String[2];
         visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
             @Override
-            public void visitKeyboardLayout(Resources resources, String descriptor, String label,
-                    String collection, int keyboardLayoutResId, int priority) {
+            public void visitKeyboardLayout(Resources resources,
+                    int keyboardLayoutResId, KeyboardLayout layout) {
                 try {
-                    result[0] = descriptor;
+                    result[0] = layout.getDescriptor();
                     result[1] = Streams.readFully(new InputStreamReader(
                             resources.openRawResource(keyboardLayoutResId)));
                 } catch (IOException ex) {
@@ -1672,7 +1790,7 @@
             }
         });
         if (result[0] == null) {
-            Log.w(TAG, "Could not get keyboard layout with descriptor '"
+            Slog.w(TAG, "Could not get keyboard layout with descriptor '"
                     + keyboardLayoutDescriptor + "'.");
             return null;
         }
@@ -1815,8 +1933,8 @@
     }
 
     private interface KeyboardLayoutVisitor {
-        void visitKeyboardLayout(Resources resources, String descriptor, String label,
-                String collection, int keyboardLayoutResId, int priority);
+        void visitKeyboardLayout(Resources resources,
+                int keyboardLayoutResId, KeyboardLayout layout);
     }
 
     private final class InputDevicesChangedListenerRecord implements DeathRecipient {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0c3cf65..daf28cf 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -107,6 +107,21 @@
         }
     }
 
+    /**
+     * Cancels any running app transitions associated with the task.
+     */
+    void cancelTaskWindowTransition() {
+        for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
+            mAppTokens.get(activityNdx).mAppAnimator.clearAnimation();
+        }
+    }
+
+    void cancelTaskThumbnailTransition() {
+        for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
+            mAppTokens.get(activityNdx).mAppAnimator.clearThumbnail();
+        }
+    }
+
     boolean showForAllUsers() {
         final int tokensCount = mAppTokens.size();
         return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 71bbdb6..15ae804 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5216,6 +5216,26 @@
         }
     }
 
+    @Override
+    public void cancelTaskWindowTransition(int taskId) {
+        synchronized (mWindowMap) {
+            Task task = mTaskIdToTask.get(taskId);
+            if (task != null) {
+                task.cancelTaskWindowTransition();
+            }
+        }
+    }
+
+    @Override
+    public void cancelTaskThumbnailTransition(int taskId) {
+        synchronized (mWindowMap) {
+            Task task = mTaskIdToTask.get(taskId);
+            if (task != null) {
+                task.cancelTaskThumbnailTransition();
+            }
+        }
+    }
+
     public void addTask(int taskId, int stackId, boolean toTop) {
         synchronized (mWindowMap) {
             if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 82012c1..17db317 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -511,4 +511,12 @@
         // TODO Auto-generated method stub
         return null;
     }
+
+    @Override
+    public void cancelTaskWindowTransition(int taskId) {
+    }
+
+    @Override
+    public void cancelTaskThumbnailTransition(int taskId) {
+    }
 }