Light navigation bar support (1/2)

Test: Open an app that has this flag set.

Test: android.systemui.cts.LightBarTests

Bug: 29058491
Change-Id: Idaff65fdd5c59b68ae9920726c9ea50b53f96675
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
index f653371..d54e33f 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
@@ -26,7 +26,7 @@
 
     public static final String ACTION = "com.android.systemui.action.PLUGIN_NAV_BUTTON";
 
-    public static final int VERSION = 1;
+    public static final int VERSION = 2;
 
     /**
      * Returns a view in the nav bar.  If the id is set "back", "home", "recent_apps", "menu",
@@ -38,7 +38,6 @@
      * Interface for button actions.
      */
     interface ButtonInterface {
-        void setImageResource(@DrawableRes int resId);
 
         void setImageDrawable(@Nullable Drawable drawable);
 
@@ -47,5 +46,7 @@
         void setVertical(boolean vertical);
 
         void setCarMode(boolean carMode);
+
+        void setDarkIntensity(float intensity);
     }
 }
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..0a6074b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..64bc40a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..fb44f22a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..a665e23
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..4f65660
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..c57face
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..bbaab44
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..dba0040
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..2b64b80
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..151a3c0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..3456a97
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..5383215
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..3a22912
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..c7e4731
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..d2949f3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..06e4c26
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..1c855c4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..371a84d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..360ed77
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..96cecc9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..9ff9825
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..e505f5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..472c55b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..c04d650
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..0f6d206
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..58bf920
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..f47533ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..f299d97
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..84d6dc8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..d813bc7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..30e8782
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..83fc662
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..71101a1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..4a477ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..bc24c00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
index 4d9ca88..3345f61 100644
--- a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
+++ b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
@@ -21,5 +21,5 @@
         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"/>
+        android:fillColor="?attr/singleToneColor"/>
 </vector>
diff --git a/packages/SystemUI/res/layout/back.xml b/packages/SystemUI/res/layout/back.xml
index d256622..4e8726b 100644
--- a/packages/SystemUI/res/layout/back.xml
+++ b/packages/SystemUI/res/layout/back.xml
@@ -21,7 +21,6 @@
     android:layout_width="@dimen/navigation_key_width"
     android:layout_height="match_parent"
     android:layout_weight="0"
-    android:src="@drawable/ic_sysbar_back"
     systemui:keyCode="4"
     android:scaleType="center"
     android:contentDescription="@string/accessibility_back"
diff --git a/packages/SystemUI/res/layout/home.xml b/packages/SystemUI/res/layout/home.xml
index f11592d..9586327 100644
--- a/packages/SystemUI/res/layout/home.xml
+++ b/packages/SystemUI/res/layout/home.xml
@@ -20,7 +20,6 @@
     android:layout_width="@dimen/navigation_key_width"
     android:layout_height="match_parent"
     android:layout_weight="0"
-    android:src="@drawable/ic_sysbar_home"
     systemui:keyCode="3"
     android:scaleType="center"
     android:contentDescription="@string/accessibility_home"
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 90b74d0..5e85ba0 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -25,7 +25,6 @@
         android:layout_width="@dimen/navigation_extra_key_width"
         android:layout_height="match_parent"
         android:layout_marginEnd="2dp"
-        android:src="@drawable/ic_sysbar_menu"
         android:scaleType="centerInside"
         systemui:keyCode="82"
         android:visibility="invisible"
@@ -36,7 +35,6 @@
         android:layout_width="@dimen/navigation_extra_key_width"
         android:layout_height="match_parent"
         android:layout_marginEnd="2dp"
-        android:src="@drawable/ic_ime_switcher_default"
         android:visibility="invisible"
         android:contentDescription="@string/accessibility_ime_switch_button"
         android:scaleType="centerInside"
diff --git a/packages/SystemUI/res/layout/recent_apps.xml b/packages/SystemUI/res/layout/recent_apps.xml
index eb8ee43c..870bcf7 100644
--- a/packages/SystemUI/res/layout/recent_apps.xml
+++ b/packages/SystemUI/res/layout/recent_apps.xml
@@ -21,7 +21,6 @@
     android:layout_width="@dimen/navigation_key_width"
     android:layout_height="match_parent"
     android:layout_weight="0"
-    android:src="@drawable/ic_sysbar_recent"
     android:scaleType="center"
     android:contentDescription="@string/accessibility_recent"
     android:paddingStart="@dimen/navigation_key_padding"
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index e036128..10328a4 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -30,6 +30,7 @@
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.phone.LockscreenWallpaper;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -96,9 +97,10 @@
                 dismissCallbackRegistry);
     }
 
