Merge "Introduce EditorInfo#locales."
diff --git a/api/current.txt b/api/current.txt
index 34a0d46..fac3b2b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28,6 +28,7 @@
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
+    field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -5529,6 +5530,8 @@
     method public void enableCarMode(int);
     method public int getCurrentModeType();
     method public int getNightMode();
+    method public boolean isNightModeLocked();
+    method public boolean isUiModeLocked();
     method public void setNightMode(int);
     field public static java.lang.String ACTION_ENTER_CAR_MODE;
     field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -8285,6 +8288,7 @@
     field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
     field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
     field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
+    field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
     field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
@@ -33148,6 +33152,35 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
+  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+    ctor public NotificationAssistantService();
+    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
+    method public final void clearAnnotation(java.lang.String);
+    method public void onNotificationActionClick(java.lang.String, long, int);
+    method public void onNotificationClick(java.lang.String, long);
+    method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    method public void onNotificationRemoved(java.lang.String, long, int);
+    method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
+    method public final void setAnnotation(java.lang.String, android.app.Notification);
+    field public static final int REASON_APP_CANCEL = 8; // 0x8
+    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
+    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
+    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
+    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
+    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
+    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
+    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
+    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
+    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+    field public static final int REASON_USER_STOPPED = 6; // 0x6
+  }
+
+  public class NotificationAssistantService.Adjustment {
+    ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
+  }
+
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -33184,11 +33217,19 @@
 
   public static class NotificationListenerService.Ranking {
     ctor public NotificationListenerService.Ranking();
+    method public int getImportance();
+    method public java.lang.CharSequence getImportanceExplanation();
     method public java.lang.String getKey();
     method public int getRank();
     method public int getSuppressedVisualEffects();
     method public boolean isAmbient();
     method public boolean matchesInterruptionFilter();
+    field public static final int IMPORTANCE_DEFAULT = 0; // 0x0
+    field public static final int IMPORTANCE_HIGH = 1; // 0x1
+    field public static final int IMPORTANCE_LOW = -1; // 0xffffffff
+    field public static final int IMPORTANCE_MAX = 2; // 0x2
+    field public static final int IMPORTANCE_NONE = -2; // 0xfffffffe
+    field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
   }
 
   public static class NotificationListenerService.RankingMap implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index f509b05..6e15f93 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -41,6 +41,7 @@
     field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
     field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
+    field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -133,6 +134,7 @@
     field public static final java.lang.String MODIFY_AUDIO_ROUTING = "android.permission.MODIFY_AUDIO_ROUTING";
     field public static final java.lang.String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS";
     field public static final java.lang.String MODIFY_CELL_BROADCASTS = "android.permission.MODIFY_CELL_BROADCASTS";
+    field public static final java.lang.String MODIFY_DAY_NIGHT_MODE = "android.permission.MODIFY_DAY_NIGHT_MODE";
     field public static final java.lang.String MODIFY_NETWORK_ACCOUNTING = "android.permission.MODIFY_NETWORK_ACCOUNTING";
     field public static final java.lang.String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS";
     field public static final java.lang.String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
@@ -5648,6 +5650,8 @@
     method public void enableCarMode(int);
     method public int getCurrentModeType();
     method public int getNightMode();
+    method public boolean isNightModeLocked();
+    method public boolean isUiModeLocked();
     method public void setNightMode(int);
     field public static java.lang.String ACTION_ENTER_CAR_MODE;
     field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -8542,6 +8546,7 @@
     field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
     field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
     field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
+    field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
     field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
@@ -35265,6 +35270,35 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
+  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+    ctor public NotificationAssistantService();
+    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
+    method public final void clearAnnotation(java.lang.String);
+    method public void onNotificationActionClick(java.lang.String, long, int);
+    method public void onNotificationClick(java.lang.String, long);
+    method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    method public void onNotificationRemoved(java.lang.String, long, int);
+    method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
+    method public final void setAnnotation(java.lang.String, android.app.Notification);
+    field public static final int REASON_APP_CANCEL = 8; // 0x8
+    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
+    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
+    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
+    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
+    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
+    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
+    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
+    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
+    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+    field public static final int REASON_USER_STOPPED = 6; // 0x6
+  }
+
+  public class NotificationAssistantService.Adjustment {
+    ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
+  }
+
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -35308,11 +35342,19 @@
 
   public static class NotificationListenerService.Ranking {
     ctor public NotificationListenerService.Ranking();
+    method public int getImportance();
+    method public java.lang.CharSequence getImportanceExplanation();
     method public java.lang.String getKey();
     method public int getRank();
     method public int getSuppressedVisualEffects();
     method public boolean isAmbient();
     method public boolean matchesInterruptionFilter();
+    field public static final int IMPORTANCE_DEFAULT = 0; // 0x0
+    field public static final int IMPORTANCE_HIGH = 1; // 0x1
+    field public static final int IMPORTANCE_LOW = -1; // 0xffffffff
+    field public static final int IMPORTANCE_MAX = 2; // 0x2
+    field public static final int IMPORTANCE_NONE = -2; // 0xfffffffe
+    field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
   }
 
   public static class NotificationListenerService.RankingMap implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 299b38a..fba944c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -28,6 +28,7 @@
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
+    field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -5529,6 +5530,8 @@
     method public void enableCarMode(int);
     method public int getCurrentModeType();
     method public int getNightMode();
+    method public boolean isNightModeLocked();
+    method public boolean isUiModeLocked();
     method public void setNightMode(int);
     field public static java.lang.String ACTION_ENTER_CAR_MODE;
     field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -8285,6 +8288,7 @@
     field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
     field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
     field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
+    field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
     field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
@@ -33150,6 +33154,35 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
+  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+    ctor public NotificationAssistantService();
+    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
+    method public final void clearAnnotation(java.lang.String);
+    method public void onNotificationActionClick(java.lang.String, long, int);
+    method public void onNotificationClick(java.lang.String, long);
+    method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    method public void onNotificationRemoved(java.lang.String, long, int);
+    method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
+    method public final void setAnnotation(java.lang.String, android.app.Notification);
+    field public static final int REASON_APP_CANCEL = 8; // 0x8
+    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
+    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
+    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
+    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
+    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
+    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
+    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
+    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
+    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+    field public static final int REASON_USER_STOPPED = 6; // 0x6
+  }
+
+  public class NotificationAssistantService.Adjustment {
+    ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
+  }
+
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -33186,11 +33219,19 @@
 
   public static class NotificationListenerService.Ranking {
     ctor public NotificationListenerService.Ranking();
+    method public int getImportance();
+    method public java.lang.CharSequence getImportanceExplanation();
     method public java.lang.String getKey();
     method public int getRank();
     method public int getSuppressedVisualEffects();
     method public boolean isAmbient();
     method public boolean matchesInterruptionFilter();
+    field public static final int IMPORTANCE_DEFAULT = 0; // 0x0
+    field public static final int IMPORTANCE_HIGH = 1; // 0x1
+    field public static final int IMPORTANCE_LOW = -1; // 0xffffffff
+    field public static final int IMPORTANCE_MAX = 2; // 0x2
+    field public static final int IMPORTANCE_NONE = -2; // 0xfffffffe
+    field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
   }
 
   public static class NotificationListenerService.RankingMap implements android.os.Parcelable {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 74f0c0e..c264368 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4841,7 +4841,7 @@
         if (ii != null) {
             final ApplicationInfo instrApp = new ApplicationInfo();
             ii.copyTo(instrApp);
-
+            instrApp.initForUser(UserHandle.myUserId());
             final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                     appContext.getClassLoader(), false, true, false);
             final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl
index 7e9873e..cae54b6 100644
--- a/core/java/android/app/IUiModeManager.aidl
+++ b/core/java/android/app/IUiModeManager.aidl
@@ -51,4 +51,14 @@
      * 2 for night, and 3 for automatic mode switching.
      */
     int getNightMode();
+
+    /**
+     * Tells if UI mode is locked or not.
+     */
+    boolean isUiModeLocked();
+
+    /**
+     * Tells if Night mode is locked or not.
+     */
+    boolean isNightModeLocked();
 }
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 0f6ce12..44164158 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -233,4 +233,35 @@
         }
         return -1;
     }
+
+    /**
+     * @return If UI mode is locked or not. When UI mode is locked, calls to change UI mode
+     *         like {@link #enableCarMode(int)} will silently fail.
+     */
+    public boolean isUiModeLocked() {
+        if (mService != null) {
+            try {
+                return mService.isUiModeLocked();
+            } catch (RemoteException e) {
+                Log.e(TAG, "isUiModeLocked: RemoteException", e);
+            }
+        }
+        return true;
+    }
+
+    /**
+     * @return If Night mode is locked or not. When Night mode is locked, changing Night mode
+     *         is only allowed to privileged system components and normal application's call
+     *         to change Night mode using {@link #setNightMode(int)} will silently fail.
+     */
+    public boolean isNightModeLocked() {
+        if (mService != null) {
+            try {
+                return mService.isNightModeLocked();
+            } catch (RemoteException e) {
+                Log.e(TAG, "isNightModeLocked: RemoteException", e);
+            }
+        }
+        return true;
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index d27dfa0..cd5c205 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -25,6 +25,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.ParcelUuid;
+import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -823,6 +824,9 @@
             return false;
         }
         try {
+            Log.i(TAG, "createBond() for device " + getAddress() +
+                    " called by pid: " + Process.myPid() +
+                    " tid: " + Process.myTid());
             return sService.createBond(this, TRANSPORT_AUTO);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
@@ -854,6 +858,9 @@
             throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport");
         }
         try {
+            Log.i(TAG, "createBond() for device " + getAddress() +
+                    " called by pid: " + Process.myPid() +
+                    " tid: " + Process.myTid());
             return sService.createBond(this, transport);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
@@ -922,6 +929,9 @@
             return false;
         }
         try {
+            Log.i(TAG, "cancelBondProcess() for device " + getAddress() +
+                    " called by pid: " + Process.myPid() +
+                    " tid: " + Process.myTid());
             return sService.cancelBondProcess(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
@@ -943,6 +953,9 @@
             return false;
         }
         try {
+            Log.i(TAG, "removeBond() for device " + getAddress() +
+                    " called by pid: " + Process.myPid() +
+                    " tid: " + Process.myTid());
             return sService.removeBond(this);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 853bc6c..9d0ebc2 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -986,6 +986,7 @@
                         stableProvider = acquireProvider(uri);
                     }
                     releaseUnstableProvider(unstableProvider);
+                    unstableProvider = null;
                     ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
                             fd.getParcelFileDescriptor(), stableProvider);
 
@@ -1130,6 +1131,7 @@
                 stableProvider = acquireProvider(uri);
             }
             releaseUnstableProvider(unstableProvider);
+            unstableProvider = null;
             ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
                     fd.getParcelFileDescriptor(), stableProvider);
 
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2178c38..b65d825 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1926,6 +1926,24 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_ALARM_CHANGED = "android.intent.action.ALARM_CHANGED";
+
+    /**
+     * Broadcast Action: This is broadcast once, after the system has finished
+     * booting and the user is in a "locked" state. A user is locked when their
+     * credential-encrypted private app data storage is unavailable. Once the
+     * user has entered their credentials (such as a lock pattern or PIN) for
+     * the first time, the {@link #ACTION_BOOT_COMPLETED} broadcast will be
+     * sent.
+     * <p>
+     * You must hold the
+     * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission in
+     * order to receive this broadcast.
+     * <p class="note">
+     * This is a protected intent that can only be sent by the system.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
+
     /**
      * Broadcast Action: This is broadcast once, after the system has finished
      * booting.  It can be used to perform application-specific initialization,
@@ -1938,6 +1956,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
+
     /**
      * Broadcast Action: This is broadcast when a user action should request a
      * temporary system dialog to dismiss.  Some examples of temporary system
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 8b2c74f..f1672df 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1931,9 +1931,9 @@
                 // so we'll report it and bail on all of the current strict mode violations
                 // we currently are maintaining for this thread.
                 // First, drain the remaining violations from the parcel.
-                while (i < numViolations) {
+                i++;  // Skip the current entry.
+                for (; i < numViolations; i++) {
                     info = new ViolationInfo(p, !currentlyGathering);
-                    i++;
                 }
                 // Next clear out all gathered violations.
                 clearGatheredViolations();
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
new file mode 100644
index 0000000..5d1317c
--- /dev/null
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import android.app.Notification;
+import android.net.Uri;
+
+/**
+ * A service that helps the user manage notifications by modifying the
+ * relative importance of notifications.
+ * <p>To extend this class, you must declare the service in your manifest file with
+ * the {@link android.Manifest.permission#BIND_NOTIFICATION_ASSISTANT_SERVICE} permission
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
+ * <pre>
+ * &lt;service android:name=".NotificationAssistant"
+ *          android:label="&#64;string/service_name"
+ *          android:permission="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE">
+ *     &lt;intent-filter>
+ *         &lt;action android:name="android.service.notification.NotificationAssistantService" />
+ *     &lt;/intent-filter>
+ * &lt;/service></pre>
+ */
+public abstract class NotificationAssistantService extends NotificationListenerService {
+    /** Notification was canceled by the status bar reporting a click. */
+    public static final int REASON_DELEGATE_CLICK = 1;
+
+    /** Notification was canceled by the status bar reporting a user dismissal. */
+    public static final int REASON_DELEGATE_CANCEL = 2;
+
+    /** Notification was canceled by the status bar reporting a user dismiss all. */
+    public static final int REASON_DELEGATE_CANCEL_ALL = 3;
+
+    /** Notification was canceled by the status bar reporting an inflation error. */
+    public static final int REASON_DELEGATE_ERROR = 4;
+
+    /** Notification was canceled by the package manager modifying the package. */
+    public static final int REASON_PACKAGE_CHANGED = 5;
+
+    /** Notification was canceled by the owning user context being stopped. */
+    public static final int REASON_USER_STOPPED = 6;
+
+    /** Notification was canceled by the user banning the package. */
+    public static final int REASON_PACKAGE_BANNED = 7;
+
+    /** Notification was canceled by the app canceling this specific notification. */
+    public static final int REASON_APP_CANCEL = 8;
+
+    /** Notification was canceled by the app cancelling all its notifications. */
+    public static final int REASON_APP_CANCEL_ALL = 9;
+
+    /** Notification was canceled by a listener reporting a user dismissal. */
+    public static final int REASON_LISTENER_CANCEL = 10;
+
+    /** Notification was canceled by a listener reporting a user dismiss all. */
+    public static final int REASON_LISTENER_CANCEL_ALL = 11;
+
+    /** Notification was canceled because it was a member of a canceled group. */
+    public static final int REASON_GROUP_SUMMARY_CANCELED = 12;
+
+    /** Notification was canceled because it was an invisible member of a group. */
+    public static final int REASON_GROUP_OPTIMIZATION = 13;
+
+    public class Adjustment {
+        int mImportance;
+        CharSequence mExplanation;
+        Uri mReference;
+
+        /**
+         * Create a notification importance adjustment.
+         *
+         * @param importance The final importance of the notification.
+         * @param explanation A human-readable justification for the adjustment.
+         * @param reference A reference to an external object that augments the
+         *                  explanation, such as a
+         *                  {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI},
+         *                  or null.
+         */
+        public Adjustment(int importance, CharSequence explanation, Uri reference) {
+            mImportance = importance;
+            mExplanation = explanation;
+            mReference = reference;
+        }
+    }
+
+    /**
+     * A notification was posted by an app. Called before alert.
+     *
+     * @param sbn the new notification
+     * @param importance the initial importance of the notification.
+     * @param user true if the initial importance reflects an explicit user preference.
+     * @return an adjustment or null to take no action, within 100ms.
+     */
+    abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
+          int importance, boolean user);
+
+    /**
+     * The visibility of a notification has changed.
+     *
+     * @param key the notification key
+     * @param time milliseconds since midnight, January 1, 1970 UTC.
+     * @param visible true if the notification became visible, false if hidden.
+     */
+    public void onNotificationVisibilityChanged(String key, long time, boolean visible)
+    {
+        // Do nothing, Override this to collect visibility statistics.
+    }
+
+    /**
+     * The user clicked on a notification.
+     *
+     * @param key the notification key
+     * @param time milliseconds since midnight, January 1, 1970 UTC.
+     */
+    public void onNotificationClick(String key, long time)
+    {
+        // Do nothing, Override this to collect click statistics
+    }
+
+    /**
+     * The user clicked on a notification action.
+     *
+     * @param key the notification key
+     * @param time milliseconds since midnight, January 1, 1970 UTC.
+     * @param actionIndex the index of the action button that was pressed.
+     */
+    public void onNotificationActionClick(String key, long time, int actionIndex)
+    {
+        // Do nothing, Override this to collect action button click statistics
+    }
+
+    /**
+     * A notification was removed.
+
+     * @param key the notification key
+     * @param time milliseconds since midnight, January 1, 1970 UTC.
+     * @param reason see {@link #REASON_LISTENER_CANCEL}, etc.
+     */
+    public void onNotificationRemoved(String key, long time, int reason) {
+        // Do nothing, Override this to collect dismissal statistics
+    }
+
+    /**
+     * Change the importance of an existing notification.  N.B. this won’t cause
+     * an existing notification to alert, but might allow a future update to
+     * this notification to alert.
+     *
+     * @param key the notification key
+     * @param adjustment the new importance with an explanation
+     */
+    public final void adjustImportance(String key, Adjustment adjustment)
+    {
+        // TODO: pack up the adjustment and send it to the NotificationManager.
+    }
+
+    /**
+     * Add an annotation to a an existing notification. The delete intent will
+     * be fired when the host notification is deleted, or when this annotation
+     * is removed or replaced.
+     *
+     * @param key the notification key
+     * @param annotation the new annotation object
+     */
+    public final void setAnnotation(String key, Notification annotation)
+    {
+        // TODO: pack up the annotation and send it to the NotificationManager.
+    }
+
+    /**
+     * Remove the annotation from a notification.
+     *
+     * @param key the notification key
+     */
+    public final void clearAnnotation(String key)
+    {
+        // TODO: ask the NotificationManager to clear the annotation.
+    }
+}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index ee97e8e..d741f1a 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -822,6 +822,41 @@
          * @hide */
         public static final int VISIBILITY_NO_OVERRIDE = -1000;
 
+        /**
+         * Value signifying thatn the has not expressed an importance.
+         *
+         * This value is for persisting preferences, and should never ve associated with
+         * an actual notification.
+         */
+        public static final int IMPORTANCE_UNSPECIFIED = -1000;
+
+        /**
+         * A notification with no importance: shows nowhere, is blocked.
+         */
+        public static final int IMPORTANCE_NONE = -2;
+
+        /**
+         * Low notification importance: only shows in the shade, below the fold.
+         */
+        public static final int IMPORTANCE_LOW = -1;
+
+        /**
+         * Default notification importance: shows everywhere, but is not intrusive.
+         */
+        public static final int IMPORTANCE_DEFAULT = 0;
+
+        /**
+         * Higher notification importance: shows everywhere, makes noise,
+         * but does not visually intrude.
+         */
+        public static final int IMPORTANCE_HIGH = 1;
+
+        /**
+         * Highest notification importance: shows everywhere, makes noise,
+         * and also visually intrudes.
+         */
+        public static final int IMPORTANCE_MAX = 2;
+
         private String mKey;
         private int mRank = -1;
         private boolean mIsAmbient;
@@ -875,7 +910,6 @@
             return mSuppressedVisualEffects;
         }
 
-
         /**
          * Returns whether the notification matches the user's interruption
          * filter.
@@ -887,6 +921,27 @@
             return mMatchesInterruptionFilter;
         }
 
+        /**
+         * Returns the importance of the notification, which dictates its
+         * modes of presentation, see: {@link #IMPORTANCE_DEFAULT}, etc.
+         *
+         * @return the rank of the notification
+         */
+        public int getImportance() {
+            return IMPORTANCE_DEFAULT;  // TODO implement;
+        }
+
+        /**
+         * If the importance has been overriden by user preference, or by a
+         * {@link NotificationAssistantService}, then this will be non-null,
+         * and should be displayed to the user.
+         *
+         * @return the explanation for the importance, or null if it is the natural importance
+         */
+        public CharSequence getImportanceExplanation() {
+            return null;  // TODO implement
+        }
+
         private void populate(String key, int rank, boolean isAmbient,
                 boolean matchesInterruptionFilter, int visibilityOverride,
                 int suppressedVisualEffects) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3669d97..fc347ea 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3057,14 +3057,29 @@
     /**
      * @hide
      *
-     * Makes system ui transparent.
+     * Makes navigation bar transparent (but not the status bar).
      */
-    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
+    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
+
+    /**
+     * @hide
+     *
+     * Makes status bar transparent (but not the navigation bar).
+     */
+    public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
+
+    /**
+     * @hide
+     *
+     * Makes both status bar and navigation bar transparent.
+     */
+    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
+            | STATUS_BAR_TRANSPARENT;
 
     /**
      * @hide
      */