-    public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
-            View headsUpScrim, LockscreenWallpaper lockscreenWallpaper) {
-        return new ScrimController(scrimBehind, scrimInFront, headsUpScrim);
+    public ScrimController createScrimController(LightBarController lightBarController,
+            ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
+            LockscreenWallpaper lockscreenWallpaper) {
+        return new ScrimController(lightBarController, scrimBehind, scrimInFront, headsUpScrim);
     }
 
     public VolumeDialogController createVolumeDialogController(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index c9f7456..2bc2665 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -18,6 +18,7 @@
 import android.view.View;
 
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
+import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
 import java.util.ArrayList;
 
@@ -36,9 +37,9 @@
     private View.OnLongClickListener mLongClickListener;
     private Boolean mLongClickable;
     private Integer mAlpha;
+    private Float mDarkIntensity;
     private Integer mVisibility = -1;
-    private int mImageResource = -1;
-    private Drawable mImageDrawable;
+    private KeyButtonDrawable mImageDrawable;
     private View mCurrentView;
     private boolean mVertical;
 
@@ -61,12 +62,13 @@
         if (mAlpha != null) {
             view.setAlpha(mAlpha);
         }
+        if (mDarkIntensity != null) {
+            ((ButtonInterface) view).setDarkIntensity(mDarkIntensity);
+        }
         if (mVisibility != null) {
             view.setVisibility(mVisibility);
         }
-        if (mImageResource > 0) {
-            ((ButtonInterface) view).setImageResource(mImageResource);
-        } else if (mImageDrawable != null) {
+        if (mImageDrawable != null) {
             ((ButtonInterface) view).setImageDrawable(mImageDrawable);
         }
 
@@ -87,24 +89,14 @@
         return mAlpha != null ? mAlpha : 1;
     }
 
-    public void setImageDrawable(Drawable drawable) {
+    public void setImageDrawable(KeyButtonDrawable drawable) {
         mImageDrawable = drawable;
-        mImageResource = -1;
         final int N = mViews.size();
         for (int i = 0; i < N; i++) {
             ((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable);
         }
     }
 
-    public void setImageResource(int resource) {
-        mImageResource = resource;
-        mImageDrawable = null;
-        final int N = mViews.size();
-        for (int i = 0; i < N; i++) {
-            ((ButtonInterface) mViews.get(i)).setImageResource(mImageResource);
-        }
-    }
-
     public void setVisibility(int visibility) {
         if (mVisibility == visibility) return;
         mVisibility = visibility;
@@ -130,6 +122,14 @@
         }
     }
 
+    public void setDarkIntensity(float darkIntensity) {
+        mDarkIntensity = darkIntensity;
+        final int N = mViews.size();
+        for (int i = 0; i < N; i++) {
+            ((ButtonInterface) mViews.get(i)).setDarkIntensity(darkIntensity);
+        }
+    }
+
     public void setOnClickListener(View.OnClickListener clickListener) {
         mClickListener = clickListener;
         final int N = mViews.size();
@@ -194,5 +194,4 @@
             }
         }
     }
-
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
new file mode 100644
index 0000000..b5358a1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.graphics.Rect;
+import android.view.View;
+
+import com.android.systemui.statusbar.policy.BatteryController;
+
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+
+/**
+ * Controls how light status bar flag applies to the icons.
+ */
+public class LightBarController implements BatteryController.BatteryStateChangeCallback {
+
+    private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
+
+    private final StatusBarIconController mStatusBarIconController;
+    private final BatteryController mBatteryController;
+    private FingerprintUnlockController mFingerprintUnlockController;
+    private final NavigationBarView mNavigationBarView;
+
+    private int mSystemUiVisibility;
+    private int mFullscreenStackVisibility;
+    private int mDockedStackVisibility;
+    private boolean mFullscreenLight;
+    private boolean mDockedLight;
+    private int mLastStatusBarMode;
+    private int mLastNavigationBarMode;
+    private boolean mNavigationLight;
+    private float mScrimAlpha;
+
+    private final Rect mLastFullscreenBounds = new Rect();
+    private final Rect mLastDockedBounds = new Rect();
+
+    public LightBarController(StatusBarIconController statusBarIconController,
+            NavigationBarView navigationBarView,
+            BatteryController batteryController) {
+        mStatusBarIconController = statusBarIconController;
+        mNavigationBarView = navigationBarView;
+        mBatteryController = batteryController;
+        batteryController.addCallback(this);
+    }
+
+    public void setFingerprintUnlockController(
+            FingerprintUnlockController fingerprintUnlockController) {
+        mFingerprintUnlockController = fingerprintUnlockController;
+    }
+
+    public void onSystemUiVisibilityChanged(int vis, int fullscreenStackVis, int dockedStackVis,
+            int mask, Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
+            int statusBarMode, boolean nbModeChanged, int navigationBarMode) {
+        int oldFullscreen = mFullscreenStackVisibility;
+        int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
+        int diffFullscreen = newFullscreen ^ oldFullscreen;
+        int oldDocked = mDockedStackVisibility;
+        int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
+        int diffDocked = newDocked ^ oldDocked;
+        if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
+                || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
+                || sbModeChanged
+                || !mLastFullscreenBounds.equals(fullscreenStackBounds)
+                || !mLastDockedBounds.equals(dockedStackBounds)) {
+
+            mFullscreenLight = isLight(newFullscreen, statusBarMode,
+                    View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+            mDockedLight = isLight(newDocked, statusBarMode, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+            updateStatus(fullscreenStackBounds, dockedStackBounds);
+        }
+
+        int oldVis = mSystemUiVisibility;
+        int newVis = (oldVis & ~mask) | (vis & mask);
+        int diffVis = newVis ^ oldVis;
+        if ((diffVis & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0
+                || nbModeChanged) {
+            boolean last = mNavigationLight;
+            mNavigationLight = isNavigationLight(newVis, navigationBarMode);
+            if (mNavigationLight != last) {
+                updateNavigation();
+            }
+        }
+        mFullscreenStackVisibility = newFullscreen;
+        mDockedStackVisibility = newDocked;
+        mSystemUiVisibility = newVis;
+        mLastStatusBarMode = statusBarMode;
+        mLastNavigationBarMode = navigationBarMode;
+        mLastFullscreenBounds.set(fullscreenStackBounds);
+        mLastDockedBounds.set(dockedStackBounds);
+    }
+
+    private void reevaluate() {
+        onSystemUiVisibilityChanged(mSystemUiVisibility, mFullscreenStackVisibility,
+                mDockedStackVisibility, 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds,
+                true /* sbModeChange*/, mLastStatusBarMode, true /* nbModeChange*/,
+                mLastNavigationBarMode);
+    }
+
+    public void setScrimAlpha(float alpha) {
+        mScrimAlpha = alpha;
+        reevaluate();
+    }
+
+    private boolean isNavigationLight(int vis, int barMode) {
+        return isLight(vis, barMode, View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
+                && mScrimAlpha < NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD;
+    }
+
+    private boolean isLight(int vis, int barMode, int flag) {
+        boolean isTransparentBar = (barMode == MODE_TRANSPARENT
+                || barMode == MODE_LIGHTS_OUT_TRANSPARENT);
+        boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
+        boolean light = (vis & flag) != 0;
+        return allowLight && light;
+    }
+
+    private boolean animateChange() {
+        if (mFingerprintUnlockController == null) {
+            return false;
+        }
+        int unlockMode = mFingerprintUnlockController.getMode();
+        return unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
+                && unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
+    }
+
+    private void updateStatus(Rect fullscreenStackBounds, Rect dockedStackBounds) {
+        boolean hasDockedStack = !dockedStackBounds.isEmpty();
+
+        // If both are light or fullscreen is light and there is no docked stack, all icons get
+        // dark.
+        if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
+            mStatusBarIconController.setIconsDarkArea(null);
+            mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
+
+        }
+
+        // If no one is light or the fullscreen is not light and there is no docked stack,
+        // all icons become white.
+        else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
+            mStatusBarIconController.getTransitionsController().setIconsDark(
+                    false, animateChange());
+        }
+
+        // Not the same for every stack, magic!
+        else {
+            Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
+            if (bounds.isEmpty()) {
+                mStatusBarIconController.setIconsDarkArea(null);
+            } else {
+                mStatusBarIconController.setIconsDarkArea(bounds);
+            }
+            mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
+        }
+    }
+
+    private void updateNavigation() {
+        if (mNavigationBarView != null) {
+            mNavigationBarView.getLightTransitionsController().setIconsDark(
+                    mNavigationLight, animateChange());
+        }
+    }
+
+    @Override
+    public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+
+    }
+
+    @Override
+    public void onPowerSaveChanged(boolean isPowerSave) {
+        reevaluate();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
new file mode 100644
index 0000000..1d4d2d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.animation.ValueAnimator;
+import android.os.Handler;
+import android.os.SystemClock;
+
+import com.android.systemui.Interpolators;
+
+/**
+ * Class to control all aspects about light bar changes.
+ */
+public class LightBarTransitionsController {
+
+    public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
+
+    private final Handler mHandler;
+    private final DarkIntensityApplier mApplier;
+
+    private boolean mTransitionDeferring;
+    private long mTransitionDeferringStartTime;
+    private long mTransitionDeferringDuration;
+    private boolean mTransitionPending;
+    private boolean mTintChangePending;
+    private float mPendingDarkIntensity;
+    private ValueAnimator mTintAnimator;
+    private float mDarkIntensity;
+
+    private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mTransitionDeferring = false;
+        }
+    };
+
+    public LightBarTransitionsController(DarkIntensityApplier applier) {
+        mApplier = applier;
+        mHandler = new Handler();
+    }
+
+    public void appTransitionPending() {
+        mTransitionPending = true;
+    }
+
+    public void appTransitionCancelled() {
+        if (mTransitionPending && mTintChangePending) {
+            mTintChangePending = false;
+            animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+        }
+        mTransitionPending = false;
+    }
+
+    public void appTransitionStarting(long startTime, long duration) {
+        if (mTransitionPending && mTintChangePending) {
+            mTintChangePending = false;
+            animateIconTint(mPendingDarkIntensity,
+                    Math.max(0, startTime - SystemClock.uptimeMillis()),
+                    duration);
+
+        } else if (mTransitionPending) {
+
+            // If we don't have a pending tint change yet, the change might come in the future until
+            // startTime is reached.
+            mTransitionDeferring = true;
+            mTransitionDeferringStartTime = startTime;
+            mTransitionDeferringDuration = duration;
+            mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
+            mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
+        }
+        mTransitionPending = false;
+    }
+
+    public void setIconsDark(boolean dark, boolean animate) {
+        if (!animate) {
+            setIconTintInternal(dark ? 1.0f : 0.0f);
+        } else if (mTransitionPending) {
+            deferIconTintChange(dark ? 1.0f : 0.0f);
+        } else if (mTransitionDeferring) {
+            animateIconTint(dark ? 1.0f : 0.0f,
+                    Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
+                    mTransitionDeferringDuration);
+        } else {
+            animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+        }
+    }
+
+    public float getCurrentDarkIntensity() {
+        return mDarkIntensity;
+    }
+
+    private void deferIconTintChange(float darkIntensity) {
+        if (mTintChangePending && darkIntensity == mPendingDarkIntensity) {
+            return;
+        }
+        mTintChangePending = true;
+        mPendingDarkIntensity = darkIntensity;
+    }
+
+    private void animateIconTint(float targetDarkIntensity, long delay,
+            long duration) {
+        if (mTintAnimator != null) {
+            mTintAnimator.cancel();
+        }
+        if (mDarkIntensity == targetDarkIntensity) {
+            return;
+        }
+        mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
+        mTintAnimator.addUpdateListener(
+                animation -> setIconTintInternal((Float) animation.getAnimatedValue()));
+        mTintAnimator.setDuration(duration);
+        mTintAnimator.setStartDelay(delay);
+        mTintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        mTintAnimator.start();
+    }
+
+    private void setIconTintInternal(float darkIntensity) {
+        mDarkIntensity = darkIntensity;
+        mApplier.applyDarkIntensity(darkIntensity);
+    }
+
+    /**
+     * Interface to apply a specific dark intensity.
+     */
+    public interface DarkIntensityApplier {
+        void applyDarkIntensity(float darkIntensity);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightStatusBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightStatusBarController.java
deleted file mode 100644
index dd7f3cc..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightStatusBarController.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.graphics.Rect;
-import android.view.View;
-
-import com.android.systemui.statusbar.policy.BatteryController;
-
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
-
-/**
- * Controls how light status bar flag applies to the icons.
- */
-public class LightStatusBarController implements BatteryController.BatteryStateChangeCallback {
-
-    private final StatusBarIconController mIconController;
-    private final BatteryController mBatteryController;
-    private FingerprintUnlockController mFingerprintUnlockController;
-
-    private int mFullscreenStackVisibility;
-    private int mDockedStackVisibility;
-    private boolean mFullscreenLight;
-    private boolean mDockedLight;
-    private int mLastStatusBarMode;
-
-    private final Rect mLastFullscreenBounds = new Rect();
-    private final Rect mLastDockedBounds = new Rect();
-
-    public LightStatusBarController(StatusBarIconController iconController,
-            BatteryController batteryController) {
-        mIconController = iconController;
-        mBatteryController = batteryController;
-        batteryController.addCallback(this);
-    }
-
-    public void setFingerprintUnlockController(
-            FingerprintUnlockController fingerprintUnlockController) {
-        mFingerprintUnlockController = fingerprintUnlockController;
-    }
-
-    public void onSystemUiVisibilityChanged(int fullscreenStackVis, int dockedStackVis, int mask,
-            Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
-            int statusBarMode) {
-        int oldFullscreen = mFullscreenStackVisibility;
-        int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
-        int diffFullscreen = newFullscreen ^ oldFullscreen;
-        int oldDocked = mDockedStackVisibility;
-        int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
-        int diffDocked = newDocked ^ oldDocked;
-        if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
-                || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
-                || sbModeChanged
-                || !mLastFullscreenBounds.equals(fullscreenStackBounds)
-                || !mLastDockedBounds.equals(dockedStackBounds)) {
-
-            mFullscreenLight = isLight(newFullscreen, statusBarMode);
-            mDockedLight = isLight(newDocked, statusBarMode);
-            update(fullscreenStackBounds, dockedStackBounds);
-        }
-        mFullscreenStackVisibility = newFullscreen;
-        mDockedStackVisibility = newDocked;
-        mLastStatusBarMode = statusBarMode;
-        mLastFullscreenBounds.set(fullscreenStackBounds);
-        mLastDockedBounds.set(dockedStackBounds);
-    }
-
-    private boolean isLight(int vis, int statusBarMode) {
-        boolean isTransparentBar = (statusBarMode == MODE_TRANSPARENT
-                || statusBarMode == MODE_LIGHTS_OUT_TRANSPARENT);
-        boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
-        boolean light = (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
-        return allowLight && light;
-    }
-
-    private boolean animateChange() {
-        if (mFingerprintUnlockController == null) {
-            return false;
-        }
-        int unlockMode = mFingerprintUnlockController.getMode();
-        return unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
-                && unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
-    }
-
-    private void update(Rect fullscreenStackBounds, Rect dockedStackBounds) {
-        boolean hasDockedStack = !dockedStackBounds.isEmpty();
-
-        // If both are light or fullscreen is light and there is no docked stack, all icons get
-        // dark.
-        if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
-            mIconController.setIconsDarkArea(null);
-            mIconController.setIconsDark(true, animateChange());
-
-        }
-
-        // If no one is light or the fullscreen is not light and there is no docked stack,
-        // all icons become white.
-        else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
-            mIconController.setIconsDark(false, animateChange());
-
-        }
-
-        // Not the same for every stack, magic!
-        else {
-            Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
-            if (bounds.isEmpty()) {
-                mIconController.setIconsDarkArea(null);
-            } else {
-                mIconController.setIconsDarkArea(bounds);
-            }
-            mIconController.setIconsDark(true, animateChange());
-        }
-    }
-
-    @Override
-    public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-
-    }
-
-    @Override
-    public void onPowerSaveChanged(boolean isPowerSave) {
-        onSystemUiVisibilityChanged(mFullscreenStackVisibility, mDockedStackVisibility,
-                0 /* mask */, mLastFullscreenBounds, mLastDockedBounds, true /* sbModeChange*/,
-                mLastStatusBarMode);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 1fe0115..3be5e57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -16,13 +16,11 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.os.ServiceManager;
+import android.util.SparseArray;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.animation.AccelerateInterpolator;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.R;
@@ -31,6 +29,7 @@
 
     private final NavigationBarView mView;
     private final IStatusBarService mBarService;
+    private final LightBarTransitionsController mLightTransitionsController;
 
     private boolean mLightsOut;
 
@@ -39,6 +38,7 @@
         mView = view;
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+        mLightTransitionsController = new LightBarTransitionsController(this::applyDarkIntensity);
     }
 
     public void init() {
@@ -46,6 +46,10 @@
         applyMode(getMode(), false /*animate*/, true /*force*/);
     }
 
+    public LightBarTransitionsController getLightTransitionsController() {
+        return mLightTransitionsController;
+    }
+
     @Override
     protected void onTransition(int oldMode, int newMode, boolean animate) {
         super.onTransition(oldMode, newMode, animate);
@@ -81,6 +85,18 @@
         }
     }
 