-    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
+    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
 
     /**
      * These are the system UI flags that can be cleared by events outside
@@ -5505,20 +5520,26 @@
     }
 
     /**
-     * Bring up the context menu for this view.
+     * Shows the context menu for this view.
      *
-     * @return Whether a context menu was displayed.
+     * @return {@code true} if the context menu was shown, {@code false}
+     *         otherwise
+     * @see #showContextMenu(float, float)
      */
     public boolean showContextMenu() {
         return getParent().showContextMenuForChild(this);
     }
 
     /**
-     * Bring up the context menu for this view, referring to the item under the specified point.
+     * Shows the context menu for this view anchored to the specified
+     * view-relative coordinate.
      *
-     * @param x The referenced x coordinate.
-     * @param y The referenced y coordinate.
-     * @return Whether a context menu was displayed.
+     * @param x the X coordinate in pixels relative to the view to which the
+     *          menu should be anchored
+     * @param y the Y coordinate in pixels relative to the view to which the
+     *          menu should be anchored
+     * @return {@code true} if the context menu was shown, {@code false}
+     *         otherwise
      */
     public boolean showContextMenu(float x, float y) {
         return getParent().showContextMenuForChild(this, x, y);
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 6ae448a..f2ab35e 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -174,26 +174,38 @@
     public void focusableViewAvailable(View v);
 
     /**
-     * Bring up a context menu for the specified view or its ancestors.
-     *
-     * <p>In most cases, a subclass does not need to override this.  However, if
+     * Shows the context menu for the specified view or its ancestors.
+     * <p>
+     * In most cases, a subclass does not need to override this. However, if
      * the subclass is added directly to the window manager (for example,
      * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
-     * then it should override this and show the context menu.</p>
-     * 
-     * @param originalView The source view where the context menu was first invoked
-     * @return true if a context menu was displayed
+     * then it should override this and show the context menu.
+     *
+     * @param originalView the source view where the context menu was first
+     *                     invoked
+     * @return {@code true} if the context menu was shown, {@code false}
+     *         otherwise
+     * @see #showContextMenuForChild(View, float, float)
      */
     public boolean showContextMenuForChild(View originalView);
 
     /**
-     * Bring up a context menu for the specified view at the given x/y offset from
-     * the top left corner.
+     * Shows the context menu for the specified view or its ancestors anchored
+     * to the specified view-relative coordinate.
+     * <p>
+     * In most cases, a subclass does not need to override this. However, if
+     * the subclass is added directly to the window manager (for example,
+     * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
+     * then it should override this and show the context menu.
      *
-     * @param originalView
-     * @param x The x offset at which to open the menu
-     * @param y The y offset at which to open the menu
-     * @return true if a context menu was displayed
+     * @param originalView the source view where the context menu was first
+     *                     invoked
+     * @param x the X coordinate in pixels relative to the original view to
+     *          which the menu should be anchored
+     * @param y the Y coordinate in pixels relative to the original view to
+     *          which the menu should be anchored
+     * @return {@code true} if the context menu was shown, {@code false}
+     *         otherwise
      */
     public boolean showContextMenuForChild(View originalView, float x, float y);
 
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index 41f1ce7..0032f17 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -933,7 +933,7 @@
             super(context, menu, anchorView, overflowOnly,
                     com.android.internal.R.attr.actionOverflowMenuStyle);
             setGravity(Gravity.END);
-            setCallback(mPopupPresenterCallback);
+            setPresenterCallback(mPopupPresenterCallback);
         }
 
         @Override
@@ -956,7 +956,7 @@
                 setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton);
             }
 
-            setCallback(mPopupPresenterCallback);
+            setPresenterCallback(mPopupPresenterCallback);
         }
 
         @Override
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 01ac22e..f0c1094 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -371,17 +371,17 @@
         }
         // TODO: Use {@link Locale#toLanguageTag()} and {@link Locale#forLanguageTag(languageTag)}.
         String[] localeParams = localeStr.split("_", 3);
+        if (localeParams.length >= 1 && "tl".equals(localeParams[0])) {
+             // Convert a locale whose language is "tl" to one whose language is "fil".
+             // For example, "tl_PH" will get converted to "fil_PH".
+             // Versions of Android earlier than Lollipop did not support three letter language
+             // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino).
+             // On Lollipop and above, the current three letter version must be used.
+             localeParams[0] = "fil";
+        }
         // The length of localeStr is guaranteed to always return a 1 <= value <= 3
         // because localeStr is not empty.
         if (localeParams.length == 1) {
-            if (localeParams.length >= 1 && "tl".equals(localeParams[0])) {
-                // Convert a locale whose language is "tl" to one whose language is "fil".
-                // For example, "tl_PH" will get converted to "fil_PH".
-                // Versions of Android earlier than Lollipop did not support three letter language
-                // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino).
-                // On Lollipop and above, the current three letter version must be used.
-                localeParams[0] = "fil";
-            }
             return new Locale(localeParams[0]);
         } else if (localeParams.length == 2) {
             return new Locale(localeParams[0], localeParams[1]);
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index b101733..75ca639 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -17,6 +17,7 @@
 package com.android.internal.policy;
 
 import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Looper;
 import android.view.Choreographer;
@@ -44,6 +45,7 @@
     // The render nodes for the multi threaded renderer.
     private ThreadedRenderer mRenderer;
     private RenderNode mFrameAndBackdropNode;
+    private RenderNode mSystemBarBackgroundNode;
 
     private final Rect mOldTargetRect = new Rect();
     private final Rect mNewTargetRect = new Rect();
@@ -62,13 +64,16 @@
 
     private Drawable mCaptionBackgroundDrawable;
     private Drawable mResizingBackgroundDrawable;
+    private ColorDrawable mStatusBarColor;
 
     public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
-            Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable) {
+            Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
+            int statusBarColor) {
         setName("ResizeFrame");
 
         mRenderer = renderer;
-        onResourcesLoaded(decorView, resizingBackgroundDrawable, captionBackgroundDrawable);
+        onResourcesLoaded(decorView, resizingBackgroundDrawable, captionBackgroundDrawable,
+                statusBarColor);
 
         // Create a render node for the content and frame backdrop
         // which can be resized independently from the content.
@@ -87,10 +92,24 @@
     }
 
     void onResourcesLoaded(DecorView decorView, Drawable resizingBackgroundDrawable,
-            Drawable captionBackgroundDrawableDrawable) {
+            Drawable captionBackgroundDrawableDrawable, int statusBarColor) {
         mDecorView = decorView;
         mResizingBackgroundDrawable = resizingBackgroundDrawable;
         mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable;
+        if (statusBarColor != 0) {
+            mStatusBarColor = new ColorDrawable(statusBarColor);
+            addSystemBarNodeIfNeeded();
+        } else {
+            mStatusBarColor = null;
+        }
+    }
+
+    private void addSystemBarNodeIfNeeded() {
+        if (mSystemBarBackgroundNode != null) {
+            return;
+        }
+        mSystemBarBackgroundNode = RenderNode.create("SystemBarBackgroundNode", null);
+        mRenderer.addRenderNode(mSystemBarBackgroundNode, false);
     }
 
     /**
@@ -132,6 +151,9 @@
                 // Remove the render node again
                 // (see comment above - better to do that only once).
                 mRenderer.removeRenderNode(mFrameAndBackdropNode);
+                if (mSystemBarBackgroundNode != null) {
+                    mRenderer.removeRenderNode(mSystemBarBackgroundNode);
+                }
 
                 mRenderer = null;
 
@@ -232,6 +254,8 @@
         // inaccessible. For that case we remember the previous metrics to avoid flashes.
         // Note that even when there is no visible caption, the caption child will exist.
         final int captionHeight = mDecorView.getCaptionHeight();
+        final int statusBarHeight = mDecorView.getStatusBarHeight();
+
         // The caption height will probably never dynamically change while we are resizing.
         // Once set to something other then 0 it should be kept that way.
         if (captionHeight != 0) {
@@ -256,7 +280,7 @@
         mFrameAndBackdropNode.setLeftTopRightBottom(left, top, left + width, top + height);
 
         // Draw the caption and content backdrops in to our render node.
-        final DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
+        DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
         mCaptionBackgroundDrawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
         mCaptionBackgroundDrawable.draw(canvas);
 
@@ -265,6 +289,15 @@
         mResizingBackgroundDrawable.draw(canvas);
         mFrameAndBackdropNode.end(canvas);
 
+        if (mSystemBarBackgroundNode != null && mStatusBarColor != null) {
+            canvas = mSystemBarBackgroundNode.start(width, height);
+            mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
+            mStatusBarColor.setBounds(0, 0, left + width, statusBarHeight);
+            mStatusBarColor.draw(canvas);
+            mSystemBarBackgroundNode.end(canvas);
+            mRenderer.drawRenderNode(mSystemBarBackgroundNode);
+        }
+
         // We need to render the node explicitly
         mRenderer.drawRenderNode(mFrameAndBackdropNode);
 
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 27fe03c..9107b1f 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -21,8 +21,7 @@
 import com.android.internal.view.RootViewSurfaceTaker;
 import com.android.internal.view.StandaloneActionMode;
 import com.android.internal.view.menu.ContextMenuBuilder;
-import com.android.internal.view.menu.MenuDialogHelper;
-import com.android.internal.view.menu.MenuPopupHelper;
+import com.android.internal.view.menu.MenuHelper;
 import com.android.internal.widget.ActionBarContextView;
 import com.android.internal.widget.BackgroundFallback;
 import com.android.internal.widget.DecorCaptionView;
@@ -152,6 +151,8 @@
     private final Interpolator mShowInterpolator;
     private final Interpolator mHideInterpolator;
     private final int mBarEnterExitDuration;
+    private final boolean mForceWindowDrawsStatusBarBackground;
+    private final int mSemiTransparentStatusBarColor;
 
     private final BackgroundFallback mBackgroundFallback = new BackgroundFallback();
 
@@ -198,6 +199,10 @@
 
         mBarEnterExitDuration = context.getResources().getInteger(
                 R.integer.dock_enter_exit_duration);
+        mForceWindowDrawsStatusBarBackground = context.getResources().getBoolean(
+                R.bool.config_forceWindowDrawsStatusBarBackground);
+        mSemiTransparentStatusBarColor = context.getResources().getColor(
+                R.color.system_bar_background_semi_transparent, null /* theme */);
 
         setWindow(window);
     }
@@ -659,30 +664,23 @@
 
     @Override
     public boolean showContextMenuForChild(View originalView) {
-        // Reuse the context menu builder
-        if (mWindow.mContextMenu == null) {
-            mWindow.mContextMenu = new ContextMenuBuilder(getContext());
-            mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
-        } else {
-            mWindow.mContextMenu.clearAll();
-        }
-
-        final MenuDialogHelper helper = mWindow.mContextMenu.show(originalView,
-                originalView.getWindowToken());
-        if (helper != null) {
-            helper.setPresenterCallback(mWindow.mContextMenuCallback);
-        } else if (mWindow.mContextMenuHelper != null) {
-            // No menu to show, but if we have a menu currently showing it just became blank.
-            // Close it.
-            mWindow.mContextMenuHelper.dismiss();
-        }
-        mWindow.mContextMenuHelper = helper;
-        return helper != null;
+        return showContextMenuForChildInternal(originalView, 0, 0, false);
     }
 
     @Override
     public boolean showContextMenuForChild(View originalView, float x, float y) {
-        // Reuse the context menu builder
+        return showContextMenuForChildInternal(originalView, x, y, true);
+    }
+
+    private boolean showContextMenuForChildInternal(View originalView,
+            float x, float y, boolean isPopup) {
+        // Only allow one context menu at a time.
+        if (mWindow.mContextMenuHelper != null) {
+            mWindow.mContextMenuHelper.dismiss();
+            mWindow.mContextMenuHelper = null;
+        }
+
+        // Reuse the context menu builder.
         if (mWindow.mContextMenu == null) {
             mWindow.mContextMenu = new ContextMenuBuilder(getContext());
             mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
@@ -690,16 +688,18 @@
             mWindow.mContextMenu.clearAll();
         }
 
-        final MenuPopupHelper helper = mWindow.mContextMenu.showPopup(
-                getContext(), originalView, x, y);
-        if (helper != null) {
-            helper.setCallback(mWindow.mContextMenuCallback);
-        } else if (mWindow.mContextMenuPopupHelper != null) {
-            // No menu to show, but if we have a menu currently showing it just became blank.
-            // Close it.
-            mWindow.mContextMenuPopupHelper.dismiss();
+        final MenuHelper helper;
+        if (isPopup) {
+            helper = mWindow.mContextMenu.showPopup(getContext(), originalView, x, y);
+        } else {
+            helper = mWindow.mContextMenu.showDialog(originalView, originalView.getWindowToken());
         }
-        mWindow.mContextMenuPopupHelper = helper;
+
+        if (helper != null) {
+            helper.setPresenterCallback(mWindow.mContextMenuCallback);
+        }
+
+        mWindow.mContextMenuHelper = helper;
         return helper != null;
     }
 
@@ -890,14 +890,15 @@
             int navBarSize = navBarToRightEdge ? mLastRightInset : mLastBottomInset;
             updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
                     mWindow.mNavigationBarColor, navBarSize, navBarToRightEdge,
-                    0 /* rightInset */, animate && !disallowAnimate);
+                    0 /* rightInset */, animate && !disallowAnimate, false /* force */);
 
             boolean statusBarNeedsRightInset = navBarToRightEdge
                     && mNavigationColorViewState.present;
             int statusBarRightInset = statusBarNeedsRightInset ? mLastRightInset : 0;
-            updateColorViewInt(mStatusColorViewState, sysUiVisibility, mWindow.mStatusBarColor,
-                    mLastTopInset, false /* matchVertical */, statusBarRightInset,
-                    animate && !disallowAnimate);
+            updateColorViewInt(mStatusColorViewState, sysUiVisibility,
+                    calculateStatusBarColor(), mLastTopInset,
+                    false /* matchVertical */, statusBarRightInset, animate && !disallowAnimate,
+                    mForceWindowDrawsStatusBarBackground);
         }
 
         // When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, we still need
@@ -941,6 +942,21 @@
         return insets;
     }
 
+    private int calculateStatusBarColor() {
+        int flags = mWindow.getAttributes().flags;
+        return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? mSemiTransparentStatusBarColor
+                : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? mWindow.mStatusBarColor
+                : Color.BLACK;
+    }
+
+    private int getCurrentColor(ColorViewState state) {
+        if (state.visible) {
+            return state.color;
+        } else {
+            return 0;
+        }
+    }
+
     /**
      * Update a color view
      *
@@ -954,13 +970,15 @@
      * @param animate if true, the change will be animated.
      */
     private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
-            int size, boolean verticalBar, int rightMargin, boolean animate) {
+            int size, boolean verticalBar, int rightMargin, boolean animate, boolean force) {
         state.present = size > 0 && (sysUiVis & state.systemUiHideFlag) == 0
                 && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
-                && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+                && ((mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+                        || force);
         boolean show = state.present
                 && (color & Color.BLACK) != 0
-                && (mWindow.getAttributes().flags & state.translucentFlag) == 0;
+                && ((mWindow.getAttributes().flags & state.translucentFlag) == 0  || force);
+        boolean showView = show && !isResizing();
 
         boolean visibilityChanged = false;
         View view = state.view;
@@ -970,7 +988,7 @@
         int resolvedGravity = verticalBar ? state.horizontalGravity : state.verticalGravity;
 
         if (view == null) {
-            if (show) {
+            if (showView) {
                 state.view = view = new View(mContext);
                 view.setBackgroundColor(color);
                 view.setTransitionName(state.transitionName);
@@ -986,7 +1004,7 @@
                 updateColorViewTranslations();
             }
         } else {
-            int vis = show ? VISIBLE : INVISIBLE;
+            int vis = showView ? VISIBLE : INVISIBLE;
             visibilityChanged = state.targetVisibility != vis;
             state.targetVisibility = vis;
             LayoutParams lp = (LayoutParams) view.getLayoutParams();
@@ -998,14 +1016,14 @@
                 lp.rightMargin = rightMargin;
                 view.setLayoutParams(lp);
             }
-            if (show) {
+            if (showView) {
                 view.setBackgroundColor(color);
             }
         }
         if (visibilityChanged) {
             view.animate().cancel();
-            if (animate) {
-                if (show) {
+            if (animate && !isResizing()) {
+                if (showView) {
                     if (view.getVisibility() != VISIBLE) {
                         view.setVisibility(VISIBLE);
                         view.setAlpha(0.0f);
@@ -1025,9 +1043,11 @@
                 }
             } else {
                 view.setAlpha(1.0f);
-                view.setVisibility(show ? VISIBLE : INVISIBLE);
+                view.setVisibility(showView ? VISIBLE : INVISIBLE);
             }
         }
+        state.visible = show;
+        state.color = color;
     }
 
     private void updateColorViewTranslations() {
@@ -1559,7 +1579,8 @@
 
         if (mBackdropFrameRenderer != null) {
             mBackdropFrameRenderer.onResourcesLoaded(
-                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable);
+                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
+                    getCurrentColor(mStatusColorViewState));
         }
 
         mDecorCaptionView = createDecorCaptionView(inflater);
@@ -1674,9 +1695,15 @@
         if (mDecorCaptionView != null) {
             mDecorCaptionView.removeContentView();
         } else {
-            // This window doesn't have caption, so we need to just remove the
-            // children of the decor view.
-            removeAllViews();
+            // This window doesn't have caption, so we need to remove everything except our views
+            // we might have added.
+            for (int i = getChildCount() - 1; i >= 0; i--) {
+                View v = getChildAt(i);
+                if (v != mStatusColorViewState.view && v != mNavigationColorViewState.view
+                        && v != mStatusGuard && v != mNavigationGuard) {
+                    removeViewAt(i);
+                }
+            }
         }
     }
 
@@ -1700,18 +1727,22 @@
         final ThreadedRenderer renderer = (ThreadedRenderer) getHardwareRenderer();
         if (renderer != null) {
             mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
-                    initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable);
+                    initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
+                    getCurrentColor(mStatusColorViewState));
 
             // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
             // If we want to get the shadow shown while resizing, we would need to elevate a new
             // element which owns the caption and has the elevation.
             updateElevation();
+
+            updateColorViews(null /* insets */, false);
         }
     }
 
     @Override
     public void onWindowDragResizeEnd() {
         releaseThreadedRenderer();
+        updateColorViews(null /* insets */, false);
     }
 
     @Override
@@ -1744,6 +1775,10 @@
         }
     }
 