+
+    public void reapplyDarkIntensity() {
+        applyDarkIntensity(mLightTransitionsController.getCurrentDarkIntensity());
+    }
+
+    public void applyDarkIntensity(float darkIntensity) {
+        SparseArray<ButtonDispatcher> buttonDispatchers = mView.getButtonDispatchers();
+        for (int i = buttonDispatchers.size() - 1; i >= 0; i--) {
+            buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
+        }
+    }
+
     private final View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
         @Override
         public boolean onTouch(View v, MotionEvent ev) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 7023324..d22f421 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -22,6 +22,7 @@
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.app.ActivityManager;
+import android.annotation.DrawableRes;
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -34,6 +35,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
+import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.IDockedStackListener.Stub;
 import android.view.MotionEvent;
@@ -51,8 +53,10 @@
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.phone.NavGesture;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.policy.DeadZone;
+import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -78,14 +82,14 @@
     int mDisabledFlags = 0;
     int mNavigationIconHints = 0;
 
-    private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
-    private Drawable mBackCarModeIcon, mBackLandCarModeIcon;
-    private Drawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
-    private Drawable mHomeDefaultIcon, mHomeCarModeIcon;
-    private Drawable mRecentIcon;
-    private Drawable mDockedIcon;
-    private Drawable mImeIcon;
-    private Drawable mMenuIcon;
+    private KeyButtonDrawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
+    private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
+    private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
+    private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
+    private KeyButtonDrawable mRecentIcon;
+    private KeyButtonDrawable mDockedIcon;
+    private KeyButtonDrawable mImeIcon;
+    private KeyButtonDrawable mMenuIcon;
 
     private GestureHelper mGestureHelper;
     private DeadZone mDeadZone;
@@ -217,6 +221,10 @@
         return mBarTransitions;
     }
 
+    public LightBarTransitionsController getLightTransitionsController() {
+        return mBarTransitions.getLightTransitionsController();
+    }
+
     public void setComponents(RecentsComponent recentsComponent, Divider divider) {
         mRecentsComponent = recentsComponent;
         mDivider = divider;
@@ -281,29 +289,44 @@
         return mButtonDispatchers.get(R.id.ime_switcher);
     }
 
+    public SparseArray<ButtonDispatcher> getButtonDispatchers() {
+        return mButtonDispatchers;
+    }
+
     private void updateCarModeIcons(Context ctx) {
-        mBackCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_carmode);
+        mBackCarModeIcon = getDrawable(ctx,
+                R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
         mBackLandCarModeIcon = mBackCarModeIcon;
-        mBackAltCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_ime_carmode);
+        mBackAltCarModeIcon = getDrawable(ctx,
+                R.drawable.ic_sysbar_back_ime_carmode, R.drawable.ic_sysbar_back_ime_carmode);
         mBackAltLandCarModeIcon = mBackAltCarModeIcon;
-        mHomeCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_home_carmode);
+        mHomeCarModeIcon = getDrawable(ctx,
+                R.drawable.ic_sysbar_home_carmode, R.drawable.ic_sysbar_home_carmode);
     }
 
     private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
         if (oldConfig.orientation != newConfig.orientation
                 || oldConfig.densityDpi != newConfig.densityDpi) {
-            mDockedIcon = ctx.getDrawable(R.drawable.ic_sysbar_docked);
+            mDockedIcon = getDrawable(ctx,
+                    R.drawable.ic_sysbar_docked, R.drawable.ic_sysbar_docked_dark);
         }
         if (oldConfig.densityDpi != newConfig.densityDpi) {
-            mBackIcon = ctx.getDrawable(R.drawable.ic_sysbar_back);
+            mBackIcon = getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark);
             mBackLandIcon = mBackIcon;