+    private boolean isResizing() {
+        return mBackdropFrameRenderer != null;
+    }
+
     /**
      * The elevation gets set for the first time and the framework needs to be informed that
      * the surface layer gets created with the shadow size in mind.
@@ -1759,8 +1794,7 @@
         final boolean wasAdjustedForStack = mElevationAdjustedForStack;
         // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null)
         // since the shadow is bound to the content size and not the target size.
-        if (ActivityManager.StackId.hasWindowShadow(mStackId)
-                && mBackdropFrameRenderer == null) {
+        if (ActivityManager.StackId.hasWindowShadow(mStackId) && !isResizing()) {
             elevation = hasWindowFocus() ?
                     DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
             // TODO(skuhne): Remove this if clause once b/22668382 got fixed.
@@ -1790,6 +1824,10 @@
         return isShowingCaption() ? mDecorCaptionView.getCaptionHeight() : 0;
     }
 
+    int getStatusBarHeight() {
+        return mStatusColorViewState.view != null ? mStatusColorViewState.view.getHeight() : 0;
+    }
+
     /**
      * Converts a DIP measure into physical pixels.
      * @param dip The dip value.
@@ -1804,6 +1842,8 @@
         View view = null;
         int targetVisibility = View.INVISIBLE;
         boolean present = false;
+        boolean visible;
+        int color;
 
         final int id;
         final int systemUiHideFlag;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 6e7e5cf..57d2244 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -53,7 +53,7 @@
 import com.android.internal.view.menu.ListMenuPresenter;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuDialogHelper;
-import com.android.internal.view.menu.MenuPopupHelper;
+import com.android.internal.view.menu.MenuHelper;
 import com.android.internal.view.menu.MenuPresenter;
 import com.android.internal.view.menu.MenuView;
 import com.android.internal.widget.DecorContentParent;
@@ -232,8 +232,7 @@
     private boolean mAlwaysReadCloseOnTouchAttr = false;
 
     ContextMenuBuilder mContextMenu;
-    MenuDialogHelper mContextMenuHelper;
-    MenuPopupHelper mContextMenuPopupHelper;
+    MenuHelper mContextMenuHelper;
     private boolean mClosingActionMenu;
 
     private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
@@ -1103,10 +1102,6 @@
             mContextMenuHelper.dismiss();
             mContextMenuHelper = null;
         }
-        if (mContextMenuPopupHelper != null) {
-            mContextMenuPopupHelper.dismiss();
-            mContextMenuPopupHelper = null;
-        }
     }
 
     @Override
@@ -2411,6 +2406,13 @@
             setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE);
         }
 
+        if (!mForcedStatusBarColor) {
+            mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
+        }
+        if (!mForcedNavigationBarColor) {
+            mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
+        }
+
         // Non-floating windows on high end devices must put up decor beneath the system bars and
         // therefore must know about visibility changes of those.
         if (!mIsFloating && ActivityManager.isHighEndGfx()) {
@@ -2421,12 +2423,6 @@
                         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS & ~getForcedWindowFlags());
             }
         }
-        if (!mForcedStatusBarColor) {
-            mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
-        }
-        if (!mForcedNavigationBarColor) {
-            mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
-        }
         if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
             decor.setSystemUiVisibility(
                     decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
diff --git a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
index aaa1bf1..82f061c 100644
--- a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
@@ -17,7 +17,6 @@
 package com.android.internal.view.menu;
 
 import android.content.Context;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.IBinder;
 import android.util.EventLog;
@@ -35,7 +34,7 @@
  * <p>
  * To use this class, instantiate it via {@link #ContextMenuBuilder(Context)},
  * and optionally populate it with any of your custom items.  Finally,
- * call {@link #show(View, IBinder)} which will populate the menu
+ * call {@link #showDialog(View, IBinder)} which will populate the menu
  * with a view's context menu items and show the context menu.
  */
 public class ContextMenuBuilder extends MenuBuilder implements ContextMenu {
@@ -75,7 +74,7 @@
      * @return If the context menu was shown, the {@link MenuDialogHelper} for
      *         dismissing it. Otherwise, null.
      */
-    public MenuDialogHelper show(View originalView, IBinder token) {
+    public MenuDialogHelper showDialog(View originalView, IBinder token) {
         if (originalView != null) {
             // Let relevant views and their populate context listeners populate
             // the context menu
diff --git a/core/java/com/android/internal/view/menu/MenuDialogHelper.java b/core/java/com/android/internal/view/menu/MenuDialogHelper.java
index b9e0e40..ecab29f 100644
--- a/core/java/com/android/internal/view/menu/MenuDialogHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuDialogHelper.java
@@ -26,13 +26,10 @@
 import android.view.WindowManager;
 
 /**
- * Helper for menus that appear as Dialogs (context and submenus).
- * 
- * @hide
+ * Presents a menu as a modal dialog.
  */
-public class MenuDialogHelper implements DialogInterface.OnKeyListener,
-        DialogInterface.OnClickListener,
-        DialogInterface.OnDismissListener,
+public class MenuDialogHelper implements MenuHelper, DialogInterface.OnKeyListener,
+        DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
         MenuPresenter.Callback {
     private MenuBuilder mMenu;
     private AlertDialog mDialog;
@@ -125,6 +122,7 @@
 
     }
 
+    @Override
     public void setPresenterCallback(MenuPresenter.Callback cb) {
         mPresenterCallback = cb;
     }
@@ -134,6 +132,7 @@
      * 
      * @see Dialog#dismiss()
      */
+    @Override
     public void dismiss() {
         if (mDialog != null) {
             mDialog.dismiss();
diff --git a/core/java/com/android/internal/view/menu/MenuHelper.java b/core/java/com/android/internal/view/menu/MenuHelper.java
new file mode 100644
index 0000000..9534722
--- /dev/null
+++ b/core/java/com/android/internal/view/menu/MenuHelper.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 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.internal.view.menu;
+
+/**
+ * Interface for a helper capable of presenting a menu.
+ */
+public interface MenuHelper {
+    void setPresenterCallback(MenuPresenter.Callback cb);
+    void dismiss();
+}
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 59d5f94..044ee6e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -30,7 +30,7 @@
 /**
  * Presents a menu as a small, simple popup anchored to another view.
  */
-public class MenuPopupHelper {
+public class MenuPopupHelper implements MenuHelper {
     private final Context mContext;
 
     // Immutable cached popup menu properties.
@@ -244,6 +244,7 @@
     /**
      * Dismisses the popup, if showing.
      */
+    @Override
     public void dismiss() {
         if (isShowing()) {
             mPopup.dismiss();
@@ -270,7 +271,8 @@
         return mPopup != null && mPopup.isShowing();
     }
 
-    public void setCallback(@Nullable MenuPresenter.Callback cb) {
+    @Override
+    public void setPresenterCallback(@Nullable MenuPresenter.Callback cb) {
         mPresenterCallback = cb;
         if (mPopup != null) {
             mPopup.setCallback(cb);
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index caee0d2..6a5f6d8 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -245,7 +245,7 @@
             MenuPopupHelper subPopup = new MenuPopupHelper(
                     mContext, subMenu, mShownAnchorView, mOverflowOnly, mPopupStyleAttr,
                     mPopupStyleRes);
-            subPopup.setCallback(mPresenterCallback);
+            subPopup.setPresenterCallback(mPresenterCallback);
             subPopup.setForceShowIcon(mAdapter.getForceShowIcon());
 
             if (subPopup.tryShow()) {
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index c139cd7..ae109c6 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -711,6 +711,9 @@
             jniThrowException(env, "java/lang/RuntimeException",
                     "Not allowed to write file descriptors here");
             break;
+        case UNEXPECTED_NULL:
+            jniThrowNullPointerException(env, NULL);
+            break;
         case -EBADF:
             jniThrowException(env, "java/lang/RuntimeException",
                     "Bad file descriptor");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9bbbdca..ee493019 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2607,6 +2607,14 @@
     <permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by an {@link
+         android.service.notification.NotificationAssistantService},
+         to ensure that only the system can bind to it.
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"
+        android:protectionLevel="signature" />
+
     <!-- Must be required by a {@link
          android.service.chooser.ChooserTargetService}, to ensure that
          only the system can bind to it.
@@ -2712,6 +2720,13 @@
     <permission android:name="android.permission.DISPATCH_NFC_MESSAGE"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows changing day / night mode when system is configured with
+         config_lockDayNightMode set to true. If requesting app does not have permission,
+         it will be ignored.
+        @hide -->
+    <permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE"
+                android:protectionLevel="signature|privileged" />
+
     <!-- The system process is explicitly the only one allowed to launch the
          confirmation UI for full backup/restore -->
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 09a63aa..454e4b6 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -37,7 +37,7 @@
          Or string format of ApnSettingV3.
          note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
     <string-array translatable="false" name="config_tether_apndata">
-        <item>[ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,54</item>
+        <item>[ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,220,,DUN,IP,IP,true,0,,,,,,,gid,54</item>
         <item>[ApnSettingV3]Tethered Mobile Internet,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,50</item>
         <item>[ApnSettingV3]Tethered Public Mobile,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,4D4F</item>
     </string-array>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index dad68ba..af8ff2e 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -173,4 +173,7 @@
     <color name="Red_800">#ffb93221</color>
 
     <color name="chooser_service_row_background_color">#fff5f5f5</color>
+
+    <!-- Status bar color for semi transparent mode. -->
+    <color name="system_bar_background_semi_transparent">#66000000</color> <!-- 40% black -->
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d9e0472..ea6cf11 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -716,6 +716,13 @@
 
     <bool name="config_carDockEnablesAccelerometer">true</bool>
 
+    <!--  Control whether to launch Car dock home app when user presses home button or when
+          car dock intent is fired.
+          In mobile device, usually separate home app is expected in car mode, and this should be
+          enabled. But in environments like real car, default home app may be enough, and in that
+          case, this can be disabled (set to false). -->
+    <bool name="config_enableCarDockHomeLaunch">true</bool>
+
     <!-- HDMI behavior -->
 
     <!-- The number of degrees to rotate the display when the device has HDMI connected
@@ -733,6 +740,15 @@
          Any other values will have surprising consequences. -->
     <integer name="config_defaultUiModeType">1</integer>
 
+    <!--  Control whether to lock UI mode to what is selected from config_defaultUiModeType.
+          Once UI mode is locked, applications cannot change it anymore. -->
+    <bool name="config_lockUiMode">false</bool>
+
+    <!--  Control whether to lock day/night mode change from normal application. When it is
+          true, day / night mode change is only allowed to apps with MODIFY_DAY_NIGHT_MODE
+          permission. -->
+    <bool name="config_lockDayNightMode">false</bool>
+
     <!-- Control the default night mode to use when there is no other mode override set.
          One of the following values (see UiModeManager.java):
              0 - MODE_NIGHT_AUTO
@@ -2384,4 +2400,9 @@
          The duplication is necessary, because this information is used before the features are
          available to the system.-->
     <bool name="config_freeformWindowManagement">false</bool>
+
+    <!-- If set, this will force all windows to draw the status bar background, including the apps
+         that have not requested doing so (via the WindowManager.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
+         flag). -->
+    <bool name="config_forceWindowDrawsStatusBarBackground">true</bool>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3860f68..dd44997 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1476,11 +1476,14 @@
   <java-symbol type="bool" name="config_carDockEnablesAccelerometer" />
   <java-symbol type="bool" name="config_deskDockEnablesAccelerometer" />
   <java-symbol type="bool" name="config_disableMenuKeyInLockScreen" />
+  <java-symbol type="bool" name="config_enableCarDockHomeLaunch" />
   <java-symbol type="bool" name="config_enableLockBeforeUnlockScreen" />
   <java-symbol type="bool" name="config_enableLockScreenRotation" />
   <java-symbol type="bool" name="config_enableLockScreenTranslucentDecor" />
   <java-symbol type="bool" name="config_enableTranslucentDecor" />
   <java-symbol type="bool" name="config_lidControlsSleep" />
+  <java-symbol type="bool" name="config_lockDayNightMode" />
+  <java-symbol type="bool" name="config_lockUiMode" />
   <java-symbol type="bool" name="config_reverseDefaultRotation" />
   <java-symbol type="bool" name="config_showNavigationBar" />
   <java-symbol type="bool" name="config_supportAutoRotation" />
@@ -2344,6 +2347,8 @@
 
   <java-symbol type="string" name="config_packagedKeyboardName" />
   <java-symbol type="string" name="default_notification_topic_label" />
+  <java-symbol type="bool" name="config_forceWindowDrawsStatusBarBackground" />
+  <java-symbol type="color" name="system_bar_background_semi_transparent" />
 
   <!-- EditText suggestion popup. -->
   <java-symbol type="id" name="suggestionContainer" />
diff --git a/core/tests/coretests/apks/keyset/permUse/AndroidManifest.xml b/core/tests/coretests/apks/keyset/permUse/AndroidManifest.xml
index b7645b0..c56079f8 100644
--- a/core/tests/coretests/apks/keyset/permUse/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/permUse/AndroidManifest.xml
@@ -21,11 +21,11 @@
     <key-sets>
         <key-set android:name="A">
           <public-key android:name="keyA"
-                      android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJoN1Nsgqf0V4C/bbN8wo8O2X/S5D76+5Mb9mlIsHkUTUTbHCNk+LxHIUYLm89YbP9zImrV0bUHLUAZUyoMUCiMCAwEAAQ=="/>
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMpNthdOxud7roPDZMMomOqXgJJdRfIWpkKEqmC61Mv+Nf6QY3TorEwJeghjSmqj7IbBKrtvfQq4E2XJO1HuspmQO4Ng2gvn+r+6EwNfKc9k55d6s+27SR867jKurBbHNtZMG+tjL1yH4r+tNzcuJCsgyAFqLmxFdcxEwzNvREyRpoYc5RDR0mmTwkMCUhJ6CId1EYEKiCEdNzxv+fWPEb21u+/MWpleGCILs8kglRVb2q/WOzAAvGr4FY5plfaE6N+lr7+UschQ+aMi1+uqewo2o0qPFVmZP5hnwj55K4UMzu/NhhDqQQsX4cSGES1KgHo5MTqRqZjN/I7emw5pFQIDAQAB"/>
         </key-set>
         <key-set android:name="B">
           <public-key android:name="keyB"
-                      android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMTfQsY8UuXiXmvw/y7Tpr7HoyfAC0nE/8Qdk3ZtEr9asa5qqP0F6xzCI1PGVFV+WLVRwm6FdB9StENL5EKyQFcCAwEAAQ==" />
+                      android:value="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtGr5cL2N7ztHiHmphB1/1eq+43lEAmP36iiEJAfX+cVReGSPFXqNnnM8Vptd2boAe332lrFw9rKPmbkZA+jOTA==" />
         </key-set>
         <upgrade-key-set android:name="A"/>
         <upgrade-key-set android:name="B"/>
diff --git a/core/tests/coretests/apks/keyset/uA/AndroidManifest.xml b/core/tests/coretests/apks/keyset/uA/AndroidManifest.xml
index f31b75f..8c440f5 100644
--- a/core/tests/coretests/apks/keyset/uA/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/uA/AndroidManifest.xml
@@ -20,7 +20,7 @@
     <key-sets>
         <key-set android:name="A" >
           <public-key android:name="keyA"
-                      android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJoN1Nsgqf0V4C/bbN8wo8O2X/S5D76+5Mb9mlIsHkUTUTbHCNk+LxHIUYLm89YbP9zImrV0bUHLUAZUyoMUCiMCAwEAAQ=="/>
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMpNthdOxud7roPDZMMomOqXgJJdRfIWpkKEqmC61Mv+Nf6QY3TorEwJeghjSmqj7IbBKrtvfQq4E2XJO1HuspmQO4Ng2gvn+r+6EwNfKc9k55d6s+27SR867jKurBbHNtZMG+tjL1yH4r+tNzcuJCsgyAFqLmxFdcxEwzNvREyRpoYc5RDR0mmTwkMCUhJ6CId1EYEKiCEdNzxv+fWPEb21u+/MWpleGCILs8kglRVb2q/WOzAAvGr4FY5plfaE6N+lr7+UschQ+aMi1+uqewo2o0qPFVmZP5hnwj55K4UMzu/NhhDqQQsX4cSGES1KgHo5MTqRqZjN/I7emw5pFQIDAQAB"/>
         </key-set>
         <upgrade-key-set android:name="A"/>
     </key-sets>
diff --git a/core/tests/coretests/apks/keyset/uAB/AndroidManifest.xml b/core/tests/coretests/apks/keyset/uAB/AndroidManifest.xml
index 8ad3471..015c3ad 100644
--- a/core/tests/coretests/apks/keyset/uAB/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/uAB/AndroidManifest.xml
@@ -20,9 +20,9 @@
     <key-sets>
         <key-set android:name="AB" >
           <public-key android:name="keyA"
-                      android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJoN1Nsgqf0V4C/bbN8wo8O2X/S5D76+5Mb9mlIsHkUTUTbHCNk+LxHIUYLm89YbP9zImrV0bUHLUAZUyoMUCiMCAwEAAQ==" />
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMpNthdOxud7roPDZMMomOqXgJJdRfIWpkKEqmC61Mv+Nf6QY3TorEwJeghjSmqj7IbBKrtvfQq4E2XJO1HuspmQO4Ng2gvn+r+6EwNfKc9k55d6s+27SR867jKurBbHNtZMG+tjL1yH4r+tNzcuJCsgyAFqLmxFdcxEwzNvREyRpoYc5RDR0mmTwkMCUhJ6CId1EYEKiCEdNzxv+fWPEb21u+/MWpleGCILs8kglRVb2q/WOzAAvGr4FY5plfaE6N+lr7+UschQ+aMi1+uqewo2o0qPFVmZP5hnwj55K4UMzu/NhhDqQQsX4cSGES1KgHo5MTqRqZjN/I7emw5pFQIDAQAB" />
           <public-key android:name="keyB"
-                      android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMTfQsY8UuXiXmvw/y7Tpr7HoyfAC0nE/8Qdk3ZtEr9asa5qqP0F6xzCI1PGVFV+WLVRwm6FdB9StENL5EKyQFcCAwEAAQ==" />
+                      android:value="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtGr5cL2N7ztHiHmphB1/1eq+43lEAmP36iiEJAfX+cVReGSPFXqNnnM8Vptd2boAe332lrFw9rKPmbkZA+jOTA==" />
         </key-set>
         <upgrade-key-set android:name="AB"/>
     </key-sets>
diff --git a/core/tests/coretests/apks/keyset/uAuB/AndroidManifest.xml b/core/tests/coretests/apks/keyset/uAuB/AndroidManifest.xml
index cdbd639..9491dbea 100644
--- a/core/tests/coretests/apks/keyset/uAuB/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/uAuB/AndroidManifest.xml
@@ -20,11 +20,11 @@
     <key-sets>
         <key-set android:name="A" >
           <public-key android:name="keyA"
-                      android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJoN1Nsgqf0V4C/bbN8wo8O2X/S5D76+5Mb9mlIsHkUTUTbHCNk+LxHIUYLm89YbP9zImrV0bUHLUAZUyoMUCiMCAwEAAQ==" />
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMpNthdOxud7roPDZMMomOqXgJJdRfIWpkKEqmC61Mv+Nf6QY3TorEwJeghjSmqj7IbBKrtvfQq4E2XJO1HuspmQO4Ng2gvn+r+6EwNfKc9k55d6s+27SR867jKurBbHNtZMG+tjL1yH4r+tNzcuJCsgyAFqLmxFdcxEwzNvREyRpoYc5RDR0mmTwkMCUhJ6CId1EYEKiCEdNzxv+fWPEb21u+/MWpleGCILs8kglRVb2q/WOzAAvGr4FY5plfaE6N+lr7+UschQ+aMi1+uqewo2o0qPFVmZP5hnwj55K4UMzu/NhhDqQQsX4cSGES1KgHo5MTqRqZjN/I7emw5pFQIDAQAB" />
         </key-set>
         <key-set android:name="B" >
           <public-key android:name="keyB"
-                      android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMTfQsY8UuXiXmvw/y7Tpr7HoyfAC0nE/8Qdk3ZtEr9asa5qqP0F6xzCI1PGVFV+WLVRwm6FdB9StENL5EKyQFcCAwEAAQ==" />
+                      android:value="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtGr5cL2N7ztHiHmphB1/1eq+43lEAmP36iiEJAfX+cVReGSPFXqNnnM8Vptd2boAe332lrFw9rKPmbkZA+jOTA==" />
         </key-set>
         <upgrade-key-set android:name="A"/>
         <upgrade-key-set android:name="B"/>
diff --git a/core/tests/coretests/apks/keyset/uB/AndroidManifest.xml b/core/tests/coretests/apks/keyset/uB/AndroidManifest.xml
index 61063c3..f491840 100644
--- a/core/tests/coretests/apks/keyset/uB/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/uB/AndroidManifest.xml
@@ -20,7 +20,7 @@
     <key-sets>
         <key-set android:name="B" >
           <public-key android:name="keyB"
-                      android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMTfQsY8UuXiXmvw/y7Tpr7HoyfAC0nE/8Qdk3ZtEr9asa5qqP0F6xzCI1PGVFV+WLVRwm6FdB9StENL5EKyQFcCAwEAAQ==" />
+                      android:value="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtGr5cL2N7ztHiHmphB1/1eq+43lEAmP36iiEJAfX+cVReGSPFXqNnnM8Vptd2boAe332lrFw9rKPmbkZA+jOTA==" />
         </key-set>
         <upgrade-key-set android:name="B"/>
     </key-sets>
diff --git a/core/tests/coretests/certs/keyset_A.pk8 b/core/tests/coretests/certs/keyset_A.pk8
index 3976b94..4076313 100644
--- a/core/tests/coretests/certs/keyset_A.pk8
+++ b/core/tests/coretests/certs/keyset_A.pk8
Binary files differ
diff --git a/core/tests/coretests/certs/keyset_A.x509.pem b/core/tests/coretests/certs/keyset_A.x509.pem
index 0fe334e..548bf13 100644
--- a/core/tests/coretests/certs/keyset_A.x509.pem
+++ b/core/tests/coretests/certs/keyset_A.x509.pem
@@ -1,14 +1,18 @@
 -----BEGIN CERTIFICATE-----
-MIICKjCCAdQCCQCpDXPnNpO5UjANBgkqhkiG9w0BAQUFADCBmzELMAkGA1UEBhMC
-VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcx
-DzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEYMBYGA1UEAxMPd3d3
-LmV4YW1wbGUuY29tMSIwIAYJKoZIhvcNAQkBFhNkY2FzaG1hbkBnb29nbGUuY29t
-MB4XDTE0MDQyMTE4MTkwM1oXDTE3MDQyMDE4MTkwM1owgZsxCzAJBgNVBAYTAlVT
-MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MQ8w
-DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxGDAWBgNVBAMTD3d3dy5l
-eGFtcGxlLmNvbTEiMCAGCSqGSIb3DQEJARYTZGNhc2htYW5AZ29vZ2xlLmNvbTBc
-MA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCaDdTbIKn9FeAv22zfMKPDtl/0uQ++vuTG
-/ZpSLB5FE1E2xwjZPi8RyFGC5vPWGz/cyJq1dG1By1AGVMqDFAojAgMBAAEwDQYJ
-KoZIhvcNAQEFBQADQQCPTVDKxVZpxFH6Nm7sxpRplLzxbs/xyGELLIjEBVrgB0CM
-HAxFpPRHDSFpTxGG2mBCSrf+lD2Bf+WiIojx+RLY
+MIIC+TCCAeGgAwIBAgIJALuyfpZeCDiwMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
+BAMMCGtleXNldF9BMB4XDTE1MTIwMjIxMTEzNFoXDTQzMDQxOTIxMTEzNFowEzER
+MA8GA1UEAwwIa2V5c2V0X0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCwyk22F07G53uug8NkwyiY6peAkl1F8hamQoSqYLrUy/41/pBjdOisTAl6CGNK
+aqPshsEqu299CrgTZck7Ue6ymZA7g2DaC+f6v7oTA18pz2Tnl3qz7btJHzruMq6s
+Fsc21kwb62MvXIfiv603Ny4kKyDIAWoubEV1zETDM29ETJGmhhzlENHSaZPCQwJS
+EnoIh3URgQqIIR03PG/59Y8RvbW778xamV4YIguzySCVFVvar9Y7MAC8avgVjmmV
+9oTo36Wvv5SxyFD5oyLX66p7CjajSo8VWZk/mGfCPnkrhQzO782GEOpBCxfhxIYR
+LUqAejkxOpGpmM38jt6bDmkVAgMBAAGjUDBOMB0GA1UdDgQWBBTVcIVD9u9538W/
+NE2Y36YiPtYmPzAfBgNVHSMEGDAWgBTVcIVD9u9538W/NE2Y36YiPtYmPzAMBgNV
+HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCjTN3mgaKep55wR1ULf4ULIc/m
+mjfZK7ZnJcynBEIGyjAqt4mMIfKRV/DllLsf997r7bz12qUSLbhWGFSq4a2ceOIp
+RG0+CGXV8Ez5Hz4o99MAP37Zdd5Lfq8fdlg2Mro2MMr21Tf3i2Y2LOfkXEZrW7rQ
+A5ZRVksoRcPQWaaNA85LGRSCiC2XSjg8TLn1qKwQUXVGQ6fwLKqAeeV2+hynADih
+FUaf7HxE5H3bHLByLmLKtab3Ta/g8VXxxRYuyd/rYsWMAHsjZge6xoVajm6Wvj5Q
+AvIxV99+PK7dkjVpg3O2oN1O4DQlqqvxdhjNP733DI4cihfJYV9Vn+wKj3TA
 -----END CERTIFICATE-----
diff --git a/core/tests/coretests/certs/keyset_B.pk8 b/core/tests/coretests/certs/keyset_B.pk8
index a44ebb3..839d96c 100644
--- a/core/tests/coretests/certs/keyset_B.pk8
+++ b/core/tests/coretests/certs/keyset_B.pk8
Binary files differ
diff --git a/core/tests/coretests/certs/keyset_B.x509.pem b/core/tests/coretests/certs/keyset_B.x509.pem
index 2806de5..537e047 100644
--- a/core/tests/coretests/certs/keyset_B.x509.pem
+++ b/core/tests/coretests/certs/keyset_B.x509.pem
@@ -1,14 +1,10 @@
 -----BEGIN CERTIFICATE-----
-MIICKjCCAdQCCQC+5GnAgmYS6DANBgkqhkiG9w0BAQUFADCBmzELMAkGA1UEBhMC
-VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcx
-DzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEYMBYGA1UEAxMPd3d3
-LmV4YW1wbGUuY29tMSIwIAYJKoZIhvcNAQkBFhNkY2FzaG1hbkBnb29nbGUuY29t
-MB4XDTE0MDQyMTE4MjczM1oXDTE3MDQyMDE4MjczM1owgZsxCzAJBgNVBAYTAlVT
-MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MQ8w
-DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxGDAWBgNVBAMTD3d3dy5l
-eGFtcGxlLmNvbTEiMCAGCSqGSIb3DQEJARYTZGNhc2htYW5AZ29vZ2xlLmNvbTBc
-MA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDE30LGPFLl4l5r8P8u06a+x6MnwAtJxP/E
-HZN2bRK/WrGuaqj9BescwiNTxlRVfli1UcJuhXQfUrRDS+RCskBXAgMBAAEwDQYJ
-KoZIhvcNAQEFBQADQQCYYyur2/sMB88MOhQE8RHNmdO0zEQYAz66z3ctTNqiNsbK
-T9iKj0CT3cjqgfN5ex4onhnoIIPtON7DIHFWke5x
+MIIBbDCCAROgAwIBAgIJALP/7jQfVyFBMAoGCCqGSM49BAMCMBMxETAPBgNVBAMM
+CGtleXNldF9CMB4XDTE1MTIwMzIwNDgwNFoXDTQzMDQyMDIwNDgwNFowEzERMA8G
+A1UEAwwIa2V5c2V0X0IwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS0avlwvY3v
+O0eIeamEHX/V6r7jeUQCY/fqKIQkB9f5xVF4ZI8Veo2eczxWm13ZugB7ffaWsXD2
+so+ZuRkD6M5Mo1AwTjAdBgNVHQ4EFgQUHrv1BwZU/MchAsa3VL0n458IwVswHwYD
+VR0jBBgwFoAUHrv1BwZU/MchAsa3VL0n458IwVswDAYDVR0TBAUwAwEB/zAKBggq
+hkjOPQQDAgNHADBEAiBp2nTHHhywNIyLpe8mYUsbwozVWM5/2xFidQe9Edua0AIg
+Wt9BCfzrcsBh2Rlje9Im9sq6hIyLSS1pe6ZcI3+lDis=
 -----END CERTIFICATE-----
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index c279c8f..d133a12 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -1191,4 +1191,25 @@
                     InputMethodUtils.buildInputMethodsAndSubtypesString(map)));
         }
     }
+
+    @SmallTest
+    public void testConstructLocaleFromString() throws Exception {
+        assertEquals(new Locale("en"), InputMethodUtils.constructLocaleFromString("en"));
+        assertEquals(new Locale("en", "US"), InputMethodUtils.constructLocaleFromString("en_US"));
+        assertEquals(new Locale("en", "US", "POSIX"),
+                InputMethodUtils.constructLocaleFromString("en_US_POSIX"));
+
+        // Special rewrite rule for "tl" for versions of Android earlier than Lollipop that did not
+        // support three letter language codes, and used "tl" (Tagalog) as the language string for
+        // "fil" (Filipino).
+        assertEquals(new Locale("fil"), InputMethodUtils.constructLocaleFromString("tl"));
+        assertEquals(new Locale("fil", "PH"), InputMethodUtils.constructLocaleFromString("tl_PH"));
+        assertEquals(new Locale("fil", "PH", "POSIX"),
+                InputMethodUtils.constructLocaleFromString("tl_PH_POSIX"));
+
+        // So far rejecting an invalid/unexpected locale string is out of the scope of this method.
+        assertEquals(new Locale("a"), InputMethodUtils.constructLocaleFromString("a"));
+        assertEquals(new Locale("a b c"), InputMethodUtils.constructLocaleFromString("a b c"));
+        assertEquals(new Locale("en-US"), InputMethodUtils.constructLocaleFromString("en-US"));
+    }
 }
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index fc4916c..d98497b 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -30,7 +30,6 @@
     utils/StringUtils.cpp \
     utils/TestWindowContext.cpp \
     utils/VectorDrawableUtils.cpp \
-    utils/TestUtils.cpp \
     AmbientShadow.cpp \
     AnimationContext.cpp \
     Animator.cpp \
@@ -90,6 +89,9 @@
     VectorDrawablePath.cpp \
     protos/hwui.proto
 
+hwui_test_common_src_files := \
+    tests/common/TestUtils.cpp
+
 hwui_cflags := \
     -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES \
     -DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" \
@@ -180,8 +182,8 @@
         -DHWUI_NULL_GPU
 LOCAL_SRC_FILES := \
         $(hwui_src_files) \
-        tests/nullegl.cpp \
-        tests/nullgles.cpp
+        tests/common/nullegl.cpp \
+        tests/common/nullgles.cpp
 LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(hwui_c_includes) $(call hwui_proto_include)
 
@@ -215,28 +217,29 @@
         -DHWUI_NULL_GPU
 
 LOCAL_SRC_FILES += \
-    unit_tests/CanvasStateTests.cpp \
-    unit_tests/ClipAreaTests.cpp \
-    unit_tests/DamageAccumulatorTests.cpp \
-    unit_tests/DeviceInfoTests.cpp \
-    unit_tests/FatVectorTests.cpp \
-    unit_tests/LayerUpdateQueueTests.cpp \
-    unit_tests/LinearAllocatorTests.cpp \
-    unit_tests/VectorDrawableTests.cpp \
-    unit_tests/OffscreenBufferPoolTests.cpp \
-    unit_tests/StringUtilsTests.cpp
+    $(hwui_test_common_src_files) \
+    tests/unit/CanvasStateTests.cpp \
+    tests/unit/ClipAreaTests.cpp \
+    tests/unit/DamageAccumulatorTests.cpp \
+    tests/unit/DeviceInfoTests.cpp \
+    tests/unit/FatVectorTests.cpp \
+    tests/unit/LayerUpdateQueueTests.cpp \
+    tests/unit/LinearAllocatorTests.cpp \
+    tests/unit/VectorDrawableTests.cpp \
+    tests/unit/OffscreenBufferPoolTests.cpp \
+    tests/unit/StringUtilsTests.cpp
 
 ifeq (true, $(HWUI_NEW_OPS))
     LOCAL_SRC_FILES += \
-        unit_tests/BakedOpStateTests.cpp \
-        unit_tests/RecordingCanvasTests.cpp \
-        unit_tests/OpReordererTests.cpp
+        tests/unit/BakedOpStateTests.cpp \
+        tests/unit/RecordingCanvasTests.cpp \
+        tests/unit/OpReordererTests.cpp
 endif
 
 include $(BUILD_NATIVE_TEST)
 
 # ------------------------
-# test app
+# Macro-bench app
 # ------------------------
 
 include $(CLEAR_VARS)
@@ -255,11 +258,12 @@
 LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
 
 LOCAL_SRC_FILES += \
-    tests/TestContext.cpp \
-    tests/TestSceneRunner.cpp \
-    tests/main.cpp
+    $(hwui_test_common_src_files) \
+    tests/macrobench/TestContext.cpp \
+    tests/macrobench/TestSceneRunner.cpp \
+    tests/macrobench/main.cpp
 
-LOCAL_SRC_FILES += $(call all-cpp-files-under, tests/scenes)
+LOCAL_SRC_FILES += $(call all-cpp-files-under, tests/common/scenes)
 
 include $(BUILD_EXECUTABLE)
 
@@ -285,14 +289,15 @@
 LOCAL_STATIC_LIBRARIES := libbenchmark libbase
 
 LOCAL_SRC_FILES += \
-    microbench/DisplayListCanvasBench.cpp \
-    microbench/LinearAllocatorBench.cpp \
-    microbench/PathParserBench.cpp \
-    microbench/ShadowBench.cpp
+    $(hwui_test_common_src_files) \
+    tests/microbench/DisplayListCanvasBench.cpp \
+    tests/microbench/LinearAllocatorBench.cpp \
+    tests/microbench/PathParserBench.cpp \
+    tests/microbench/ShadowBench.cpp
 
 ifeq (true, $(HWUI_NEW_OPS))
     LOCAL_SRC_FILES += \
-        microbench/OpReordererBench.cpp
+        tests/microbench/OpReordererBench.cpp
 endif
 
 include $(BUILD_EXECUTABLE)
diff --git a/libs/hwui/tests/TestScene.h b/libs/hwui/tests/common/TestScene.h
similarity index 100%
rename from libs/hwui/tests/TestScene.h
rename to libs/hwui/tests/common/TestScene.h
diff --git a/libs/hwui/utils/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
similarity index 100%
rename from libs/hwui/utils/TestUtils.cpp
rename to libs/hwui/tests/common/TestUtils.cpp
diff --git a/libs/hwui/utils/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
similarity index 100%
rename from libs/hwui/utils/TestUtils.h
rename to libs/hwui/tests/common/TestUtils.h
diff --git a/libs/hwui/tests/nullegl.cpp b/libs/hwui/tests/common/nullegl.cpp
similarity index 100%
rename from libs/hwui/tests/nullegl.cpp
rename to libs/hwui/tests/common/nullegl.cpp
diff --git a/libs/hwui/tests/nullgles.cpp b/libs/hwui/tests/common/nullgles.cpp
similarity index 100%
rename from libs/hwui/tests/nullgles.cpp
rename to libs/hwui/tests/common/nullgles.cpp
diff --git a/libs/hwui/tests/scenes/HwLayerAnimation.cpp b/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/HwLayerAnimation.cpp
rename to libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
diff --git a/libs/hwui/tests/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/ListViewAnimation.cpp
rename to libs/hwui/tests/common/scenes/ListViewAnimation.cpp
diff --git a/libs/hwui/tests/scenes/OvalAnimation.cpp b/libs/hwui/tests/common/scenes/OvalAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/OvalAnimation.cpp
rename to libs/hwui/tests/common/scenes/OvalAnimation.cpp
diff --git a/libs/hwui/tests/scenes/PartialDamageAnimation.cpp b/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/PartialDamageAnimation.cpp
rename to libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
diff --git a/libs/hwui/tests/scenes/RecentsAnimation.cpp b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/RecentsAnimation.cpp
rename to libs/hwui/tests/common/scenes/RecentsAnimation.cpp
diff --git a/libs/hwui/tests/scenes/RectGridAnimation.cpp b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/RectGridAnimation.cpp
rename to libs/hwui/tests/common/scenes/RectGridAnimation.cpp
diff --git a/libs/hwui/tests/scenes/SaveLayerAnimation.cpp b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/SaveLayerAnimation.cpp
rename to libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
diff --git a/libs/hwui/tests/scenes/ShadowGrid2Animation.cpp b/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/ShadowGrid2Animation.cpp
rename to libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
diff --git a/libs/hwui/tests/scenes/ShadowGridAnimation.cpp b/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/ShadowGridAnimation.cpp
rename to libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
diff --git a/libs/hwui/tests/scenes/TestSceneBase.h b/libs/hwui/tests/common/scenes/TestSceneBase.h
similarity index 86%
rename from libs/hwui/tests/scenes/TestSceneBase.h
rename to libs/hwui/tests/common/scenes/TestSceneBase.h
index a208509..8a24149 100644
--- a/libs/hwui/tests/scenes/TestSceneBase.h
+++ b/libs/hwui/tests/common/scenes/TestSceneBase.h
@@ -19,10 +19,10 @@
 #include "DisplayListCanvas.h"
 #include "RecordingCanvas.h"
 #include "RenderNode.h"
-#include "tests/Benchmark.h"
-#include "tests/TestContext.h"
-#include "tests/TestScene.h"
-#include "utils/TestUtils.h"
+#include "tests/macrobench/Benchmark.h"
+#include "tests/macrobench/TestContext.h"
+#include "tests/common/TestScene.h"
+#include "tests/common/TestUtils.h"
 
 #include <functional>
 
diff --git a/libs/hwui/tests/Benchmark.h b/libs/hwui/tests/macrobench/Benchmark.h
similarity index 97%
rename from libs/hwui/tests/Benchmark.h
rename to libs/hwui/tests/macrobench/Benchmark.h
index 3f87d7f..aad8eb3 100644
--- a/libs/hwui/tests/Benchmark.h
+++ b/libs/hwui/tests/macrobench/Benchmark.h
@@ -16,7 +16,7 @@
 #ifndef TESTS_BENCHMARK_H
 #define TESTS_BENCHMARK_H
 
-#include "TestScene.h"
+#include "tests/common/TestScene.h"
 
 #include <string>
 #include <vector>
diff --git a/libs/hwui/tests/TestContext.cpp b/libs/hwui/tests/macrobench/TestContext.cpp
similarity index 100%
rename from libs/hwui/tests/TestContext.cpp
rename to libs/hwui/tests/macrobench/TestContext.cpp
diff --git a/libs/hwui/tests/TestContext.h b/libs/hwui/tests/macrobench/TestContext.h
similarity index 100%
rename from libs/hwui/tests/TestContext.h
rename to libs/hwui/tests/macrobench/TestContext.h
diff --git a/libs/hwui/tests/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
similarity index 98%
rename from libs/hwui/tests/TestSceneRunner.cpp
rename to libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 0376e10..1e1c6a1 100644
--- a/libs/hwui/tests/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -18,7 +18,7 @@
 #include "Benchmark.h"
 #include "RenderNode.h"
 #include "TestContext.h"
-#include "scenes/TestSceneBase.h"
+#include "tests/common/scenes/TestSceneBase.h"
 #include "renderthread/RenderProxy.h"
 #include "renderthread/RenderTask.h"
 
diff --git a/libs/hwui/tests/how_to_run.txt b/libs/hwui/tests/macrobench/how_to_run.txt
similarity index 100%
rename from libs/hwui/tests/how_to_run.txt
rename to libs/hwui/tests/macrobench/how_to_run.txt
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/macrobench/main.cpp
similarity index 100%
rename from libs/hwui/tests/main.cpp
rename to libs/hwui/tests/macrobench/main.cpp
diff --git a/libs/hwui/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
similarity index 98%
rename from libs/hwui/microbench/DisplayListCanvasBench.cpp
rename to libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index 4be1f99..2e59eb4 100644
--- a/libs/hwui/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -22,8 +22,8 @@
 #else
 #include "DisplayListCanvas.h"
 #endif
-#include "microbench/MicroBench.h"
-#include "utils/TestUtils.h"
+#include "tests/common/TestUtils.h"
+#include "tests/microbench/MicroBench.h"
 
 using namespace android;
 using namespace android::uirenderer;
diff --git a/libs/hwui/microbench/LinearAllocatorBench.cpp b/libs/hwui/tests/microbench/LinearAllocatorBench.cpp
similarity index 97%
rename from libs/hwui/microbench/LinearAllocatorBench.cpp
rename to libs/hwui/tests/microbench/LinearAllocatorBench.cpp
index 75f57cb..28513e4 100644
--- a/libs/hwui/microbench/LinearAllocatorBench.cpp
+++ b/libs/hwui/tests/microbench/LinearAllocatorBench.cpp
@@ -16,8 +16,8 @@
 
 #include <benchmark/Benchmark.h>
 
+#include "tests/microbench/MicroBench.h"
 #include "utils/LinearAllocator.h"
-#include "microbench/MicroBench.h"
 
 #include <vector>
 
diff --git a/libs/hwui/microbench/MicroBench.h b/libs/hwui/tests/microbench/MicroBench.h
similarity index 100%
rename from libs/hwui/microbench/MicroBench.h
rename to libs/hwui/tests/microbench/MicroBench.h
diff --git a/libs/hwui/microbench/OpReordererBench.cpp b/libs/hwui/tests/microbench/OpReordererBench.cpp
similarity index 98%
rename from libs/hwui/microbench/OpReordererBench.cpp
rename to libs/hwui/tests/microbench/OpReordererBench.cpp
index 53b64c3..406bfcc 100644
--- a/libs/hwui/microbench/OpReordererBench.cpp
+++ b/libs/hwui/tests/microbench/OpReordererBench.cpp
@@ -23,7 +23,7 @@
 #include "OpReorderer.h"
 #include "RecordedOp.h"
 #include "RecordingCanvas.h"
-#include "utils/TestUtils.h"
+#include "tests/common/TestUtils.h"
 #include "Vector.h"
 #include "microbench/MicroBench.h"
 
diff --git a/libs/hwui/microbench/PathParserBench.cpp b/libs/hwui/tests/microbench/PathParserBench.cpp
similarity index 100%
rename from libs/hwui/microbench/PathParserBench.cpp
rename to libs/hwui/tests/microbench/PathParserBench.cpp
diff --git a/libs/hwui/microbench/ShadowBench.cpp b/libs/hwui/tests/microbench/ShadowBench.cpp
similarity index 98%
rename from libs/hwui/microbench/ShadowBench.cpp
rename to libs/hwui/tests/microbench/ShadowBench.cpp
index 1b0f5ea..98ec4d9 100644
--- a/libs/hwui/microbench/ShadowBench.cpp
+++ b/libs/hwui/tests/microbench/ShadowBench.cpp
@@ -21,7 +21,7 @@
 #include "Vector.h"
 #include "VertexBuffer.h"
 #include "TessellationCache.h"
-#include "microbench/MicroBench.h"
+#include "tests/microbench/MicroBench.h"
 
 #include <SkPath.h>
 
diff --git a/libs/hwui/microbench/how_to_run.txt b/libs/hwui/tests/microbench/how_to_run.txt
similarity index 100%
rename from libs/hwui/microbench/how_to_run.txt
rename to libs/hwui/tests/microbench/how_to_run.txt
diff --git a/libs/hwui/unit_tests/BakedOpStateTests.cpp b/libs/hwui/tests/unit/BakedOpStateTests.cpp
similarity index 98%
rename from libs/hwui/unit_tests/BakedOpStateTests.cpp
rename to libs/hwui/tests/unit/BakedOpStateTests.cpp
index 7ad2f9b..de14abf 100644
--- a/libs/hwui/unit_tests/BakedOpStateTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpStateTests.cpp
@@ -18,7 +18,7 @@
 
 #include <BakedOpState.h>
 #include <RecordedOp.h>
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/unit_tests/CanvasStateTests.cpp b/libs/hwui/tests/unit/CanvasStateTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/CanvasStateTests.cpp
rename to libs/hwui/tests/unit/CanvasStateTests.cpp
diff --git a/libs/hwui/unit_tests/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/ClipAreaTests.cpp
rename to libs/hwui/tests/unit/ClipAreaTests.cpp
diff --git a/libs/hwui/unit_tests/DamageAccumulatorTests.cpp b/libs/hwui/tests/unit/DamageAccumulatorTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/DamageAccumulatorTests.cpp
rename to libs/hwui/tests/unit/DamageAccumulatorTests.cpp
diff --git a/libs/hwui/unit_tests/DeviceInfoTests.cpp b/libs/hwui/tests/unit/DeviceInfoTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/DeviceInfoTests.cpp
rename to libs/hwui/tests/unit/DeviceInfoTests.cpp
diff --git a/libs/hwui/unit_tests/FatVectorTests.cpp b/libs/hwui/tests/unit/FatVectorTests.cpp
similarity index 98%
rename from libs/hwui/unit_tests/FatVectorTests.cpp
rename to libs/hwui/tests/unit/FatVectorTests.cpp
index c6ccf4d..64b0ba1 100644
--- a/libs/hwui/unit_tests/FatVectorTests.cpp
+++ b/libs/hwui/tests/unit/FatVectorTests.cpp
@@ -17,7 +17,7 @@
 #include <gtest/gtest.h>
 #include <utils/FatVector.h>
 
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
 
 using namespace android;
 using namespace android::uirenderer;
diff --git a/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
similarity index 98%
rename from libs/hwui/unit_tests/LayerUpdateQueueTests.cpp
rename to libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
index cc15cc6..8b0e91c 100644
--- a/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp
+++ b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
@@ -19,7 +19,7 @@
 #include <LayerUpdateQueue.h>
 #include <RenderNode.h>
 
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/unit_tests/LinearAllocatorTests.cpp b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
similarity index 98%
rename from libs/hwui/unit_tests/LinearAllocatorTests.cpp
rename to libs/hwui/tests/unit/LinearAllocatorTests.cpp
index 0591db6..78d65dd 100644
--- a/libs/hwui/unit_tests/LinearAllocatorTests.cpp
+++ b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
@@ -17,7 +17,7 @@
 #include <gtest/gtest.h>
 #include <utils/LinearAllocator.h>
 
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
 
 using namespace android;
 using namespace android::uirenderer;
diff --git a/libs/hwui/unit_tests/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
similarity index 98%
rename from libs/hwui/unit_tests/OffscreenBufferPoolTests.cpp
rename to libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index de86aed..2187654 100644
--- a/libs/hwui/unit_tests/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -17,7 +17,7 @@
 #include <gtest/gtest.h>
 #include <renderstate/OffscreenBufferPool.h>
 
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
 
 using namespace android;
 using namespace android::uirenderer;
diff --git a/libs/hwui/unit_tests/OpReordererTests.cpp b/libs/hwui/tests/unit/OpReordererTests.cpp
similarity index 99%
rename from libs/hwui/unit_tests/OpReordererTests.cpp
rename to libs/hwui/tests/unit/OpReordererTests.cpp
index 2ce1d0a..98a430a 100644
--- a/libs/hwui/unit_tests/OpReordererTests.cpp
+++ b/libs/hwui/tests/unit/OpReordererTests.cpp
@@ -21,7 +21,7 @@
 #include <OpReorderer.h>
 #include <RecordedOp.h>
 #include <RecordingCanvas.h>
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
 
 #include <unordered_map>
 
diff --git a/libs/hwui/unit_tests/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
similarity index 99%
rename from libs/hwui/unit_tests/RecordingCanvasTests.cpp
rename to libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 81f0851..2449ce8 100644
--- a/libs/hwui/unit_tests/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -18,7 +18,7 @@
 
 #include <RecordedOp.h>
 #include <RecordingCanvas.h>
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/unit_tests/StringUtilsTests.cpp b/libs/hwui/tests/unit/StringUtilsTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/StringUtilsTests.cpp
rename to libs/hwui/tests/unit/StringUtilsTests.cpp
diff --git a/libs/hwui/unit_tests/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/VectorDrawableTests.cpp
rename to libs/hwui/tests/unit/VectorDrawableTests.cpp
diff --git a/libs/hwui/unit_tests/how_to_run.txt b/libs/hwui/tests/unit/how_to_run.txt
similarity index 100%
rename from libs/hwui/unit_tests/how_to_run.txt
rename to libs/hwui/tests/unit/how_to_run.txt
diff --git a/packages/Shell/tests/src/com/android/shell/UiBot.java b/packages/Shell/tests/src/com/android/shell/UiBot.java
index fa1714e..5e8bab1 100644
--- a/packages/Shell/tests/src/com/android/shell/UiBot.java
+++ b/packages/Shell/tests/src/com/android/shell/UiBot.java
@@ -20,6 +20,7 @@
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiScrollable;
 import android.support.test.uiautomator.UiSelector;
 import android.support.test.uiautomator.Until;
 import android.util.Log;
@@ -116,21 +117,27 @@
      */
     // TODO: UI Automator should provide such logic.
     public void chooseActivity(String name) {
-        // First select activity if it's not the default option.
-        boolean gotIt = mDevice.wait(Until.hasObject(By.text(name)), mTimeout);
-        // TODO: if the activity is indeed the default option, call above will timeout, which will
-        // make the tests run slower. It might be better to change the logic to assume the default
-        // first.
+        // First check if the activity is the default option.
+        String shareText = String.format("Share with %s", name);
+        boolean gotIt = mDevice.wait(Until.hasObject(By.text(shareText)), mTimeout);
+
         if (gotIt) {
-            Log.v(TAG, "Found activity " + name + ", it's not default action");
-            UiObject activityChooser = getVisibleObject(name);
-            click(activityChooser, "activity chooser");
+            Log.v(TAG, "Found activity " + name + ", it's the default action");
         } else {
-            String text = String.format("Share with %s", name);
-            Log.v(TAG, "Didn't find activity " + name
-                    + ", assuming it's the default action and search for '" + text + "'");
-            gotIt = mDevice.wait(Until.hasObject(By.text(text)), mTimeout);
-            assertTrue("did not find text '" + text + "'", gotIt);
+            // Since it's not, need to find it in the scrollable list...
+            Log.v(TAG, "Activity " + name + " is not default action");
+            UiScrollable activitiesList = new UiScrollable(new UiSelector().scrollable(true));
+
+            UiObject activity;
+            try {
+                activitiesList.scrollForward();
+                activity = getVisibleObject(name);
+            } catch (UiObjectNotFoundException e) {
+                throw new IllegalStateException("didn't find activity '" + name
+                        + "' on activities chooser", e);
+            }
+            // ... then select it.
+            click(activity, name);
         }
 
         // Then clicks the "Just Once" button.
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index bfd8af9..5618e9b 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -21,7 +21,6 @@
     <drawable name="ticker_background_color">#ff1d1d1d</drawable>
     <drawable name="system_bar_background">@color/system_bar_background_opaque</drawable>
     <color name="system_bar_background_opaque">#ff000000</color>
-    <color name="system_bar_background_semi_transparent">#66000000</color> <!-- 40% black -->
     <color name="system_bar_background_transparent">#00000000</color>
     <color name="notification_panel_solid_background">#ff000000</color>
     <drawable name="status_bar_notification_row_background_color">#ff090909</drawable>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d6a361c..002b9f5 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1171,13 +1171,23 @@
     <!-- Toggles fullscreen screenshots. DO NOT TRANSLATE -->
     <string name="overview_fullscreen_thumbnails">Enable fullscreen screenshots</string>
     <!-- Description for the toggle for fullscreen screenshots. DO NOT TRANSLATE -->
-    <string name="overview_fullscreen_thumbnails_desc">Enable fullscreen screenshots in Overview</string>
+    <string name="overview_fullscreen_thumbnails_desc">Enable fullscreen screenshots in Overview. Restart required.</string>
+
+    <!-- Toggle to enable the Overview nav bar gesture. DO NOT TRANSLATE -->
+    <string name="overview_nav_bar_gesture">Enable navigation bar gesture</string>
+    <!-- Description for the toggle to enable the Overview nav bar gesture. DO NOT TRANSLATE -->
+    <string name="overview_nav_bar_gesture_desc">Enables the gesture to enter Overview by swiping up on the Nav bar</string>
 
     <!-- Toggle to show the history view in Overview. DO NOT TRANSLATE -->
     <string name="overview_show_history">Show History</string>
     <!-- Description for the toggle to show the history view in Overview. DO NOT TRANSLATE -->
     <string name="overview_show_history_desc">Enables the history view to see more recent tasks</string>
 
+    <!-- Toggle to set the initial scroll state to be paging or stack. DO NOT TRANSLATE -->
+    <string name="overview_initial_state_paging">Initialize to paging</string>
+    <!-- Description for the toggle to set the initial scroll state to be paging or stack. DO NOT TRANSLATE -->
+    <string name="overview_initial_state_paging_desc">Determines whether Overview will initially be in a stacked or paged state</string>
+
     <!-- Category in the System UI Tuner settings, where new/experimental
          settings are -->
     <string name="experimental">Experimental</string>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index f398af3..8dcf8a7 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -93,11 +93,21 @@
             android:summary="@string/overview_page_on_toggle_desc" />
 
         <com.android.systemui.tuner.TunerSwitch
+            android:key="overview_initial_state_paging"
+            android:title="@string/overview_initial_state_paging"
+            android:summary="@string/overview_initial_state_paging_desc" />
+
+        <com.android.systemui.tuner.TunerSwitch
             android:key="overview_fast_toggle"
             android:title="@string/overview_fast_toggle_via_button"
             android:summary="@string/overview_fast_toggle_via_button_desc" />
 
         <com.android.systemui.tuner.TunerSwitch
+            android:key="overview_nav_bar_gesture"
+            android:title="@string/overview_nav_bar_gesture"
+            android:summary="@string/overview_nav_bar_gesture_desc" />
+
+        <com.android.systemui.tuner.TunerSwitch
             android:key="overview_fullscreen_thumbnails"
             android:title="@string/overview_fullscreen_thumbnails"
             android:summary="@string/overview_fullscreen_thumbnails_desc" />
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index 4cb8a3c..7f6cda0 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -32,7 +32,7 @@
     /**
      * Docks the top-most task and opens recents.
      */
-    void dockTopTask(boolean draggingInRecents, Rect initialBounds);
+    void dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds);
 
     /**
      * Called during a drag-from-navbar-in gesture.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index c98ecb5..b81c23a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -365,8 +365,8 @@
     }
 
     @Override
-    public void dockTopTask(boolean draggingInRecents, Rect initialBounds) {
-        mImpl.dockTopTask(draggingInRecents, initialBounds);
+    public void dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds) {
+        mImpl.dockTopTask(draggingInRecents, stackCreateMode,initialBounds);
         if (draggingInRecents) {
             mDraggingInRecentsCurrentUser = sSystemServicesProxy.getCurrentUser();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 063bb3e..384b86f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -425,10 +425,6 @@
             EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
         }
 
-        if (!launchState.launchedHasConfigurationChanged) {
-            mRecentsView.disableLayersForOneFrame();
-        }
-
         // Notify that recents is now visible
         SystemServicesProxy ssp = Recents.getSystemServices();
         EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index e8b8816..d778886 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -30,6 +30,7 @@
     private static final String KEY_PAGE_ON_TOGGLE = "overview_page_on_toggle";
     private static final String KEY_FULLSCREEN_THUMBNAILS = "overview_fullscreen_thumbnails";
     private static final String KEY_SHOW_HISTORY = "overview_show_history";
+    private static final String KEY_INITIAL_STATE_PAGING = "overview_initial_state_paging";
 
     public static class Static {
         // Enables debug drawing for the transition thumbnail
@@ -54,6 +55,7 @@
     private boolean mPageOnToggle;
     private boolean mUseFullscreenThumbnails;
     private boolean mShowHistory;
+    private boolean mInitialStatePaging;
 
     /**
      * We read the prefs once when we start the activity, then update them as the tuner changes
@@ -63,7 +65,7 @@
         // Register all our flags, this will also call onTuningChanged() for each key, which will
         // initialize the current state of each flag
         TunerService.get(context).addTunable(this, KEY_FAST_TOGGLE, KEY_PAGE_ON_TOGGLE,
-                KEY_FULLSCREEN_THUMBNAILS, KEY_SHOW_HISTORY);
+                KEY_FULLSCREEN_THUMBNAILS, KEY_SHOW_HISTORY, KEY_INITIAL_STATE_PAGING);
     }
 
     /**
@@ -94,6 +96,13 @@
         return mShowHistory;
     }
 
+    /**
+     * @return whether the initial stack state is paging.
+     */
+    public boolean isInitialStatePaging() {
+        return mInitialStatePaging;
+    }
+
     @Override
     public void onTuningChanged(String key, String newValue) {
         switch (key) {
@@ -113,6 +122,10 @@
                 mShowHistory = (newValue != null) &&
                         (Integer.parseInt(newValue) != 0);
                 break;
+            case KEY_INITIAL_STATE_PAGING:
+                mInitialStatePaging = (newValue != null) &&
+                        (Integer.parseInt(newValue) != 0);
+                break;
         }
         EventBus.getDefault().send(new DebugFlagsChangedEvent());
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 3efb0cc..2a4017a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -539,12 +539,11 @@
         showRelativeAffiliatedTask(false);
     }
 
-    public void dockTopTask(boolean draggingInRecents, Rect initialBounds) {
+    public void dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds) {
         SystemServicesProxy ssp = Recents.getSystemServices();
         ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
         if (topTask != null && !SystemServicesProxy.isHomeStack(topTask.stackId)) {
-            ssp.moveTaskToDockedStack(topTask.id,
-                    ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, initialBounds);
+            ssp.moveTaskToDockedStack(topTask.id, stackCreateMode, initialBounds);
             showRecents(false /* triggeredFromAltTab */, draggingInRecents, false /* animate */,
                     true /* reloadTasks*/);
         }
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 2b20c07..5d17e2c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -115,7 +115,6 @@
 
     /** Private constructor */
     public SystemServicesProxy(Context context) {
-        RecentsDebugFlags flags = Recents.getDebugFlags();
         mAccm = AccessibilityManager.getInstance(context);
         mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         mIam = ActivityManagerNative.getDefault();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 3bb89a3..63d09ee 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -48,7 +48,8 @@
     private static boolean DEBUG = false;
 
     private static int MIN_NUM_TASKS = 5;
-    private static int SESSION_BEGIN_TIME = 60 /* s/min */ * 60 /* min/hr */ * 6 /* hrs */;
+    private static int SESSION_BEGIN_TIME = 1000 /* ms/s */ * 60 /* s/min */ * 60 /* min/hr */ *
+            6 /* hrs */;
 
     /** The set of conditions to load tasks. */
     public static class Options {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 530cd2d..e313fd2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -199,8 +199,8 @@
     /** Task stack callbacks */
     public interface TaskStackCallbacks {
         /* Notifies when a task has been removed from the stack */
-        void onStackTaskRemoved(TaskStack stack, Task removedTask, int removedTaskIndex,
-                boolean wasFrontMostTask, Task newFrontMostTask);
+        void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
+            Task newFrontMostTask);
 
         /* Notifies when a task has been removed from the history */
         void onHistoryTaskRemoved(TaskStack stack, Task removedTask);
@@ -393,8 +393,7 @@
             }
             if (mCb != null) {
                 // Notify that a task has been removed
-                mCb.onStackTaskRemoved(this, t, removedTaskIndex, wasFrontMostTask,
-                        newFrontMostTask);
+                mCb.onStackTaskRemoved(this, t, wasFrontMostTask, newFrontMostTask);
             }
         } else if (mHistoryTaskList.contains(t)) {
             removeTaskImpl(mHistoryTaskList, t);
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 0911578..a9f570e 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,8 @@
 
 package com.android.systemui.recents.views;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -27,6 +29,8 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewPropertyAnimator;
 import android.view.WindowInsets;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
@@ -55,6 +59,8 @@
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.stackdivider.WindowManagerProxy;
+import com.android.systemui.statusbar.FlingAnimationUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -94,8 +100,10 @@
 
     Rect mSystemInsets = new Rect();
 
+    final FlingAnimationUtils mFlingAnimationUtils;
+
     public RecentsView(Context context) {
-        super(context);
+        this(context, null);
     }
 
     public RecentsView(Context context, AttributeSet attrs) {
@@ -118,6 +126,7 @@
                 com.android.internal.R.interpolator.fast_out_linear_in);
         mHistoryTransitionDuration = res.getInteger(R.integer.recents_history_transition_duration);
         mTouchHandler = new RecentsViewTouchHandler(this);
+        mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
 
         LayoutInflater inflater = LayoutInflater.from(context);
         mHistoryButton = inflater.inflate(R.layout.recents_history_button, this, false);
@@ -138,6 +147,8 @@
                 // If onRecentsHidden is not triggered, we need to the stack view again here
                 mTaskStackView.reset();
                 mTaskStackView.setStack(stack);
+                removeView(mTaskStackView);
+                addView(mTaskStackView);
             } else {
                 mTaskStackView = new TaskStackView(getContext(), stack);
                 mTaskStackView.setCallbacks(this);
@@ -443,12 +454,6 @@
         return super.verifyDrawable(who);
     }
 
-    public void disableLayersForOneFrame() {
-        if (mTaskStackView != null) {
-            mTaskStackView.disableLayersForOneFrame();
-        }
-    }
-
     /**** TaskStackView.TaskStackCallbacks Implementation ****/
 
     @Override
@@ -515,7 +520,22 @@
     }
 
     public final void onBusEvent(DraggingInRecentsEndedEvent event) {
-        animate().translationY(0f);
+        ViewPropertyAnimator animator = animate();
+        if (event.velocity > ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity()) {
+            animator.translationY(getHeight());
+            animator.withEndAction(new Runnable() {
+                @Override
+                public void run() {
+                    WindowManagerProxy.getInstance().maximizeDockedStack();
+                }
+            });
+            mFlingAnimationUtils.apply(animator, getTranslationY(), getHeight(), event.velocity);
+        } else {
+            animator.translationY(0f);
+            animator.setListener(null);
+            mFlingAnimationUtils.apply(animator, getTranslationY(), 0, event.velocity);
+        }
+        animator.start();
     }
 
     public final void onBusEvent(ShowHistoryEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 6dc380c..ebb819c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -118,18 +118,21 @@
      */
     public static class StackState {
 
-        public static final StackState FREEFORM_ONLY = new StackState(1f);
-        public static final StackState STACK_ONLY = new StackState(0f);
-        public static final StackState SPLIT = new StackState(0.5f);
+        public static final StackState FREEFORM_ONLY = new StackState(1f, 0);
+        public static final StackState STACK_ONLY = new StackState(0f, 0);
+        public static final StackState SPLIT = new StackState(0.5f, 255);
 
         public final float freeformHeightPct;
+        public final int freeformBackgroundAlpha;
 
         /**
          * @param freeformHeightPct the percentage of the stack height (not including paddings) to
          *                          allocate to the freeform workspace
+         * @param freeformBackgroundAlpha the background alpha for the freeform workspace
          */
-        StackState(float freeformHeightPct) {
+        StackState(float freeformHeightPct, int freeformBackgroundAlpha) {
             this.freeformHeightPct = freeformHeightPct;
+            this.freeformBackgroundAlpha = freeformBackgroundAlpha;
         }
 
         /**
@@ -278,7 +281,6 @@
     FreeformWorkspaceLayoutAlgorithm mFreeformLayoutAlgorithm;
 
     public TaskStackLayoutAlgorithm(Context context, TaskStackView stackView) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
         Resources res = context.getResources();
         mStackView = stackView;
 
@@ -309,9 +311,6 @@
      */
     public void setSystemInsets(Rect systemInsets) {
         mSystemInsets.set(systemInsets);
-        if (DEBUG) {
-            Log.d(TAG, "setSystemInsets: " + systemInsets);
-        }
     }
 
     /**
@@ -343,6 +342,7 @@
 
         // The freeform height is the visible height (not including system insets) - padding above
         // freeform and below stack - gap between the freeform and stack
+        mState = state;
         mStackTopOffset = mFocusedPeekHeight + heightPadding;
         mStackBottomOffset = mSystemInsets.bottom + heightPadding;
         state.computeRects(mFreeformRect, mStackRect, taskStackBounds, widthPadding, heightPadding,
@@ -498,13 +498,31 @@
     public float getDefaultFocusState() {
         RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
         RecentsDebugFlags debugFlags = Recents.getDebugFlags();
-        if (debugFlags.isPageOnToggleEnabled() || launchState.launchedWithAltTab) {
+        if (launchState.launchedWithAltTab ||
+                (debugFlags.isPageOnToggleEnabled() && debugFlags.isInitialStatePaging())) {
             return 1f;
         }
         return 0f;
     }
 
     /**
+     * Returns the task progress that would put the task just off the front of the stack.
+     */
+    public float getStackFrontTaskProgress(float stackScroll) {
+        float max = mUnfocusedRange.relativeMax +
+                mFocusState * (mFocusedRange.relativeMax - mUnfocusedRange.relativeMax);
+        return stackScroll + max;
+    }
+
+    /**
+     *
+     * Returns the current stack state.
+     */
+    public StackState getStackState() {
+        return mState;
+    }
+
+    /**
      * Computes the maximum number of visible tasks and thumbnails when the scroll is at the initial
      * stack scroll.  Requires that update() is called first.
      */
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 d45fba2..cc5aaae 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents.views;
 
+import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.ComponentName;
 import android.content.Context;
@@ -23,8 +24,11 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.util.IntProperty;
 import android.util.Log;
+import android.util.Property;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -90,6 +94,19 @@
     private static final float SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
     private static final float HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
 
+    public static final Property<ColorDrawable, Integer> COLOR_DRAWABLE_ALPHA =
+            new IntProperty<ColorDrawable>("colorDrawableAlpha") {
+                @Override
+                public void setValue(ColorDrawable object, int alpha) {
+                    object.setAlpha(alpha);
+                }
+
+                @Override
+                public Integer get(ColorDrawable object) {
+                    return object.getAlpha();
+                }
+            };
+
     /** The TaskView callbacks */
     interface TaskStackViewCallbacks {
         public void onTaskViewClicked(TaskStackView stackView, TaskView tv, TaskStack stack, Task t,
@@ -102,10 +119,11 @@
     TaskStackViewTouchHandler mTouchHandler;
     TaskStackViewCallbacks mCb;
     ColorDrawable mFreeformWorkspaceBackground;
+    ObjectAnimator mFreeformWorkspaceBackgroundAnimator;
     ViewPool<TaskView, Task> mViewPool;
     ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
     DozeTrigger mUIDozeTrigger;
-    int mFocusedTaskIndex = -1;
+    Task mFocusedTask;
     // Optimizations
     int mStackViewsAnimationDuration;
     boolean mStackViewsDirty = true;
@@ -119,7 +137,6 @@
     int[] mTmpVisibleRange = new int[2];
     Rect mTmpRect = new Rect();
     RectF mTmpTaskRect = new RectF();
-    TaskViewTransform mTmpTransform = new TaskViewTransform();
     TaskViewTransform mTmpStackBackTransform = new TaskViewTransform();
     TaskViewTransform mTmpStackFrontTransform = new TaskViewTransform();
     HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<>();
@@ -127,7 +144,6 @@
     List<TaskView> mImmutableTaskViews = new ArrayList<>();
     List<TaskView> mTmpTaskViews = new ArrayList<>();
     LayoutInflater mInflater;
-    boolean mLayersDisabled;
     boolean mTouchExplorationEnabled;
 
     Interpolator mFastOutSlowInInterpolator;
@@ -186,6 +202,7 @@
         setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
 
         mFreeformWorkspaceBackground = new ColorDrawable(0x33000000);
+        mFreeformWorkspaceBackground.setCallback(this);
     }
 
     /** Sets the callbacks */
@@ -462,24 +479,14 @@
                         Log.d(TAG, "picking up from pool: " + task.key);
                     }
                     tv = mViewPool.pickUpViewFromPool(task, task);
-                    if (mLayersDisabled) {
-                        tv.disableLayersForOneFrame();
-                    }
                 } else {
                     // Reattach it in the right z order
-                    detachViewFromParent(tv);
-                    int insertIndex = -1;
                     int taskIndex = mStack.indexOfStackTask(task);
-                    taskViews = getTaskViews();
-                    taskViewCount = taskViews.size();
-                    for (int j = 0; j < taskViewCount; j++) {
-                        Task tvTask = taskViews.get(j).getTask();
-                        if (taskIndex <= mStack.indexOfStackTask(tvTask)) {
-                            insertIndex = j;
-                            break;
-                        }
+                    int insertIndex = findTaskViewInsertIndex(task, taskIndex);
+                    if (insertIndex != getTaskViews().indexOf(tv)){
+                        detachViewFromParent(tv);
+                        attachViewToParent(tv, insertIndex, tv.getLayoutParams());
                     }
-                    attachViewToParent(tv, insertIndex, tv.getLayoutParams());
                 }
 
                 // Animate the task into place
@@ -500,9 +507,6 @@
 
                 if (tv == null) {
                     tv = mViewPool.pickUpViewFromPool(task, task);
-                    if (mLayersDisabled) {
-                        tv.disableLayersForOneFrame();
-                    }
                     if (mStackViewsAnimationDuration > 0) {
                         // For items in the list, put them in start animating them from the
                         // approriate ends of the list where they are expected to appear
@@ -517,8 +521,9 @@
                         } else {
                             if (!hasStackFrontTransform) {
                                 hasStackFrontTransform = true;
-                                mLayoutAlgorithm.getStackTransform(1f, 0f, mTmpStackFrontTransform,
-                                        null);
+                                mLayoutAlgorithm.getStackTransform(
+                                        mLayoutAlgorithm.getStackFrontTaskProgress(0f), 0f,
+                                        mTmpStackFrontTransform, null);
                             }
                             tv.updateViewPropertiesToTaskTransform(mTmpStackFrontTransform, 0, 0,
                                     mFastOutSlowInInterpolator, mRequestUpdateClippingListener);
@@ -612,7 +617,6 @@
         SystemServicesProxy ssp = Recents.getSystemServices();
         if (ssp.hasFreeformWorkspaceSupport()) {
             mTmpRect.set(mLayoutAlgorithm.mFreeformRect);
-            mFreeformWorkspaceBackground.setAlpha(255);
             mFreeformWorkspaceBackground.setBounds(mTmpRect);
         }
 
@@ -642,7 +646,7 @@
      * @return whether or not the stack will scroll as a part of this focus change
      */
     private boolean setFocusedTask(int taskIndex, boolean scrollToTask, final boolean animated,
-                                final boolean requestViewFocus) {
+            final boolean requestViewFocus) {
         // Find the next task to focus
         int newFocusedTaskIndex = mStack.getStackTaskCount() > 0 ?
                 Math.max(0, Math.min(mStack.getStackTaskCount() - 1, taskIndex)) : -1;
@@ -650,16 +654,13 @@
                 mStack.getStackTasks().get(newFocusedTaskIndex) : null;
 
         // Reset the last focused task state if changed
-        if (mFocusedTaskIndex != -1) {
-            Task focusedTask = mStack.getStackTasks().get(mFocusedTaskIndex);
-            if (focusedTask != newFocusedTask) {
-                resetFocusedTask(focusedTask);
-            }
+        if (mFocusedTask != null) {
+            resetFocusedTask(mFocusedTask);
         }
 
         boolean willScroll = false;
-        mFocusedTaskIndex = newFocusedTaskIndex;
-        if (mFocusedTaskIndex != -1) {
+        mFocusedTask = newFocusedTask;
+        if (newFocusedTask != null) {
             Runnable focusTaskRunnable = new Runnable() {
                 @Override
                 public void run() {
@@ -729,13 +730,11 @@
      */
     public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
                                        boolean cancelWindowAnimations) {
-        int newIndex = -1;
-        if (mFocusedTaskIndex != -1) {
+        int newIndex = mStack.indexOfStackTask(mFocusedTask);
+        if (mFocusedTask != null) {
             if (stackTasksOnly) {
                 List<Task> tasks =  mStack.getStackTasks();
-                newIndex = mFocusedTaskIndex;
-                Task task = tasks.get(mFocusedTaskIndex);
-                if (task.isFreeformTask()) {
+                if (mFocusedTask.isFreeformTask()) {
                     // Try and focus the front most stack task
                     TaskView tv = getFrontMostTaskView(stackTasksOnly);
                     if (tv != null) {
@@ -743,7 +742,7 @@
                     }
                 } else {
                     // Try the next task if it is a stack task
-                    int tmpNewIndex = mFocusedTaskIndex + (forward ? -1 : 1);
+                    int tmpNewIndex = newIndex + (forward ? -1 : 1);
                     if (0 <= tmpNewIndex && tmpNewIndex < tasks.size()) {
                         Task t = tasks.get(tmpNewIndex);
                         if (!t.isFreeformTask()) {
@@ -755,7 +754,7 @@
                 // No restrictions, lets just move to the new task (looping forward/backwards if
                 // necessary)
                 int taskCount = mStack.getStackTaskCount();
-                newIndex = (mFocusedTaskIndex + (forward ? -1 : 1) + taskCount) % taskCount;
+                newIndex = (newIndex + (forward ? -1 : 1) + taskCount) % taskCount;
             }
         } else {
             // We don't have a focused task, so focus the first visible task view
@@ -784,17 +783,14 @@
                 tv.setFocusedState(false, false /* animated */, false /* requestViewFocus */);
             }
         }
-        mFocusedTaskIndex = -1;
+        mFocusedTask = null;
     }
 
     /**
      * Returns the focused task.
      */
     Task getFocusedTask() {
-        if (mFocusedTaskIndex != -1) {
-            return mStack.getStackTasks().get(mFocusedTaskIndex);
-        }
-        return null;
+        return mFocusedTask;
     }
 
     @Override
@@ -819,12 +815,13 @@
         super.onInitializeAccessibilityNodeInfo(info);
         List<TaskView> taskViews = getTaskViews();
         int taskViewCount = taskViews.size();
-        if (taskViewCount > 1 && mFocusedTaskIndex != -1) {
+        if (taskViewCount > 1 && mFocusedTask != null) {
             info.setScrollable(true);
-            if (mFocusedTaskIndex > 0) {
+            int focusedTaskIndex = mStack.indexOfStackTask(mFocusedTask);
+            if (focusedTaskIndex > 0) {
                 info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
             }
-            if (mFocusedTaskIndex < mStack.getStackTaskCount() - 1) {
+            if (focusedTaskIndex < mStack.getStackTaskCount() - 1) {
                 info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
             }
         }
@@ -1027,6 +1024,11 @@
             mStartEnterAnimationContext = null;
         }
 
+        // Animate in the freeform workspace
+        animateFreeformWorkspaceBackgroundAlpha(
+                mLayoutAlgorithm.getStackState().freeformBackgroundAlpha, 150,
+                mFastOutSlowInInterpolator);
+
         // Set the task focused state without requesting view focus, and leave the focus animations
         // until after the enter-animation
         RecentsConfiguration config = Recents.getConfiguration();
@@ -1088,11 +1090,11 @@
                     // requesting view focus in onFirstLayout(), actually request view focus and
                     // animate the focused state if we are alt-tabbing now, after the window enter
                     // animation is completed
-                    if (mFocusedTaskIndex != -1) {
+                    if (mFocusedTask != null) {
                         RecentsConfiguration config = Recents.getConfiguration();
                         RecentsActivityLaunchState launchState = config.getLaunchState();
-                        setFocusedTask(mFocusedTaskIndex, false /* scrollToTask */,
-                                launchState.launchedWithAltTab);
+                        setFocusedTask(mStack.indexOfStackTask(mFocusedTask),
+                                false /* scrollToTask */, launchState.launchedWithAltTab);
                     }
                 }
             });
@@ -1106,6 +1108,11 @@
         mStackScroller.stopBoundScrollAnimation();
         // Animate all the task views out of view
         ctx.offscreenTranslationY = mLayoutAlgorithm.mStackRect.bottom;
+        // Dismiss the freeform workspace background
+        int taskViewExitToHomeDuration = getResources().getInteger(
+                R.integer.recents_task_exit_to_home_duration);
+        animateFreeformWorkspaceBackgroundAlpha(0, taskViewExitToHomeDuration,
+                mFastOutSlowInInterpolator);
 
         List<TaskView> taskViews = getTaskViews();
         int taskViewCount = taskViews.size();
@@ -1146,8 +1153,6 @@
 
     @Override
     protected void dispatchDraw(Canvas canvas) {
-        mLayersDisabled = false;
-
         // Draw the freeform workspace background
         SystemServicesProxy ssp = Recents.getSystemServices();
         if (ssp.hasFreeformWorkspaceSupport()) {
@@ -1159,12 +1164,12 @@
         super.dispatchDraw(canvas);
     }
 
-    public void disableLayersForOneFrame() {
-        mLayersDisabled = true;
-        List<TaskView> taskViews = getTaskViews();
-        for (int i = 0; i < taskViews.size(); i++) {
-            taskViews.get(i).disableLayersForOneFrame();
+    @Override
+    protected boolean verifyDrawable(Drawable who) {
+        if (who == mFreeformWorkspaceBackground) {
+            return true;
         }
+        return super.verifyDrawable(who);
     }
 
     /**
@@ -1182,9 +1187,9 @@
     /**** TaskStackCallbacks Implementation ****/
 
     @Override
-    public void onStackTaskRemoved(TaskStack stack, Task removedTask, int removedTaskIndex,
-            boolean wasFrontMostTask, Task newFrontMostTask) {
-        if (mFocusedTaskIndex == removedTaskIndex) {
+    public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
+            Task newFrontMostTask) {
+        if (mFocusedTask == removedTask) {
             resetFocusedTask(removedTask);
         }
 
@@ -1313,19 +1318,8 @@
         tv.setNoUserInteractionState();
 
         // Find the index where this task should be placed in the stack
-        int insertIndex = -1;
         int taskIndex = mStack.indexOfStackTask(task);
-        if (taskIndex != -1) {
-            List<TaskView> taskViews = getTaskViews();
-            int taskViewCount = taskViews.size();
-            for (int i = 0; i < taskViewCount; i++) {
-                Task tvTask = taskViews.get(i).getTask();
-                if (taskIndex < mStack.indexOfStackTask(tvTask)) {
-                    insertIndex = i;
-                    break;
-                }
-            }
-        }
+        int insertIndex = findTaskViewInsertIndex(task, taskIndex);
 
         // Add/attach the view to the hierarchy
         if (isNewView) {
@@ -1343,7 +1337,7 @@
         tv.setCallbacks(this);
         tv.setTouchEnabled(true);
         tv.setClipViewInStack(true);
-        if (mFocusedTaskIndex == taskIndex) {
+        if (mFocusedTask == task) {
             tv.setFocusedState(true, false /* animated */, false /* requestViewFocus */);
         }
     }
@@ -1429,10 +1423,12 @@
     }
 
     public final void onBusEvent(DismissFocusedTaskViewEvent event) {
-        if (mFocusedTaskIndex != -1) {
-            Task t = mStack.getStackTasks().get(mFocusedTaskIndex);
-            TaskView tv = getChildViewForTask(t);
-            tv.dismissTask();
+        if (mFocusedTask != null) {
+            TaskView tv = getChildViewForTask(mFocusedTask);
+            if (tv != null) {
+                tv.dismissTask();
+            }
+            resetFocusedTask(mFocusedTask);
         }
     }
 
@@ -1574,4 +1570,50 @@
         // Remove the task from the stack
         mStack.removeTask(task);
     }
+
+    /**
+     * Starts an alpha animation on the freeform workspace background.
+     */
+    private void animateFreeformWorkspaceBackgroundAlpha(int targetAlpha, int duration,
+            Interpolator interpolator) {
+        if (mFreeformWorkspaceBackground.getAlpha() == targetAlpha) {
+            return;
+        }
+
+        Utilities.cancelAnimationWithoutCallbacks(mFreeformWorkspaceBackgroundAnimator);
+        mFreeformWorkspaceBackgroundAnimator = ObjectAnimator.ofInt(mFreeformWorkspaceBackground,
+                COLOR_DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha);
+        mFreeformWorkspaceBackgroundAnimator.setDuration(duration);
+        mFreeformWorkspaceBackgroundAnimator.setInterpolator(interpolator);
+        mFreeformWorkspaceBackgroundAnimator.start();
+    }
+
+    /**
+     * Returns the insert index for the task in the current set of task views.  If the given task
+     * is already in the task view list, then this method returns the insert index assuming it
+     * is first removed at the previous index.
+     *
+     * @param task the task we are finding the index for
+     * @param taskIndex the index of the task in the stack
+     */
+    private int findTaskViewInsertIndex(Task task, int taskIndex) {
+        if (taskIndex != -1) {
+            List<TaskView> taskViews = getTaskViews();
+            boolean foundTaskView = false;
+            int taskViewCount = taskViews.size();
+            for (int i = 0; i < taskViewCount; i++) {
+                Task tvTask = taskViews.get(i).getTask();
+                if (tvTask == task) {
+                    foundTaskView = true;
+                } else if (taskIndex < mStack.indexOfStackTask(tvTask)) {
+                    if (foundTaskView) {
+                        return i - 1;
+                    } else {
+                        return i;
+                    }
+                }
+            }
+        }
+        return -1;
+    }
 }
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 907ed2f..1a6f129 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -176,11 +176,11 @@
             }
             case MotionEvent.ACTION_POINTER_DOWN: {
                 final int index = ev.getActionIndex();
-                mDownX = (int) ev.getX();
-                mDownY = (int) ev.getY();
+                mActivePointerId = ev.getPointerId(index);
+                mDownX = (int) ev.getX(index);
+                mDownY = (int) ev.getY(index);
                 mLastY = mDownY;
                 mDownScrollP = mScroller.getStackScroll();
-                mActivePointerId = ev.getPointerId(index);
                 mVelocityTracker.addMovement(ev);
                 break;
             }
@@ -221,6 +221,10 @@
                     // Select a new active pointer id and reset the motion state
                     final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
                     mActivePointerId = ev.getPointerId(newPointerIndex);
+                    mDownX = (int) ev.getX(pointerIndex);
+                    mDownY = (int) ev.getY(pointerIndex);
+                    mLastY = mDownY;
+                    mDownScrollP = mScroller.getStackScroll();
                 }
                 mVelocityTracker.addMovement(ev);
                 break;
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 1baa1a3..813a1fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -659,10 +659,6 @@
         }
     }
 
-    public void disableLayersForOneFrame() {
-        mHeaderView.disableLayersForOneFrame();
-    }
-
     /**** TaskCallbacks Implementation ****/
 
     /** Binds this task view to the task */
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 ec59f31..78a2c7f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -80,13 +80,10 @@
 
     // Header dim, which is only used when task view hardware layers are not used
     Paint mDimLayerPaint = new Paint();
-    PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
 
     Interpolator mFastOutSlowInInterpolator;
     Interpolator mFastOutLinearInInterpolator;
 
-    boolean mLayersDisabled;
-
     public TaskViewHeader(Context context) {
         this(context, null);
     }
@@ -111,6 +108,7 @@
         });
 
         // Load the dismiss resources
+        mDimLayerPaint.setColor(Color.argb(0, 0, 0, 0));
         mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light);
         mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
         mDismissContentDescription =
@@ -173,21 +171,13 @@
         canvas.restoreToCount(count);
     }
 
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-
     /**
      * Sets the dim alpha, only used when we are not using hardware layers.
      * (see RecentsConfiguration.useHardwareLayers)
      */
     void setDimAlpha(int alpha) {
-        mDimColorFilter.setColor(Color.argb(alpha, 0, 0, 0));
-        mDimLayerPaint.setColorFilter(mDimColorFilter);
-        if (!mLayersDisabled) {
-            setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
-        }
+        mDimLayerPaint.setColor(Color.argb(alpha, 0, 0, 0));
+        invalidate();
     }
 
     /** Returns the secondary color for a primary color. */
@@ -341,23 +331,11 @@
     @Override
     protected void dispatchDraw(Canvas canvas) {
         super.dispatchDraw(canvas);
-        if (mLayersDisabled) {
-            mLayersDisabled = false;
-            postOnAnimation(new Runnable() {
-                @Override
-                public void run() {
-                    mLayersDisabled = false;
-                    setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
-                }
-            });
-        }
-    }
 
-    public void disableLayersForOneFrame() {
-        mLayersDisabled = true;
-
-        // Disable layer for a frame so we can draw our first frame faster.
-        setLayerType(LAYER_TYPE_NONE, null);
+        // Draw the thumbnail with the rounded corners
+        canvas.drawRoundRect(0, 0, getWidth(), getHeight(),
+                mCornerRadius,
+                mCornerRadius, mDimLayerPaint);
     }
 
     /** Notifies the associated TaskView has been focused. */
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 98f3f0c..93264ff 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -74,7 +74,7 @@
 
     private final Rect mTmpRect = new Rect();
     private final Rect mLastResizeRect = new Rect();
-    private final WindowManagerProxy mWindowManagerProxy = new WindowManagerProxy();
+    private final WindowManagerProxy mWindowManagerProxy = WindowManagerProxy.getInstance();
     private Interpolator mFastOutSlowInInterpolator;
     private final Interpolator mTouchResponseInterpolator =
             new PathInterpolator(0.3f, 0f, 0.1f, 1f);
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 0d3f803..58de5d5 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -37,6 +37,8 @@
 
     private static final String TAG = "WindowManagerProxy";
 
+    private static final WindowManagerProxy sInstance = new WindowManagerProxy();
+
     @GuardedBy("mResizeRect")
     private final Rect mResizeRect = new Rect();
     private final Rect mTmpRect = new Rect();
@@ -78,6 +80,13 @@
         }
     };
 
+    private WindowManagerProxy() {
+    }
+
+    public static WindowManagerProxy getInstance() {
+        return sInstance;
+    }
+
     public void resizeDockedStack(Rect rect) {
         synchronized (mResizeRect) {
             mResizeRect.set(rect);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 1601b83..a3f404a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -146,7 +146,8 @@
                 mWarning = 0xffff0000;
             } else {
                 mOpaque = context.getColor(R.color.system_bar_background_opaque);
-                mSemiTransparent = context.getColor(R.color.system_bar_background_semi_transparent);
+                mSemiTransparent = context.getColor(
+                        com.android.internal.R.color.system_bar_background_semi_transparent);
                 mTransparent = context.getColor(R.color.system_bar_background_transparent);
                 mWarning = context.getColor(com.android.internal.R.color.battery_saver_mode_color);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index d91bfb9..a2616fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -16,30 +16,29 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.ActivityManager;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
-import android.os.SystemProperties;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
-import android.view.WindowManager;
 
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.stackdivider.Divider;
-import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.tuner.TunerService;
 
 import static android.view.WindowManager.*;
 
 /**
  * Class to detect gestures on the navigation bar.
  */
-public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureListener {
+public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureListener
+        implements TunerService.Tunable {
 
-    private static final String DOCK_WINDOW_GESTURE_ENABLED_PROP = "persist.dock_gesture_enabled";
+    private static final String KEY_DOCK_WINDOW_GESTURE = "overview_nav_bar_gesture";
 
     /**
      * When dragging from the navigation bar, we drag in recents.
@@ -53,6 +52,7 @@
 
     private RecentsComponent mRecentsComponent;
     private Divider mDivider;
+    private Context mContext;
     private boolean mIsVertical;
     private boolean mIsRTL;
 
@@ -69,13 +69,14 @@
     private int mDragMode;
 
     public NavigationBarGestureHelper(Context context) {
+        mContext = context;
         ViewConfiguration configuration = ViewConfiguration.get(context);
         Resources r = context.getResources();
         mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
         mTaskSwitcherDetector = new GestureDetector(context, this);
-        mDockWindowEnabled = SystemProperties.getBoolean(DOCK_WINDOW_GESTURE_ENABLED_PROP, false);
+        TunerService.get(context).addTunable(this, KEY_DOCK_WINDOW_GESTURE);
     }
 
     public void setComponents(RecentsComponent recentsComponent, Divider divider) {
@@ -172,6 +173,7 @@
                     == DOCKED_INVALID) {
                 mDragMode = calculateDragMode();
                 Rect initialBounds = null;
+                int createMode = ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
                 if (mDragMode == DRAG_MODE_DIVIDER) {
                     initialBounds = new Rect();
                     mDivider.getView().calculateBoundsForPosition(mIsVertical
@@ -181,8 +183,12 @@
                                     ? DOCKED_TOP
                                     : DOCKED_LEFT,
                             initialBounds);
+                } else if (mDragMode == DRAG_MODE_RECENTS && mTouchDownX
+                        < mContext.getResources().getDisplayMetrics().widthPixels / 2) {
+                    createMode = ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
                 }
-                mRecentsComponent.dockTopTask(mDragMode == DRAG_MODE_RECENTS, initialBounds);
+                mRecentsComponent.dockTopTask(mDragMode == DRAG_MODE_RECENTS, createMode,
+                        initialBounds);
                 if (mDragMode == DRAG_MODE_DIVIDER) {
                     mDivider.getView().startDragging();
                 }
@@ -259,4 +265,14 @@
         }
         return true;
     }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        switch (key) {
+            case KEY_DOCK_WINDOW_GESTURE:
+                mDockWindowEnabled = (newValue != null) &&
+                        (Integer.parseInt(newValue) != 0);
+                break;
+        }
+    }
 }
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 685c4e5..e51cf7ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1133,7 +1133,9 @@
         @Override
         public boolean onLongClick(View v) {
             if (mRecents != null) {
-                mRecents.dockTopTask(false /* draggingInRecents */, null /* initialBounds */);
+                mRecents.dockTopTask(false /* draggingInRecents */,
+                        ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
+                        null /* initialBounds */);
                 return true;
             }
             return false;
@@ -2486,12 +2488,14 @@
 
             // update status bar mode
             final int sbMode = computeBarMode(oldVal, newVal, mStatusBarView.getBarTransitions(),
-                    View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_TRANSLUCENT);
+                    View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_TRANSLUCENT,
+                    View.STATUS_BAR_TRANSPARENT);
 
             // update navigation bar mode
             final int nbMode = mNavigationBarView == null ? -1 : computeBarMode(
                     oldVal, newVal, mNavigationBarView.getBarTransitions(),
-                    View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT);
+                    View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
+                    View.NAVIGATION_BAR_TRANSPARENT);
             final boolean sbModeChanged = sbMode != -1;
             final boolean nbModeChanged = nbMode != -1;
             boolean checkBarModes = false;
@@ -2542,21 +2546,21 @@
     }
 
     private int computeBarMode(int oldVis, int newVis, BarTransitions transitions,
-            int transientFlag, int translucentFlag) {
-        final int oldMode = barMode(oldVis, transientFlag, translucentFlag);
-        final int newMode = barMode(newVis, transientFlag, translucentFlag);
+            int transientFlag, int translucentFlag, int transparentFlag) {
+        final int oldMode = barMode(oldVis, transientFlag, translucentFlag, transparentFlag);
+        final int newMode = barMode(newVis, transientFlag, translucentFlag, transparentFlag);
         if (oldMode == newMode) {
             return -1; // no mode change
         }
         return newMode;
     }
 
-    private int barMode(int vis, int transientFlag, int translucentFlag) {
-        int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_TRANSPARENT;
+    private int barMode(int vis, int transientFlag, int translucentFlag, int transparentFlag) {
+        int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | transparentFlag;
         return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT
                 : (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT
                 : (vis & lightsOutTransparent) == lightsOutTransparent ? MODE_LIGHTS_OUT_TRANSPARENT
-                : (vis & View.SYSTEM_UI_TRANSPARENT) != 0 ? MODE_TRANSPARENT
+                : (vis & transparentFlag) != 0 ? MODE_TRANSPARENT
                 : (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT
                 : MODE_OPAQUE;
     }
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index a5cef1a..ede92fb 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -513,33 +513,35 @@
         String[] uidPackageNames = getPackagesForUid(uid);
         ArrayMap<Callback, ArraySet<String>> callbackSpecs = null;
 
-        ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
-        if (callbacks != null) {
-            final int callbackCount = callbacks.size();
-            for (int i = 0; i < callbackCount; i++) {
-                Callback callback = callbacks.get(i);
-                ArraySet<String> changedPackages = new ArraySet<>();
-                Collections.addAll(changedPackages, uidPackageNames);
-                callbackSpecs = new ArrayMap<>();
-                callbackSpecs.put(callback, changedPackages);
-            }
-        }
-
-        for (String uidPackageName : uidPackageNames) {
-            callbacks = mPackageModeWatchers.get(uidPackageName);
+        synchronized (this) {
+            ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
             if (callbacks != null) {
-                if (callbackSpecs == null) {
-                    callbackSpecs = new ArrayMap<>();
-                }
                 final int callbackCount = callbacks.size();
                 for (int i = 0; i < callbackCount; i++) {
                     Callback callback = callbacks.get(i);
-                    ArraySet<String> changedPackages = callbackSpecs.get(callback);
-                    if (changedPackages == null) {
-                        changedPackages = new ArraySet<>();
-                        callbackSpecs.put(callback, changedPackages);
+                    ArraySet<String> changedPackages = new ArraySet<>();
+                    Collections.addAll(changedPackages, uidPackageNames);
+                    callbackSpecs = new ArrayMap<>();
+                    callbackSpecs.put(callback, changedPackages);
+                }
+            }
+
+            for (String uidPackageName : uidPackageNames) {
+                callbacks = mPackageModeWatchers.get(uidPackageName);
+                if (callbacks != null) {
+                    if (callbackSpecs == null) {
+                        callbackSpecs = new ArrayMap<>();
                     }
-                    changedPackages.add(uidPackageName);
+                    final int callbackCount = callbacks.size();
+                    for (int i = 0; i < callbackCount; i++) {
+                        Callback callback = callbacks.get(i);
+                        ArraySet<String> changedPackages = callbackSpecs.get(callback);
+                        if (changedPackages == null) {
+                            changedPackages = new ArraySet<>();
+                            callbackSpecs.put(callback, changedPackages);
+                        }
+                        changedPackages.add(uidPackageName);
+                    }
                 }
             }
         }
@@ -2051,7 +2053,7 @@
     private static String[] getPackagesForUid(int uid) {
         String[] packageNames = null;
         try {
-            packageNames= AppGlobals.getPackageManager().getPackagesForUid(uid);
+            packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
         } catch (RemoteException e) {
             /* ignore - local call */
         }
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 6aa5263..033a4b8 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -624,7 +624,13 @@
             byte[] hash = credentialUtil.toHash(credential, userId);
             if (Arrays.equals(hash, storedHash.hash)) {
                 unlockKeystore(credentialUtil.adjustForKeystore(credential), userId);
-                unlockUser(userId, null);
+
+                // TODO: pass through a meaningful token from gatekeeper to
+                // unlock credential keys; for now pass through a stub value to
+                // indicate that we came from a user challenge.
+                final byte[] token = String.valueOf(userId).getBytes();
+                unlockUser(userId, token);
+
                 // migrate credential to GateKeeper
                 credentialUtil.setCredential(credential, null, userId);
                 if (!hasChallenge) {
@@ -677,7 +683,13 @@
         if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
             // credential has matched
             unlockKeystore(credential, userId);
-            unlockUser(userId, null);
+
+            // TODO: pass through a meaningful token from gatekeeper to
+            // unlock credential keys; for now pass through a stub value to
+            // indicate that we came from a user challenge.
+            final byte[] token = String.valueOf(userId).getBytes();
+            unlockUser(userId, token);
+
             UserInfo info = UserManager.get(mContext).getUserInfo(userId);
             if (LockPatternUtils.isSeparateWorkChallengeEnabled() && info.isManagedProfile()) {
                 TrustManager trustManager =
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index bd43a71..807c0d6 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -100,6 +100,7 @@
 import com.android.internal.util.HexDump;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.server.NativeDaemonConnector.Command;
 import com.android.server.NativeDaemonConnector.SensitiveArg;
 import com.android.server.pm.PackageManagerService;
@@ -435,6 +436,7 @@
     private PackageManagerService mPms;
 
     private final Callbacks mCallbacks;
+    private final LockPatternUtils mLockPatternUtils;
 
     // Two connectors - mConnector & mCryptConnector
     private final CountDownLatch mConnectedSignal = new CountDownLatch(2);
@@ -1429,6 +1431,7 @@
 
         mContext = context;
         mCallbacks = new Callbacks(FgThread.get().getLooper());
+        mLockPatternUtils = new LockPatternUtils(mContext);
 
         // XXX: This will go away soon in favor of IMountServiceObserver
         mPms = (PackageManagerService) ServiceManager.getService("package");
@@ -2721,6 +2724,12 @@
         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
         waitForReady();
 
+        // When a user has secure lock screen, require a challenge token to
+        // actually unlock. This check is mostly in place for emulation mode.
+        if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(token)) {
+            throw new IllegalStateException("Token required to unlock secure user " + userId);
+        }
+
         final String encodedToken;
         if (ArrayUtils.isEmpty(token)) {
             encodedToken = "!";
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index e0a9ab4..ce3166d 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -133,6 +133,15 @@
     public void onStartUser(int userHandle) {}
 
     /**
+     * Called when an existing user is unlocked. This means the
+     * credential-encrypted storage for that user is now available, and
+     * encryption-aware component filtering is no longer in effect.
+     *
+     * @param userHandle The identifier of the user.
+     */
+    public void onUnlockUser(int userHandle) {}
+
+    /**
      * Called when switching to a different foreground user, for system services that have
      * special behavior for whichever user is currently in the foreground.  This is called
      * before any application processes are aware of the new user.
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 92e6814..ecc69e9 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -165,6 +165,19 @@
         }
     }
 
+    public void unlockUser(final int userHandle) {
+        final int serviceLen = mServices.size();
+        for (int i = 0; i < serviceLen; i++) {
+            final SystemService service = mServices.get(i);
+            try {
+                service.onUnlockUser(userHandle);
+            } catch (Exception ex) {
+                Slog.wtf(TAG, "Failure reporting unlock of user " + userHandle
+                        + " to service " + service.getClass().getName(), ex);
+            }
+        }
+    }
+
     public void switchUser(final int userHandle) {
         final int serviceLen = mServices.size();
         for (int i = 0; i < serviceLen; i++) {
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 0b67ad8..6f713cd 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -57,7 +57,6 @@
     private static final boolean LOG = false;
 
     // Enable launching of applications when entering the dock.
-    private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
     private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
 
     final Object mLock = new Object();
@@ -76,6 +75,13 @@
     private boolean mComputedNightMode;
     private int mCarModeEnableFlags;
 
+    // flag set by resource, whether to enable Car dock launch when starting car mode.
+    private boolean mEnableCarDockLaunch = true;
+    // flag set by resource, whether to lock UI mode to the default one or not.
+    private boolean mUiModeLocked = false;
+    // flag set by resource, whether to night mode change for normal all or not.
+    private boolean mNightModeLocked = false;
+
     int mCurUiMode = 0;
     private int mSetUiMode = 0;
     private boolean mHoldingConfiguration = false;
@@ -176,6 +182,10 @@
                 com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1);
         mDeskModeKeepsScreenOn = (res.getInteger(
                 com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
+        mEnableCarDockLaunch = res.getBoolean(
+                com.android.internal.R.bool.config_enableCarDockHomeLaunch);
+        mUiModeLocked = res.getBoolean(com.android.internal.R.bool.config_lockUiMode);
+        mNightModeLocked = res.getBoolean(com.android.internal.R.bool.config_lockDayNightMode);
 
         final PackageManager pm = context.getPackageManager();
         mTelevision = pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
@@ -199,6 +209,10 @@
     private final IBinder mService = new IUiModeManager.Stub() {
         @Override
         public void enableCarMode(int flags) {
+            if (isUiModeLocked()) {
+                Slog.e(TAG, "enableCarMode while UI mode is locked");
+                return;
+            }
             final long ident = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -214,6 +228,10 @@
 
         @Override
         public void disableCarMode(int flags) {
+            if (isUiModeLocked()) {
+                Slog.e(TAG, "disableCarMode while UI mode is locked");
+                return;
+            }
             final long ident = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -241,6 +259,13 @@
 
         @Override
         public void setNightMode(int mode) {
+            if (isNightModeLocked() &&  (getContext().checkCallingOrSelfPermission(
+                    android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
+                    != PackageManager.PERMISSION_GRANTED)) {
+                Slog.e(TAG,
+                        "Night mode locked, requires MODIFY_DAY_NIGHT_MODE permission");
+                return;
+            }
             switch (mode) {
                 case UiModeManager.MODE_NIGHT_NO:
                 case UiModeManager.MODE_NIGHT_YES:
@@ -273,6 +298,20 @@
         }
 
         @Override
+        public boolean isUiModeLocked() {
+            synchronized (mLock) {
+                return mUiModeLocked;
+            }
+        }
+
+        @Override
+        public boolean isNightModeLocked() {
+            synchronized (mLock) {
+                return mNightModeLocked;
+            }
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -293,10 +332,13 @@
             pw.print("  mDockState="); pw.print(mDockState);
                     pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
             pw.print("  mNightMode="); pw.print(mNightMode);
+                    pw.print(" mNightModeLocked="); pw.print(mNightModeLocked);
                     pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
                     pw.print(" mComputedNightMode="); pw.print(mComputedNightMode);
-                    pw.print(" mCarModeEnableFlags="); pw.println(mCarModeEnableFlags);
+                    pw.print(" mCarModeEnableFlags="); pw.print(mCarModeEnableFlags);
+                    pw.print(" mEnableCarDockLaunch="); pw.println(mEnableCarDockLaunch);
             pw.print("  mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
+                    pw.print(" mUiModeLocked="); pw.print(mUiModeLocked);
                     pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
             pw.print("  mHoldingConfiguration="); pw.print(mHoldingConfiguration);
                     pw.print(" mSystemReady="); pw.println(mSystemReady);
@@ -356,7 +398,9 @@
 
     private void updateConfigurationLocked() {
         int uiMode = mDefaultUiModeType;
-        if (mTelevision) {
+        if (mUiModeLocked) {
+            // no-op, keeps default one
+        } else if (mTelevision) {
             uiMode = Configuration.UI_MODE_TYPE_TELEVISION;
         } else if (mWatch) {
             uiMode = Configuration.UI_MODE_TYPE_WATCH;
@@ -460,7 +504,7 @@
         } else {
             String category = null;
             if (mCarModeEnabled) {
-                if (ENABLE_LAUNCH_CAR_DOCK_APP
+                if (mEnableCarDockLaunch
                         && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
                     category = Intent.CATEGORY_CAR_DOCK;
                 }
@@ -503,7 +547,7 @@
         if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(action)) {
             // Only launch car home when car mode is enabled and the caller
             // has asked us to switch to it.
-            if (ENABLE_LAUNCH_CAR_DOCK_APP
+            if (mEnableCarDockLaunch
                     && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
                 category = Intent.CATEGORY_CAR_DOCK;
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ef623eb..b769d39 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1487,6 +1487,7 @@
     static final int APP_BOOST_DEACTIVATE_MSG = 58;
     static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 59;
     static final int IDLE_UIDS_MSG = 60;
+    static final int SYSTEM_USER_UNLOCK_MSG = 61;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1989,6 +1990,10 @@
                 mSystemServiceManager.startUser(msg.arg1);
                 break;
             }
+            case SYSTEM_USER_UNLOCK_MSG: {
+                mSystemServiceManager.unlockUser(msg.arg1);
+                break;
+            }
             case SYSTEM_USER_CURRENT_MSG: {
                 mBatteryStatsService.noteEvent(
                         BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_FINISH,
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 3e0ae17..f6f82da 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -34,6 +34,7 @@
 import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MSG;
 import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG;
 import static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG;
+import static com.android.server.am.ActivityManagerService.SYSTEM_USER_UNLOCK_MSG;
 import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG;
 
 import android.annotation.NonNull;
@@ -81,8 +82,6 @@
 import java.util.List;
 import java.util.Set;
 
-import libcore.util.EmptyArray;
-
 /**
  * Helper class for {@link ActivityManagerService} responsible for multi-user functionality.
  */
@@ -147,7 +146,6 @@
         // User 0 is the first and only user that runs at boot.
         final UserState uss = new UserState(UserHandle.SYSTEM);
         mStartedUsers.put(UserHandle.USER_SYSTEM, uss);
-        updateUserUnlockedState(uss);
         mUserLru.add(UserHandle.USER_SYSTEM);
         updateStartedUserArrayLocked();
     }
@@ -173,8 +171,8 @@
                 num--;
                 continue;
             }
-            if (oldUss.mState == UserState.STATE_STOPPING
-                    || oldUss.mState == UserState.STATE_SHUTDOWN) {
+            if (oldUss.state == UserState.STATE_STOPPING
+                    || oldUss.state == UserState.STATE_SHUTDOWN) {
                 // This user is already stopping, doesn't count.
                 num--;
                 i++;
@@ -199,17 +197,65 @@
     }
 
     void finishUserBoot(UserState uss) {
+        finishUserBoot(uss, null);
+    }
+
+    void finishUserBoot(UserState uss, IIntentReceiver resultTo) {
+        final int userId = uss.mHandle.getIdentifier();
         synchronized (mService) {
-            if (uss.mState == UserState.STATE_BOOTING
-                    && mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) {
-                uss.mState = UserState.STATE_RUNNING;
-                final int userId = uss.mHandle.getIdentifier();
-                Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
+            // Bail if we ended up with a stale user
+            if (mStartedUsers.get(userId) != uss) return;
+
+            // We always walk through all the user lifecycle states to send
+            // consistent developer events. We step into RUNNING_LOCKED here,
+            // but we might immediately step into RUNNING below if the user
+            // storage is already unlocked.
+            if (uss.state == UserState.STATE_BOOTING) {
+                uss.setState(UserState.STATE_RUNNING_LOCKED);
+
+                Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null);
                 intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
                 intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
-                mService.broadcastIntentLocked(null, null, intent,
-                        null, null, 0, null, null,
-                        new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
+                mService.broadcastIntentLocked(null, null, intent, null, resultTo, 0, null, null,
+                        new String[] { android.Manifest.permission.RECEIVE_BOOT_COMPLETED },
+                        AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
+            }
+
+            maybeUnlockUser(userId);
+        }
+    }
+
+    /**
+     * Consider stepping from {@link UserState#STATE_RUNNING_LOCKED} into
+     * {@link UserState#STATE_RUNNING}, which only occurs if the user storage is
+     * actually unlocked.
+     */
+    void finishUserUnlock(UserState uss) {
+        final int userId = uss.mHandle.getIdentifier();
+        synchronized (mService) {
+            // Bail if we ended up with a stale user
+            if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
+
+            // Only keep marching forward if user is actually unlocked
+            if (!isUserKeyUnlocked(userId)) return;
+
+            if (uss.state == UserState.STATE_RUNNING_LOCKED) {
+                uss.setState(UserState.STATE_RUNNING);
+
+                mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0));
+
+                final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
+                unlockedIntent.addFlags(
+                        Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+                mService.broadcastIntentLocked(null, null, unlockedIntent, null, null, 0, null,
+                        null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+                        userId);
+
+                final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
+                bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
+                mService.broadcastIntentLocked(null, null, bootIntent, null, null, 0, null, null,
+                        new String[] { android.Manifest.permission.RECEIVE_BOOT_COMPLETED },
                         AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
             }
         }
@@ -291,9 +337,9 @@
             uss.mStopCallbacks.add(callback);
         }
 
-        if (uss.mState != UserState.STATE_STOPPING
-                && uss.mState != UserState.STATE_SHUTDOWN) {
-            uss.mState = UserState.STATE_STOPPING;
+        if (uss.state != UserState.STATE_STOPPING
+                && uss.state != UserState.STATE_SHUTDOWN) {
+            uss.setState(UserState.STATE_STOPPING);
             updateStartedUserArrayLocked();
 
             long ident = Binder.clearCallingIdentity();
@@ -321,11 +367,11 @@
                             Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                         // On to the next.
                         synchronized (mService) {
-                            if (uss.mState != UserState.STATE_STOPPING) {
+                            if (uss.state != UserState.STATE_STOPPING) {
                                 // Whoops, we are being started back up.  Abort, abort!
                                 return;
                             }
-                            uss.mState = UserState.STATE_SHUTDOWN;
+                            uss.setState(UserState.STATE_SHUTDOWN);
                         }
                         mService.mBatteryStatsService.noteEvent(
                                 BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH,
@@ -355,7 +401,7 @@
             callbacks = new ArrayList<>(uss.mStopCallbacks);
             if (mStartedUsers.get(userId) != uss) {
                 stopped = false;
-            } else if (uss.mState != UserState.STATE_SHUTDOWN) {
+            } else if (uss.state != UserState.STATE_SHUTDOWN) {
                 stopped = false;
             } else {
                 stopped = true;
@@ -438,8 +484,8 @@
                 Integer oldUserId = mUserLru.get(i);
                 UserState oldUss = mStartedUsers.get(oldUserId);
                 if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId
-                        || oldUss.mState == UserState.STATE_STOPPING
-                        || oldUss.mState == UserState.STATE_SHUTDOWN) {
+                        || oldUss.state == UserState.STATE_STOPPING
+                        || oldUss.state == UserState.STATE_SHUTDOWN) {
                     continue;
                 }
                 UserInfo userInfo = getUserInfo(oldUserId);
@@ -482,18 +528,21 @@
         return userManager;
     }
 
-    private void updateUserUnlockedState(UserState uss) {
-        final IMountService mountService = IMountService.Stub
-                .asInterface(ServiceManager.getService("mount"));
+    private IMountService getMountService() {
+        return IMountService.Stub.asInterface(ServiceManager.getService("mount"));
+    }
+
+    private boolean isUserKeyUnlocked(int userId) {
+        final IMountService mountService = getMountService();
         if (mountService != null) {
             try {
-                uss.unlocked = mountService.isUserKeyUnlocked(uss.mHandle.getIdentifier());
+                return mountService.isUserKeyUnlocked(userId);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             }
         } else {
-            // System isn't fully booted yet, so guess based on property
-            uss.unlocked = !StorageManager.isFileBasedEncryptionEnabled();
+            Slog.w(TAG, "Mount service not published; guessing locked state based on property");
+            return !StorageManager.isFileBasedEncryptionEnabled();
         }
     }
 
@@ -547,8 +596,6 @@
                 }
 
                 final UserState uss = mStartedUsers.get(userId);
-                updateUserUnlockedState(uss);
-
                 final Integer userIdInt = userId;
                 mUserLru.remove(userIdInt);
                 mUserLru.add(userIdInt);
@@ -572,22 +619,22 @@
 
                 // Make sure user is in the started state.  If it is currently
                 // stopping, we need to knock that off.
-                if (uss.mState == UserState.STATE_STOPPING) {
+                if (uss.state == UserState.STATE_STOPPING) {
                     // If we are stopping, we haven't sent ACTION_SHUTDOWN,
                     // so we can just fairly silently bring the user back from
                     // the almost-dead.
-                    uss.mState = UserState.STATE_RUNNING;
+                    uss.setState(uss.lastState);
                     updateStartedUserArrayLocked();
                     needStart = true;
-                } else if (uss.mState == UserState.STATE_SHUTDOWN) {
+                } else if (uss.state == UserState.STATE_SHUTDOWN) {
                     // This means ACTION_SHUTDOWN has been sent, so we will
                     // need to treat this as a new boot of the user.
-                    uss.mState = UserState.STATE_BOOTING;
+                    uss.setState(UserState.STATE_BOOTING);
                     updateStartedUserArrayLocked();
                     needStart = true;
                 }
 
-                if (uss.mState == UserState.STATE_BOOTING) {
+                if (uss.state == UserState.STATE_BOOTING) {
                     // Let user manager propagate user restrictions to other services.
                     getUserManager().onBeforeStartUser(userId);
 
@@ -697,35 +744,40 @@
         }
     }
 
+    /**
+     * Attempt to unlock user without a credential token. This typically
+     * succeeds when the device doesn't have credential-encrypted storage, or
+     * when the the credential-encrypted storage isn't tied to a user-provided
+     * PIN or pattern.
+     */
+    boolean maybeUnlockUser(final int userId) {
+        // Try unlocking storage using empty token
+        return unlockUserCleared(userId, null);
+    }
+
     boolean unlockUserCleared(final int userId, byte[] token) {
         synchronized (mService) {
+            // Bail if already running unlocked
             final UserState uss = mStartedUsers.get(userId);
-            if (uss.unlocked) {
-                // Bail early when already unlocked
-                return true;
+            if (uss.state == UserState.STATE_RUNNING) return true;
+        }
+
+        if (!isUserKeyUnlocked(userId)) {
+            final UserInfo userInfo = getUserInfo(userId);
+            final IMountService mountService = getMountService();
+            try {
+                mountService.unlockUserKey(userId, userInfo.serialNumber, token);
+            } catch (RemoteException | RuntimeException e) {
+                Slog.w(TAG, "Failed to unlock: " + e.getMessage());
+                return false;
             }
         }
 
-        final UserInfo userInfo = getUserInfo(userId);
-        final IMountService mountService = IMountService.Stub
-                .asInterface(ServiceManager.getService("mount"));
-        try {
-            mountService.unlockUserKey(userId, userInfo.serialNumber, token);
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Failed to unlock: " + e.getMessage());
-            return false;
-        }
-
         synchronized (mService) {
             final UserState uss = mStartedUsers.get(userId);
-            updateUserUnlockedState(uss);
+            finishUserUnlock(uss);
         }
 
-        final Intent intent = new Intent(Intent.ACTION_USER_UNLOCKED);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
-        mService.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
-                AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, userId);
-
         return true;
     }
 
@@ -1045,8 +1097,8 @@
         for (int i = 0; i < mStartedUsers.size(); i++) {
             UserState uss = mStartedUsers.valueAt(i);
             // This list does not include stopping users.
-            if (uss.mState != UserState.STATE_STOPPING
-                    && uss.mState != UserState.STATE_SHUTDOWN) {
+            if (uss.state != UserState.STATE_STOPPING
+                    && uss.state != UserState.STATE_SHUTDOWN) {
                 num++;
             }
         }
@@ -1054,8 +1106,8 @@
         num = 0;
         for (int i = 0; i < mStartedUsers.size(); i++) {
             UserState uss = mStartedUsers.valueAt(i);
-            if (uss.mState != UserState.STATE_STOPPING
-                    && uss.mState != UserState.STATE_SHUTDOWN) {
+            if (uss.state != UserState.STATE_STOPPING
+                    && uss.state != UserState.STATE_SHUTDOWN) {
                 mStartedUserArray[num] = mStartedUsers.keyAt(i);
                 num++;
             }
@@ -1065,17 +1117,7 @@
     void sendBootCompletedLocked(IIntentReceiver resultTo) {
         for (int i = 0; i < mStartedUsers.size(); i++) {
             UserState uss = mStartedUsers.valueAt(i);
-            if (uss.mState == UserState.STATE_BOOTING) {
-                uss.mState = UserState.STATE_RUNNING;
-                final int userId = mStartedUsers.keyAt(i);
-                Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
-                intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
-                intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
-                mService.broadcastIntentLocked(null, null, intent, null,
-                        resultTo, 0, null, null,
-                        new String[] {android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
-                        AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
-            }
+            finishUserBoot(uss, resultTo);
         }
     }
 
@@ -1117,14 +1159,33 @@
         if ((flags & ActivityManager.FLAG_OR_STOPPED) != 0) {
             return true;
         }
-        if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0 && state.unlocked) {
-            return false;
+
+        final boolean unlocked;
+        switch (state.state) {
+            case UserState.STATE_STOPPING:
+            case UserState.STATE_SHUTDOWN:
+            default:
+                return false;
+
+            case UserState.STATE_BOOTING:
+            case UserState.STATE_RUNNING_LOCKED:
+                unlocked = false;
+                break;
+
+            case UserState.STATE_RUNNING:
+                unlocked = true;
+                break;
         }
-        if ((flags & ActivityManager.FLAG_AND_UNLOCKED) != 0 && !state.unlocked) {
-            return false;
+
+        if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0) {
+            return !unlocked;
         }
-        return state.mState != UserState.STATE_STOPPING
-                && state.mState != UserState.STATE_SHUTDOWN;
+        if ((flags & ActivityManager.FLAG_AND_UNLOCKED) != 0) {
+            return unlocked;
+        }
+
+        // One way or another, we're running!
+        return true;
     }
 
     UserInfo getCurrentUser() {
diff --git a/services/core/java/com/android/server/am/UserState.java b/services/core/java/com/android/server/am/UserState.java
index b5b5c1d..7b18a17 100644
--- a/services/core/java/com/android/server/am/UserState.java
+++ b/services/core/java/com/android/server/am/UserState.java
@@ -19,28 +19,37 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
 import android.app.IStopUserCallback;
 import android.os.UserHandle;
 import android.util.ArrayMap;
+import android.util.Slog;
 
 public final class UserState {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "UserState" : TAG_AM;
+
     // User is first coming up.
     public final static int STATE_BOOTING = 0;
+    // User is in the locked running state.
+    public final static int STATE_RUNNING_LOCKED = 1;
     // User is in the normal running state.
-    public final static int STATE_RUNNING = 1;
+    public final static int STATE_RUNNING = 2;
     // User is in the initial process of being stopped.
-    public final static int STATE_STOPPING = 2;
+    public final static int STATE_STOPPING = 3;
     // User is in the final phase of stopping, sending Intent.ACTION_SHUTDOWN.
-    public final static int STATE_SHUTDOWN = 3;
+    public final static int STATE_SHUTDOWN = 4;
 
     public final UserHandle mHandle;
     public final ArrayList<IStopUserCallback> mStopCallbacks
             = new ArrayList<IStopUserCallback>();
 
-    public int mState = STATE_BOOTING;
+    public int state = STATE_BOOTING;
+    public int lastState = STATE_BOOTING;
     public boolean switching;
     public boolean initializing;
-    public boolean unlocked;
 
     /**
      * The last time that a provider was reported to usage stats as being brought to important
@@ -52,22 +61,32 @@
         mHandle = handle;
     }
 
-    void dump(String prefix, PrintWriter pw) {
-        pw.print(prefix); pw.print("mState=");
-        switch (mState) {
-            case STATE_BOOTING: pw.print("BOOTING"); break;
-            case STATE_RUNNING: pw.print("RUNNING"); break;
-            case STATE_STOPPING: pw.print("STOPPING"); break;
-            case STATE_SHUTDOWN: pw.print("SHUTDOWN"); break;
-            default: pw.print(mState); break; 
+    public void setState(int newState) {
+        if (DEBUG_MU) {
+            Slog.i(TAG, "User " + mHandle.getIdentifier() + " state changed from "
+                    + stateToString(state) + " to " + stateToString(newState));
         }
+        lastState = state;
+        state = newState;
+    }
+
+    private static String stateToString(int state) {
+        switch (state) {
+            case STATE_BOOTING: return "BOOTING";
+            case STATE_RUNNING_LOCKED: return "RUNNING_LOCKED";
+            case STATE_RUNNING: return "RUNNING";
+            case STATE_STOPPING: return "STOPPING";
+            case STATE_SHUTDOWN: return "SHUTDOWN";
+            default: return Integer.toString(state);
+        }
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix);
+        pw.print("state="); pw.print(stateToString(state));
+        pw.print(" lastState="); pw.print(stateToString(lastState));
         if (switching) pw.print(" SWITCHING");
         if (initializing) pw.print(" INITIALIZING");
-        if (unlocked) {
-            pw.print(" UNLOCKED");
-        } else {
-            pw.print(" LOCKED");
-        }
         pw.println();
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e0b7370..c2666b8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -17,6 +17,19 @@
 package com.android.server.notification;
 
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
+import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CLICK;
+import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CANCEL;
+import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CANCEL_ALL;
+import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_ERROR;
+import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_CHANGED;
+import static android.service.notification.NotificationAssistantService.REASON_USER_STOPPED;
+import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_BANNED;
+import static android.service.notification.NotificationAssistantService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationAssistantService.REASON_APP_CANCEL_ALL;
+import static android.service.notification.NotificationAssistantService.REASON_LISTENER_CANCEL;
+import static android.service.notification.NotificationAssistantService.REASON_LISTENER_CANCEL_ALL;
+import static android.service.notification.NotificationAssistantService.REASON_GROUP_SUMMARY_CANCELED;
+import static android.service.notification.NotificationAssistantService.REASON_GROUP_OPTIMIZATION;
 import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_LIGHTS;
 import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_PEEK;
 import static android.service.notification.NotificationListenerService.TRIM_FULL;
@@ -281,19 +294,6 @@
 
     private static final int MY_UID = Process.myUid();
     private static final int MY_PID = Process.myPid();
-    private static final int REASON_DELEGATE_CLICK = 1;
-    private static final int REASON_DELEGATE_CANCEL = 2;
-    private static final int REASON_DELEGATE_CANCEL_ALL = 3;
-    private static final int REASON_DELEGATE_ERROR = 4;
-    private static final int REASON_PACKAGE_CHANGED = 5;
-    private static final int REASON_USER_STOPPED = 6;
-    private static final int REASON_PACKAGE_BANNED = 7;
-    private static final int REASON_NOMAN_CANCEL = 8;
-    private static final int REASON_NOMAN_CANCEL_ALL = 9;
-    private static final int REASON_LISTENER_CANCEL = 10;
-    private static final int REASON_LISTENER_CANCEL_ALL = 11;
-    private static final int REASON_GROUP_SUMMARY_CANCELED = 12;
-    private static final int REASON_GROUP_OPTIMIZATION = 13;
 
     private static class Archive {
         final int mBufferSize;
@@ -1176,7 +1176,7 @@
             cancelNotification(Binder.getCallingUid(), Binder.getCallingPid(), pkg, tag, id, 0,
                     Binder.getCallingUid() == Process.SYSTEM_UID
                             ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId,
-                    REASON_NOMAN_CANCEL, null);
+                    REASON_APP_CANCEL, null);
         }
 
         @Override
@@ -1190,7 +1190,7 @@
             // running foreground services.
             cancelAllNotificationsInt(Binder.getCallingUid(), Binder.getCallingPid(),
                     pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId,
-                    REASON_NOMAN_CANCEL_ALL, null);
+                    REASON_APP_CANCEL_ALL, null);
         }
 
         @Override
@@ -2879,8 +2879,8 @@
             case REASON_LISTENER_CANCEL_ALL:
                 mUsageStats.registerDismissedByUser(r);
                 break;
-            case REASON_NOMAN_CANCEL:
-            case REASON_NOMAN_CANCEL_ALL:
+            case REASON_APP_CANCEL:
+            case REASON_APP_CANCEL_ALL:
                 mUsageStats.registerRemovedByApp(r);
                 break;
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0fde27f..8ef8276 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8397,9 +8397,9 @@
                 }
             }
             if ((p.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
-                ArraySet<String> appOpPerms = mAppOpPermissionPackages.get(p.info.name);
-                if (appOpPerms != null) {
-                    appOpPerms.remove(pkg.packageName);
+                ArraySet<String> appOpPkgs = mAppOpPermissionPackages.get(p.info.name);
+                if (appOpPkgs != null) {
+                    appOpPkgs.remove(pkg.packageName);
                 }
             }
         }
@@ -8413,10 +8413,10 @@
             String perm = pkg.requestedPermissions.get(i);
             BasePermission bp = mSettings.mPermissions.get(perm);
             if (bp != null && (bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
-                ArraySet<String> appOpPerms = mAppOpPermissionPackages.get(perm);
-                if (appOpPerms != null) {
-                    appOpPerms.remove(pkg.packageName);
-                    if (appOpPerms.isEmpty()) {
+                ArraySet<String> appOpPkgs = mAppOpPermissionPackages.get(perm);
+                if (appOpPkgs != null) {
+                    appOpPkgs.remove(pkg.packageName);
+                    if (appOpPkgs.isEmpty()) {
                         mAppOpPermissionPackages.remove(perm);
                     }
                 }
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index 051b7fb..0c80ffa 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -47,6 +47,7 @@
     private final int mTransientFlag;
     private final int mUnhideFlag;
     private final int mTranslucentFlag;
+    private final int mTransparentFlag;
     private final int mStatusBarManagerId;
     private final int mTranslucentWmFlag;
     protected final Handler mHandler;
@@ -63,13 +64,14 @@
     private boolean mNoAnimationOnNextShow;
 
     public BarController(String tag, int transientFlag, int unhideFlag, int translucentFlag,
-            int statusBarManagerId, int translucentWmFlag) {
+            int statusBarManagerId, int translucentWmFlag, int transparentFlag) {
         mTag = "BarController." + tag;
         mTransientFlag = transientFlag;
         mUnhideFlag = unhideFlag;
         mTranslucentFlag = translucentFlag;
         mStatusBarManagerId = statusBarManagerId;
         mTranslucentWmFlag = translucentWmFlag;
+        mTransparentFlag = transparentFlag;
         mHandler = new Handler();
     }
 
@@ -126,13 +128,13 @@
                     vis &= ~mTranslucentFlag;
                 }
                 if ((fl & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
-                    vis |= View.SYSTEM_UI_TRANSPARENT;
+                    vis |= mTransparentFlag;
                 } else {
-                    vis &= ~View.SYSTEM_UI_TRANSPARENT;
+                    vis &= ~mTransparentFlag;
                 }
             } else {
                 vis = (vis & ~mTranslucentFlag) | (oldVis & mTranslucentFlag);
-                vis = (vis & ~View.SYSTEM_UI_TRANSPARENT) | (oldVis & View.SYSTEM_UI_TRANSPARENT);
+                vis = (vis & ~mTransparentFlag) | (oldVis & mTransparentFlag);
             }
         }
         return vis;
@@ -247,7 +249,7 @@
             }
         }
         if (mShowTransparent) {
-            vis |= View.SYSTEM_UI_TRANSPARENT;
+            vis |= mTransparentFlag;
             if (mSetUnHideFlagWhenNextTransparent) {
                 vis |= mUnhideFlag;
                 mSetUnHideFlagWhenNextTransparent = false;
@@ -258,7 +260,7 @@
             vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;  // never show transient bars in low profile
         }
         if ((vis & mTranslucentFlag) != 0 || (oldVis & mTranslucentFlag) != 0 ||
-                ((vis | oldVis) & View.SYSTEM_UI_TRANSPARENT) != 0) {
+                ((vis | oldVis) & mTransparentFlag) != 0) {
             mLastTranslucent = SystemClock.uptimeMillis();
         }
         return vis;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 9a7d153..fe427d3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -158,8 +158,7 @@
     static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
 
     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
-    // No longer recommended for desk docks; still useful in car docks.
-    static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
+    // No longer recommended for desk docks;
     static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
 
     static final int SHORT_PRESS_POWER_NOTHING = 0;
@@ -210,7 +209,8 @@
             | View.SYSTEM_UI_FLAG_FULLSCREEN
             | View.STATUS_BAR_TRANSLUCENT
             | View.NAVIGATION_BAR_TRANSLUCENT
-            | View.SYSTEM_UI_TRANSPARENT;
+            | View.STATUS_BAR_TRANSPARENT
+            | View.NAVIGATION_BAR_TRANSPARENT;
 
     private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -316,6 +316,10 @@
     int[] mNavigationBarHeightForRotation = new int[4];
     int[] mNavigationBarWidthForRotation = new int[4];
 
+    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
+    // This is for car dock and this is updated from resource.
+    private boolean mEnableCarDockHomeCapture = true;
+
     boolean mBootMessageNeedsHiding;
     KeyguardServiceDelegate mKeyguardDelegate;
     final Runnable mWindowManagerDrawCallback = new Runnable() {
@@ -623,6 +627,8 @@
     private final LogDecelerateInterpolator mLogDecelerateInterpolator
             = new LogDecelerateInterpolator(100, 0);
 
+    private boolean mForceWindowDrawsStatusBarBackground;
+
     private static final int MSG_ENABLE_POINTER_LOCATION = 1;
     private static final int MSG_DISABLE_POINTER_LOCATION = 2;
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
@@ -803,7 +809,8 @@
             View.NAVIGATION_BAR_UNHIDE,
             View.NAVIGATION_BAR_TRANSLUCENT,
             StatusBarManager.WINDOW_NAVIGATION_BAR,
-            WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+            WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
+            View.NAVIGATION_BAR_TRANSPARENT);
 
     private ImmersiveModeConfirmation mImmersiveModeConfirmation;
 
@@ -1398,6 +1405,8 @@
         mHomeIntent.addCategory(Intent.CATEGORY_HOME);
         mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        mEnableCarDockHomeCapture = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableCarDockHomeLaunch);
         mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
         mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
         mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -1582,6 +1591,8 @@
 
         mScreenshotChordEnabled = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_enableScreenshotChord);
+        mForceWindowDrawsStatusBarBackground = mContext.getResources().getBoolean(
+                R.bool.config_forceWindowDrawsStatusBarBackground);
 
         mGlobalKeyManager = new GlobalKeyManager(mContext);
 
@@ -2044,10 +2055,14 @@
             attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         }
 
-        if (ActivityManager.isHighEndGfx()
-                && (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
-            attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+        if (ActivityManager.isHighEndGfx()) {
+            if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
+                attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+            }
+            if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+                    || mForceWindowDrawsStatusBarBackground) {
+                attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+            }
         }
     }
 
@@ -3604,7 +3619,7 @@
             final int sysui = mLastSystemUiFlags;
             boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
             boolean navTranslucent = (sysui
-                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
+                    & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
             boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
             boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
             boolean navAllowedHidden = immersive || immersiveSticky;
@@ -3672,7 +3687,7 @@
 
             boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
             boolean statusBarTranslucent = (sysui
-                    & (View.STATUS_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
+                    & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
             if (!isKeyguardShowing) {
                 statusBarTranslucent &= areTranslucentBarsAllowed();
             }
@@ -4003,7 +4018,8 @@
                         && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
                         && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
                         && (fl & WindowManager.LayoutParams.
-                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
+                                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
+                        && !mForceWindowDrawsStatusBarBackground) {
                     // Ensure policy decor includes status bar
                     dcf.top = mStableTop;
                 }
@@ -6404,7 +6420,7 @@
      * true:
      * <ul>
      *  <li>The device is not in either car mode or desk mode
-     *  <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
+     *  <li>The device is in car mode but mEnableCarDockHomeCapture is false
      *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
      *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
      *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
@@ -6418,7 +6434,7 @@
         // is, when in car mode you should be taken to car home regardless
         // of whether we are actually in a car dock.
         if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
-            if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
+            if (mEnableCarDockHomeCapture) {
                 intent = mCarDockIntent;
             }
         } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
@@ -6728,10 +6744,7 @@
         final boolean freeformStackVisible =
                 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
         final boolean forceShowSystemBars = dockedStackVisible || freeformStackVisible;
-        // TODO(multi-window): Update to force opaque independently for status bar and nav bar.
-        // This will require refactoring the code to have separate vis flag for each bar so it can
-        // be adjusted independently.
-        final boolean forceOpaqueSystemBars = forceShowSystemBars;
+        final boolean forceOpaqueSystemBars = forceShowSystemBars && !mForceStatusBarFromKeyguard;
 
         // apply translucent bar vis flags
         WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
@@ -6761,6 +6774,11 @@
                     | View.SYSTEM_UI_TRANSPARENT);
         }
 
+        if (mForceWindowDrawsStatusBarBackground) {
+            vis |= View.STATUS_BAR_TRANSPARENT;
+            vis &= ~View.STATUS_BAR_TRANSLUCENT;
+        }
+
         // update status bar
         boolean immersiveSticky =
                 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
@@ -6938,6 +6956,7 @@
         pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
         pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
                 pw.print(" mDockMode="); pw.print(mDockMode);
+                pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
                 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
                 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
         pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
diff --git a/services/core/java/com/android/server/policy/StatusBarController.java b/services/core/java/com/android/server/policy/StatusBarController.java
index b935f5a..9d353c6 100644
--- a/services/core/java/com/android/server/policy/StatusBarController.java
+++ b/services/core/java/com/android/server/policy/StatusBarController.java
@@ -111,7 +111,8 @@
                 View.STATUS_BAR_UNHIDE,
                 View.STATUS_BAR_TRANSLUCENT,
                 StatusBarManager.WINDOW_STATUS_BAR,
-                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
+                View.STATUS_BAR_TRANSPARENT);
     }
 
     public AppTransitionListener getAppTransitionListener() {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 22f1d63..e4f6c56 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -252,7 +252,7 @@
         }
 
         int boundsChange = BOUNDS_CHANGE_NONE;
-        if (mBounds.left != bounds.left || mBounds.right != bounds.right) {
+        if (mBounds.left != bounds.left || mBounds.top != bounds.top) {
             boundsChange |= BOUNDS_CHANGE_POSITION;
         }
         if (mBounds.width() != bounds.width() || mBounds.height() != bounds.height()) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4736c60..f25f1e3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2517,7 +2517,7 @@
     }
 
     void repositionChild(Session session, IWindow client,
-            int top, int left, int right, int bottom,
+            int left, int top, int right, int bottom,
             long deferTransactionUntilFrame, Rect outFrame) {
         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild");
         long origId = Binder.clearCallingIdentity();
@@ -2538,23 +2538,24 @@
                 win.mAttrs.y = top;
                 win.mAttrs.width = right - left;
                 win.mAttrs.height = bottom - top;
-
                 win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
 
-                win.mWinAnimator.computeShownFrameLocked();
-
                 if (SHOW_TRANSACTIONS) {
                     Slog.i(TAG, ">>> OPEN TRANSACTION repositionChild");
                 }
 
                 SurfaceControl.openTransaction();
 
+                win.applyGravityAndUpdateFrame();
+                win.mWinAnimator.computeShownFrameLocked();
+
+                win.mWinAnimator.setSurfaceBoundariesLocked(false);
+
                 if (deferTransactionUntilFrame > 0) {
                     win.mWinAnimator.mSurfaceController.deferTransactionUntil(
                             win.mAttachedWindow.mWinAnimator.mSurfaceController.getHandle(),
                             deferTransactionUntilFrame);
                 }
-                win.mWinAnimator.setSurfaceBoundariesLocked(false);
 
                 SurfaceControl.closeTransaction();
                 if (SHOW_TRANSACTIONS) {
@@ -2588,6 +2589,7 @@
             if (win == null) {
                 return 0;
             }
+
             WindowStateAnimator winAnimator = win.mWinAnimator;
             if (viewVisibility != View.GONE) {
                 win.setRequestedSize(requestedWidth, requestedHeight);
@@ -10193,7 +10195,7 @@
     public void setReplacingWindow(IBinder token, boolean animate) {
         synchronized (mWindowMap) {
             AppWindowToken appWindowToken = findAppWindowToken(token);
-            if (appWindowToken == null) {
+            if (appWindowToken == null || !appWindowToken.isVisible()) {
                 Slog.w(TAG, "Attempted to set replacing window on non-existing app token " + token);
                 return;
             }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index cfa2bb3..5e38492 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -72,6 +72,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
 import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
@@ -618,39 +619,6 @@
         final int pw = mContainingFrame.width();
         final int ph = mContainingFrame.height();
 
-        int w,h;
-        if ((mAttrs.flags & FLAG_SCALED) != 0) {
-            if (mAttrs.width < 0) {
-                w = pw;
-            } else if (mEnforceSizeCompat) {
-                w = (int)(mAttrs.width * mGlobalScale + .5f);
-            } else {
-                w = mAttrs.width;
-            }
-            if (mAttrs.height < 0) {
-                h = ph;
-            } else if (mEnforceSizeCompat) {
-                h = (int)(mAttrs.height * mGlobalScale + .5f);
-            } else {
-                h = mAttrs.height;
-            }
-        } else {
-            if (mAttrs.width == WindowManager.LayoutParams.MATCH_PARENT) {
-                w = pw;
-            } else if (mEnforceSizeCompat) {
-                w = (int)(mRequestedWidth * mGlobalScale + .5f);
-            } else {
-                w = mRequestedWidth;
-            }
-            if (mAttrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
-                h = ph;
-            } else if (mEnforceSizeCompat) {
-                h = (int)(mRequestedHeight * mGlobalScale + .5f);
-            } else {
-                h = mRequestedHeight;
-            }
-        }
-
         if (!mParentFrame.equals(pf)) {
             //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
             //        + " to " + pf);
@@ -676,28 +644,7 @@
         final int fw = mFrame.width();
         final int fh = mFrame.height();
 
-        float x, y;
-        if (mEnforceSizeCompat) {
-            x = mAttrs.x * mGlobalScale;
-            y = mAttrs.y * mGlobalScale;
-        } else {
-            x = mAttrs.x;
-            y = mAttrs.y;
-        }
-
-        if (nonFullscreenTask) {
-            // Make sure window fits in containing frame since it is in a non-fullscreen stack as
-            // required by {@link Gravity#apply} call.
-            w = Math.min(w, pw);
-            h = Math.min(h, ph);
-        }
-
-        Gravity.apply(mAttrs.gravity, w, h, mContainingFrame,
-                (int) (x + mAttrs.horizontalMargin * pw),
-                (int) (y + mAttrs.verticalMargin * ph), mFrame);
-
-        // Now make sure the window fits in the overall display frame.
-        Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+        applyGravityAndUpdateFrame();
 
         // Calculate the outsets before the content frame gets shrinked to the window frame.
         if (hasOutsets) {
@@ -2229,4 +2176,69 @@
             rect.bottom = rect.top + (int)((rect.bottom - rect.top) / mVScale);
         }
     }
+
+    void applyGravityAndUpdateFrame() {
+        final int pw = mContainingFrame.width();
+        final int ph = mContainingFrame.height();
+        final Task task = getTask();
+        final boolean nonFullscreenTask = task != null && !task.isFullscreen();
+
+        float x, y;
+        int w,h;
+
+        if ((mAttrs.flags & FLAG_SCALED) != 0) {
+            if (mAttrs.width < 0) {
+                w = pw;
+            } else if (mEnforceSizeCompat) {
+                w = (int)(mAttrs.width * mGlobalScale + .5f);
+            } else {
+                w = mAttrs.width;
+            }
+            if (mAttrs.height < 0) {
+                h = ph;
+            } else if (mEnforceSizeCompat) {
+                h = (int)(mAttrs.height * mGlobalScale + .5f);
+            } else {
+                h = mAttrs.height;
+            }
+        } else {
+            if (mAttrs.width == MATCH_PARENT) {
+                w = pw;
+            } else if (mEnforceSizeCompat) {
+                w = (int)(mRequestedWidth * mGlobalScale + .5f);
+            } else {
+                w = mRequestedWidth;
+            }
+            if (mAttrs.height == MATCH_PARENT) {
+                h = ph;
+            } else if (mEnforceSizeCompat) {
+                h = (int)(mRequestedHeight * mGlobalScale + .5f);
+            } else {
+                h = mRequestedHeight;
+            }
+        }
+
+        if (mEnforceSizeCompat) {
+            x = mAttrs.x * mGlobalScale;
+            y = mAttrs.y * mGlobalScale;
+        } else {
+            x = mAttrs.x;
+            y = mAttrs.y;
+        }
+
+        if (nonFullscreenTask) {
+            // Make sure window fits in containing frame since it is in a non-fullscreen stack as
+            // required by {@link Gravity#apply} call.
+            w = Math.min(w, pw);
+            h = Math.min(h, ph);
+        }
+
+        // Set mFrame
+        Gravity.apply(mAttrs.gravity, w, h, mContainingFrame,
+                (int) (x + mAttrs.horizontalMargin * pw),
+                (int) (y + mAttrs.verticalMargin * ph), mFrame);
+
+        // Now make sure the window fits in the overall display frame.
+        Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+    }
 }