-            mBackAltIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_ime);
+            mBackAltIcon = getDrawable(ctx,
+                    R.drawable.ic_sysbar_back_ime, R.drawable.ic_sysbar_back_ime_dark);
             mBackAltLandIcon = mBackAltIcon;
 
-            mHomeDefaultIcon = ctx.getDrawable(R.drawable.ic_sysbar_home);
-            mRecentIcon = ctx.getDrawable(R.drawable.ic_sysbar_recent);
-            mMenuIcon = ctx.getDrawable(R.drawable.ic_sysbar_menu);
-            mImeIcon = ctx.getDrawable(R.drawable.ic_ime_switcher_default);
+            mHomeDefaultIcon = getDrawable(ctx,
+                    R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
+            mRecentIcon = getDrawable(ctx,
+                    R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
+            mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
+
+            Context darkContext = new ContextThemeWrapper(ctx, R.style.DualToneDarkTheme);
+            Context lightContext = new ContextThemeWrapper(ctx, R.style.DualToneLightTheme);
+            mImeIcon = getDrawable(darkContext, lightContext,
+                    R.drawable.ic_ime_switcher_default, R.drawable.ic_ime_switcher_default);
 
             if (ALTERNATE_CAR_MODE_UI) {
                 updateCarModeIcons(ctx);
@@ -311,6 +334,17 @@
         }
     }
 
+    private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
+            @DrawableRes int darkIcon) {
+        return getDrawable(ctx, ctx, lightIcon, darkIcon);
+    }
+
+    private KeyButtonDrawable getDrawable(Context darkContext, Context lightContext,
+            @DrawableRes int lightIcon, @DrawableRes int darkIcon) {
+        return KeyButtonDrawable.create(lightContext.getDrawable(lightIcon),
+                darkContext.getDrawable(darkIcon));
+    }
+
     @Override
     public void setLayoutDirection(int layoutDirection) {
         // Reload all the icons
@@ -328,13 +362,13 @@
         setNavigationIconHints(hints, false);
     }
 
-    private Drawable getBackIconWithAlt(boolean carMode, boolean landscape) {
+    private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
         return landscape
                 ? carMode ? mBackAltLandCarModeIcon : mBackAltLandIcon
                 : carMode ? mBackAltCarModeIcon : mBackAltIcon;
     }
 
-    private Drawable getBackIcon(boolean carMode, boolean landscape) {
+    private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
         return landscape
                 ? carMode ? mBackLandCarModeIcon : mBackLandIcon
                 : carMode ? mBackCarModeIcon : mBackIcon;
@@ -357,7 +391,7 @@
         // We have to replace or restore the back and home button icons when exiting or entering
         // carmode, respectively. Recents are not available in CarMode in nav bar so change
         // to recent icon is not required.
-        Drawable backIcon = (backAlt)
+        KeyButtonDrawable backIcon = (backAlt)
                 ? getBackIconWithAlt(mUseCarModeUi, mVertical)
                 : getBackIcon(mUseCarModeUi, mVertical);
 
@@ -380,6 +414,8 @@
         getMenuButton().setImageDrawable(mMenuIcon);
 
         setDisabledFlags(mDisabledFlags, true);
+
+        mBarTransitions.reapplyDarkIntensity();
     }
 
     public void setDisabledFlags(int disabledFlags) {
@@ -565,6 +601,7 @@
 
     private void updateRecentsIcon() {
         getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
+        mBarTransitions.reapplyDarkIntensity();
     }
 
     public boolean isVertical() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index b2dae50..8565b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -333,7 +333,7 @@
     BrightnessMirrorController mBrightnessMirrorController;
     AccessibilityController mAccessibilityController;
     protected FingerprintUnlockController mFingerprintUnlockController;
-    LightStatusBarController mLightStatusBarController;
+    LightBarController mLightBarController;
     protected LockscreenWallpaper mLockscreenWallpaper;
 
     int mNaturalBarHeight = -1;
@@ -829,10 +829,45 @@
             mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
         }
 
+        mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
+        mKeyguardStatusView =
+                (KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view);
+        mKeyguardBottomArea =
+                (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
+        mKeyguardBottomArea.setActivityStarter(this);
+        mKeyguardBottomArea.setAssistManager(mAssistManager);
+        mKeyguardIndicationController = new KeyguardIndicationController(mContext,
+                (ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
+                mKeyguardBottomArea.getLockIcon());
+        mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
+
+        // set the initial view visibility
+        setAreThereNotifications();
+
+        createIconController();
+
+        mBatteryController = createBatteryController();
+        mBatteryController.addCallback(new BatteryStateChangeCallback() {
+            @Override
+            public void onPowerSaveChanged(boolean isPowerSave) {
+                mHandler.post(mCheckBarModes);
+                if (mDozeServiceHost != null) {
+                    mDozeServiceHost.firePowerSaveChanged(isPowerSave);
+                }
+            }
+            @Override
+            public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+                // noop
+            }
+        });
+
+        mLightBarController = new LightBarController(mIconController, mNavigationBarView,
+                mBatteryController);
+
         ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
         ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
         View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
-        mScrimController = SystemUIFactory.getInstance().createScrimController(
+        mScrimController = SystemUIFactory.getInstance().createScrimController(mLightBarController,
                 scrimBehind, scrimInFront, headsUpScrim, mLockscreenWallpaper);
         if (mScrimSrcModeEnabled) {
             Runnable runnable = new Runnable() {
@@ -851,23 +886,6 @@
         mStatusBarView.setScrimController(mScrimController);
         mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller);
 
-        mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
-        mKeyguardStatusView =
-                (KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view);
-        mKeyguardBottomArea =
-                (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
-        mKeyguardBottomArea.setActivityStarter(this);
-        mKeyguardBottomArea.setAssistManager(mAssistManager);
-        mKeyguardIndicationController = new KeyguardIndicationController(mContext,
-                (ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
-                mKeyguardBottomArea.getLockIcon());
-        mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
-
-        // set the initial view visibility
-        setAreThereNotifications();
-
-        createIconController();
-
         // Background thread for any controllers that need it.
         mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
         mHandlerThread.start();
@@ -875,20 +893,6 @@
         // Other icons
         mLocationController = new LocationControllerImpl(mContext,
                 mHandlerThread.getLooper()); // will post a notification
-        mBatteryController = createBatteryController();
-        mBatteryController.addCallback(new BatteryStateChangeCallback() {
-            @Override
-            public void onPowerSaveChanged(boolean isPowerSave) {
-                mHandler.post(mCheckBarModes);
-                if (mDozeServiceHost != null) {
-                    mDozeServiceHost.firePowerSaveChanged(isPowerSave);
-                }
-            }
-            @Override
-            public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-                // noop
-            }
-        });
         mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
         mNetworkController.setUserSetupComplete(mUserSetup);
         mHotspotController = new HotspotControllerImpl(mContext);
@@ -915,8 +919,6 @@
         mAccessibilityController = new AccessibilityController(mContext);
         mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
         mNextAlarmController = new NextAlarmControllerImpl(mContext);
-        mLightStatusBarController = new LightStatusBarController(mIconController,
-                mBatteryController);
         mKeyguardMonitor = new KeyguardMonitorImpl(mContext);
             mUserSwitcherController = createUserSwitcherController();
         if (UserManager.get(mContext).isUserSwitcherEnabled()) {
@@ -1305,7 +1307,7 @@
         });
 
         mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
-        mLightStatusBarController.setFingerprintUnlockController(mFingerprintUnlockController);
+        mLightBarController.setFingerprintUnlockController(mFingerprintUnlockController);
         Trace.endSection();
     }
 
@@ -3080,6 +3082,7 @@
                 Integer.toHexString(oldVal), Integer.toHexString(newVal),
                 Integer.toHexString(diff)));
         boolean sbModeChanged = false;
+        boolean nbModeChanged = false;
         if (diff != 0) {
             mSystemUiVisibility = newVal;
 
@@ -3103,7 +3106,7 @@
                     View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
                     View.NAVIGATION_BAR_TRANSPARENT);
             sbModeChanged = sbMode != -1;
-            final boolean nbModeChanged = nbMode != -1;
+            nbModeChanged = nbMode != -1;
             boolean checkBarModes = false;
             if (sbModeChanged && sbMode != mStatusBarMode) {
                 mStatusBarMode = sbMode;
@@ -3133,8 +3136,9 @@
             notifyUiVisibilityChanged(mSystemUiVisibility);
         }
 
-        mLightStatusBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis,
-                mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode);
+        mLightBarController.onSystemUiVisibilityChanged(vis, fullscreenStackVis, dockedStackVis,
+                mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode,
+                nbModeChanged, mNavigationBarMode);
     }
 
     protected int computeStatusBarMode(int oldVal, int newVal) {
@@ -4195,8 +4199,14 @@
                                 onLaunchTransitionFadingEnded();
                             }
                         });
-                mIconController.appTransitionStarting(SystemClock.uptimeMillis(),
-                        StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
+                mIconController.getTransitionsController().appTransitionStarting(
+                        SystemClock.uptimeMillis(),
+                        LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+                if (mNavigationBarView != null) {
+                    mNavigationBarView.getLightTransitionsController().appTransitionStarting(
+                            SystemClock.uptimeMillis(),
+                            LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+                }
             }
         };
         if (mNotificationPanel.isLaunchTransitionRunning()) {
@@ -4327,7 +4337,10 @@
         // Treat Keyguard exit animation as an app transition to achieve nice transition for status
         // bar.
         mKeyguardGoingAway = true;
-        mIconController.appTransitionPending();
+        mIconController.getTransitionsController().appTransitionPending();
+        if (mNavigationBarView != null) {
+            mNavigationBarView.getLightTransitionsController().appTransitionPending();
+        }
     }
 
     /**
@@ -4342,11 +4355,16 @@
         mKeyguardFadingAwayDelay = delay;
         mKeyguardFadingAwayDuration = fadeoutDuration;
         mWaitingForKeyguardExit = false;
-        mIconController.appTransitionStarting(
+        mIconController.getTransitionsController().appTransitionStarting(
                 startTime + fadeoutDuration
-                        - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION,
-                StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
+                        - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
+                LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
         recomputeDisableFlags(fadeoutDuration > 0 /* animate */);
+        if (mNavigationBarView != null) {
+            mNavigationBarView.getLightTransitionsController().appTransitionStarting(
+                    startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
+                    LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+        }
     }
 
     public boolean isKeyguardFadingAway() {
@@ -4977,13 +4995,19 @@
         // Use own timings when Keyguard is going away, see keyguardGoingAway and
         // setKeyguardFadingAway
         if (!mKeyguardFadingAway) {
-            mIconController.appTransitionPending();
+            mIconController.getTransitionsController().appTransitionPending();
+            if (mNavigationBarView != null) {
+                mNavigationBarView.getLightTransitionsController().appTransitionPending();
+            }
         }
     }
 
     @Override
     public void appTransitionCancelled() {
-        mIconController.appTransitionCancelled();
+        mIconController.getTransitionsController().appTransitionCancelled();
+        if (mNavigationBarView != null) {
+            mNavigationBarView.getLightTransitionsController().appTransitionCancelled();
+        }
         EventBus.getDefault().send(new AppTransitionFinishedEvent());
     }
 
@@ -4993,7 +5017,11 @@
         // Use own timings when Keyguard is going away, see keyguardGoingAway and
         // setKeyguardFadingAway.
         if (!mKeyguardGoingAway) {
-            mIconController.appTransitionStarting(startTime, duration);
+            mIconController.getTransitionsController().appTransitionStarting(startTime, duration);
+            if (mNavigationBarView != null) {
+                mNavigationBarView.getLightTransitionsController().appTransitionStarting(
+                        startTime, duration);
+            }
         }
         if (mIconPolicy != null) {
             mIconPolicy.appTransitionStarting(startTime, duration);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 749ff99e..944495e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -59,6 +59,7 @@
     private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
     private static final int TAG_END_ALPHA = R.id.scrim_alpha_end;
 
+    private final LightBarController mLightBarController;
     protected final ScrimView mScrimBehind;
     private final ScrimView mScrimInFront;
     private final UnlockMethodCache mUnlockMethodCache;
@@ -99,13 +100,15 @@
     private boolean mKeyguardFadingOutInProgress;
     private ValueAnimator mKeyguardFadeoutAnimation;
 
-    public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim) {
+    public ScrimController(LightBarController lightBarController, ScrimView scrimBehind,
+            ScrimView scrimInFront, View headsUpScrim) {
         mScrimBehind = scrimBehind;
         mScrimInFront = scrimInFront;
         mHeadsUpScrim = headsUpScrim;
         final Context context = scrimBehind.getContext();
         mUnlockMethodCache = UnlockMethodCache.getInstance(context);
         mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
+        mLightBarController = lightBarController;
         updateHeadsUpScrim(false);
     }
 
@@ -341,6 +344,7 @@
             alpha = Math.max(0.0f, Math.min(1.0f, alpha));
             mCurrentHeadsUpAlpha = alpha;
         }
+        mLightBarController.setScrimAlpha(mCurrentBehindAlpha);
     }
 
     protected void updateScrimColor(View scrim) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index a948a08..a0425e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -60,7 +60,6 @@
  */
 public class StatusBarIconController extends StatusBarIconList implements Tunable {
 
-    public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
     public static final String ICON_BLACKLIST = "icon_blacklist";
     public static final int DEFAULT_ICON_TINT = Color.WHITE;
 
@@ -90,31 +89,16 @@
     private static final Rect sTmpRect = new Rect();
     private static final int[] sTmpInt2 = new int[2];
 
-    private boolean mTransitionPending;
-    private boolean mTintChangePending;
-    private float mPendingDarkIntensity;
-    private ValueAnimator mTintAnimator;
-
     private int mDarkModeIconColorSingleTone;
     private int mLightModeIconColorSingleTone;
 
-    private final Handler mHandler;
-    private boolean mTransitionDeferring;
-    private long mTransitionDeferringStartTime;
-    private long mTransitionDeferringDuration;
+    private final LightBarTransitionsController mTransitionsController;
 
     private boolean mClockVisibleByPolicy = true;
     private boolean mClockVisibleByUser = true;
 
     private final ArraySet<String> mIconBlacklist = new ArraySet<>();
 
-    private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
-        @Override
-        public void run() {
-            mTransitionDeferring = false;
-        }
-    };
-
     public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
             PhoneStatusBar phoneStatusBar) {
         super(context.getResources().getStringArray(
@@ -144,16 +128,21 @@
         mClock = (TextView) statusBar.findViewById(R.id.clock);
         mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
         mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
-        mHandler = new Handler();
         loadDimens();
 
         TunerService.get(mContext).addTunable(this, ICON_BLACKLIST);
+
+        mTransitionsController = new LightBarTransitionsController(this::setIconTintInternal);
     }
 
     public void setSignalCluster(SignalClusterView signalCluster) {
         mSignalCluster = signalCluster;
     }
 
+    public LightBarTransitionsController getTransitionsController() {
+        return mTransitionsController;
+    }
+
     /**
      * Looks up the scale factor for status bar icons and scales the battery view by that amount.
      */
@@ -444,41 +433,6 @@
         mNotificationIconAreaController.setTintArea(darkArea);
     }
 
-    public void setIconsDark(boolean dark, boolean animate) {
-        if (!animate) {
-            setIconTintInternal(dark ? 1.0f : 0.0f);
-        } else if (mTransitionPending) {
-            deferIconTintChange(dark ? 1.0f : 0.0f);
-        } else if (mTransitionDeferring) {
-            animateIconTint(dark ? 1.0f : 0.0f,
-                    Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
-                    mTransitionDeferringDuration);
-        } else {
-            animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
-        }
-    }
-
-    private void animateIconTint(float targetDarkIntensity, long delay,
-            long duration) {
-        if (mTintAnimator != null) {
-            mTintAnimator.cancel();
-        }
-        if (mDarkIntensity == targetDarkIntensity) {
-            return;
-        }
-        mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
-        mTintAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                setIconTintInternal((Float) animation.getAnimatedValue());
-            }
-        });
-        mTintAnimator.setDuration(duration);
-        mTintAnimator.setStartDelay(delay);
-        mTintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        mTintAnimator.start();
-    }
-
     private void setIconTintInternal(float darkIntensity) {
         mDarkIntensity = darkIntensity;
         mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
@@ -487,14 +441,6 @@
         applyIconTint();
     }
 
-    private void deferIconTintChange(float darkIntensity) {
-        if (mTintChangePending && darkIntensity == mPendingDarkIntensity) {
-            return;
-        }
-        mTintChangePending = true;
-        mPendingDarkIntensity = darkIntensity;
-    }
-
     /**
      * @return the tint to apply to {@param view} depending on the desired tint {@param color} and
      *         the screen {@param tintArea} in which to apply that tint
@@ -551,38 +497,6 @@
         mClock.setTextColor(getTint(mTintArea, mClock, mIconTint));
     }
 
-    public void appTransitionPending() {
-        mTransitionPending = true;
-    }
-
-    public void appTransitionCancelled() {
-        if (mTransitionPending && mTintChangePending) {
-            mTintChangePending = false;
-            animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
-        }
-        mTransitionPending = false;
-    }
-
-    public void appTransitionStarting(long startTime, long duration) {
-        if (mTransitionPending && mTintChangePending) {
-            mTintChangePending = false;
-            animateIconTint(mPendingDarkIntensity,
-                    Math.max(0, startTime - SystemClock.uptimeMillis()),
-                    duration);
-
-        } else if (mTransitionPending) {
-
-            // If we don't have a pending tint change yet, the change might come in the future until
-            // startTime is reached.
-            mTransitionDeferring = true;
-            mTransitionDeferringStartTime = startTime;
-            mTransitionDeferringDuration = duration;
-            mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
-            mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
-        }
-        mTransitionPending = false;
-    }
-
     public static ArraySet<String> getIconBlacklist(String blackListStr) {
         ArraySet<String> ret = new ArraySet<String>();
         if (blackListStr == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
new file mode 100644
index 0000000..3ee01de
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.annotation.Nullable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+
+/**
+ * Drawable for {@link KeyButtonView}s which contains an asset for both normal mode and light
+ * navigation bar mode.
+ */
+public class KeyButtonDrawable extends LayerDrawable {
+
+    private final boolean mHasDarkDrawable;
+
+    public static KeyButtonDrawable create(Drawable lightDrawable,
+            @Nullable Drawable darkDrawable) {
+        if (darkDrawable != null) {
+            return new KeyButtonDrawable(
+                    new Drawable[] { lightDrawable.mutate(), darkDrawable.mutate() });
+        } else {
+            return new KeyButtonDrawable(new Drawable[] { lightDrawable.mutate() });
+        }
+    }
+
+    private KeyButtonDrawable(Drawable[] drawables) {
+        super(drawables);
+        mutate();
+        mHasDarkDrawable = drawables.length > 1;
+        setDarkIntensity(0f);
+    }
+
+    public void setDarkIntensity(float intensity) {
+        if (!mHasDarkDrawable) {
+            return;
+        }
+        getDrawable(0).setAlpha((int) ((1 - intensity) * 255f));
+        getDrawable(1).setAlpha((int) (intensity * 255f));
+        invalidateSelf();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index 57e092a..8e51ddb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -41,6 +41,7 @@
 
     private static final float GLOW_MAX_SCALE_FACTOR = 1.35f;
     private static final float GLOW_MAX_ALPHA = 0.2f;
+    private static final float GLOW_MAX_ALPHA_DARK = 0.1f;
     private static final int ANIMATION_DURATION_SCALE = 350;
     private static final int ANIMATION_DURATION_FADE = 450;
 
@@ -57,6 +58,8 @@
     private boolean mPressed;
     private boolean mDrawingHardwareGlow;
     private int mMaxWidth;
+    private boolean mLastDark;
+    private boolean mDark;
 
     private final Interpolator mInterpolator = new LogInterpolator();
     private boolean mSupportHardware;
@@ -70,11 +73,15 @@
         mTargetView = targetView;
     }
 
+    public void setDarkIntensity(float darkIntensity) {
+        mDark = darkIntensity >= 0.5f;
+    }
+
     private Paint getRipplePaint() {
         if (mRipplePaint == null) {
             mRipplePaint = new Paint();
             mRipplePaint.setAntiAlias(true);
-            mRipplePaint.setColor(0xffffffff);
+            mRipplePaint.setColor(mLastDark ? 0xff000000 : 0xffffffff);
         }
         return mRipplePaint;
     }
@@ -155,6 +162,10 @@
         invalidateSelf();
     }
 
+    private float getMaxGlowAlpha() {
+        return mLastDark ? GLOW_MAX_ALPHA_DARK : GLOW_MAX_ALPHA;
+    }
+
     @Override
     protected boolean onStateChange(int[] state) {
         boolean pressed = false;
@@ -184,6 +195,10 @@
     }
 
     public void setPressed(boolean pressed) {
+        if (mDark != mLastDark && pressed) {
+            mRipplePaint = null;
+            mLastDark = mDark;
+        }
         if (mSupportHardware) {
             setPressedHardware(pressed);
         } else {
@@ -212,7 +227,7 @@
 
     private void enterSoftware() {
         cancelAnimations();
-        mGlowAlpha = GLOW_MAX_ALPHA;
+        mGlowAlpha = getMaxGlowAlpha();
         ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(this, "glowScale",
                 0f, GLOW_MAX_SCALE_FACTOR);
         scaleAnimator.setInterpolator(mInterpolator);
@@ -312,7 +327,7 @@
         }
 
         mGlowScale = GLOW_MAX_SCALE_FACTOR;
-        mGlowAlpha = GLOW_MAX_ALPHA;
+        mGlowAlpha = getMaxGlowAlpha();
         mRipplePaint = getRipplePaint();
         mRipplePaint.setAlpha((int) (mGlowAlpha * 255));
         mPaintProp = CanvasProperty.createPaint(mRipplePaint);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index ae59315..45cfbdc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.annotation.DrawableRes;
-import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -60,6 +58,7 @@
     private boolean mGestureAborted;
     private boolean mLongClicked;
     private OnClickListener mOnClickListener;
+    private final KeyButtonRipple mRipple;
 
     private final Runnable mCheckLongPress = new Runnable() {
         public void run() {
@@ -99,11 +98,12 @@
 
         a.recycle();
 
-
         setClickable(true);
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        setBackground(new KeyButtonRipple(context, this));
+
+        mRipple = new KeyButtonRipple(context, this);
+        setBackground(mRipple);
     }
 
     public void setCode(int code) {
@@ -265,13 +265,16 @@
     }
 
     @Override
-    public void setImageResource(@DrawableRes int resId) {
-        super.setImageResource(resId);
-    }
+    public void setDarkIntensity(float darkIntensity) {
+        Drawable drawable = getDrawable();
+        if (drawable != null) {
+            ((KeyButtonDrawable) getDrawable()).setDarkIntensity(darkIntensity);
 
-    @Override
-    public void setImageDrawable(@Nullable Drawable drawable) {
-        super.setImageDrawable(drawable);
+            // Since we reuse the same drawable for multiple views, we need to invalidate the view
+            // manually.
+            invalidate();
+        }
+        mRipple.setDarkIntensity(darkIntensity);
     }
 
     @Override