Merge "Update doc to reflect requirement of a Looper for changing animation's frame delay"
diff --git a/api/current.txt b/api/current.txt
index 7040e4d..77c64d7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4016,6 +4016,23 @@
     field public java.lang.String serviceDetails;
   }
 
+  public class AutomaticZenRule implements android.os.Parcelable {
+    ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
+    ctor public AutomaticZenRule(android.os.Parcel);
+    method public int describeContents();
+    method public android.net.Uri getConditionId();
+    method public int getInterruptionFilter();
+    method public java.lang.String getName();
+    method public android.content.ComponentName getOwner();
+    method public boolean isEnabled();
+    method public void setConditionId(android.net.Uri);
+    method public void setEnabled(boolean);
+    method public void setInterruptionFilter(int);
+    method public void setName(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.AutomaticZenRule> CREATOR;
+  }
+
   public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
     ctor public DatePickerDialog(android.content.Context, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
     ctor public DatePickerDialog(android.content.Context, int, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
@@ -5061,15 +5078,20 @@
   }
 
   public class NotificationManager {
+    method public boolean addOrUpdateAutomaticZenRule(android.app.AutomaticZenRule);
     method public void cancel(int);
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
+    method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
+    method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules();
     method public final int getCurrentInterruptionFilter();
     method public android.app.NotificationManager.Policy getNotificationPolicy();
     method public boolean isNotificationPolicyAccessGranted();
     method public void notify(int, android.app.Notification);
     method public void notify(java.lang.String, int, android.app.Notification);
+    method public boolean removeAutomaticZenRule(java.lang.String);
+    method public boolean renameAutomaticZenRule(java.lang.String, java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
@@ -9213,6 +9235,7 @@
     method public void setAppLabel(java.lang.CharSequence);
     method public void setAppPackageName(java.lang.String);
     method public void setInstallLocation(int);
+    method public void setOriginatingUid(int);
     method public void setOriginatingUri(android.net.Uri);
     method public void setReferrerUri(android.net.Uri);
     method public void setSize(long);
@@ -23567,7 +23590,7 @@
     method public static final int myPid();
     method public static final int myTid();
     method public static final int myUid();
-    method public static final android.os.UserHandle myUserHandle();
+    method public static android.os.UserHandle myUserHandle();
     method public static final void sendSignal(int, int);
     method public static final void setThreadPriority(int, int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
     method public static final void setThreadPriority(int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
@@ -45361,7 +45384,10 @@
   }
 
   public final class Constructor extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+    method public boolean equals(java.lang.Object);
     method public A getAnnotation(java.lang.Class<A>);
+    method public java.lang.annotation.Annotation[] getAnnotations();
+    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.Class<T> getDeclaringClass();
     method public java.lang.Class<?>[] getExceptionTypes();
     method public java.lang.reflect.Type[] getGenericExceptionTypes();
@@ -45371,6 +45397,7 @@
     method public java.lang.annotation.Annotation[][] getParameterAnnotations();
     method public java.lang.Class<?>[] getParameterTypes();
     method public java.lang.reflect.TypeVariable<java.lang.reflect.Constructor<T>>[] getTypeParameters();
+    method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
     method public boolean isSynthetic();
     method public boolean isVarArgs();
     method public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
@@ -45444,7 +45471,10 @@
   }
 
   public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+    method public boolean equals(java.lang.Object);
     method public A getAnnotation(java.lang.Class<A>);
+    method public java.lang.annotation.Annotation[] getAnnotations();
+    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.Class<?> getDeclaringClass();
     method public java.lang.Object getDefaultValue();
     method public java.lang.Class<?>[] getExceptionTypes();
@@ -45458,6 +45488,7 @@
     method public java.lang.Class<?> getReturnType();
     method public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
     method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
+    method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
     method public boolean isBridge();
     method public boolean isSynthetic();
     method public boolean isVarArgs();
diff --git a/api/system-current.txt b/api/system-current.txt
index 9b85df4..cff0055 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4127,6 +4127,23 @@
     field public java.lang.String serviceDetails;
   }
 
+  public class AutomaticZenRule implements android.os.Parcelable {
+    ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
+    ctor public AutomaticZenRule(android.os.Parcel);
+    method public int describeContents();
+    method public android.net.Uri getConditionId();
+    method public int getInterruptionFilter();
+    method public java.lang.String getName();
+    method public android.content.ComponentName getOwner();
+    method public boolean isEnabled();
+    method public void setConditionId(android.net.Uri);
+    method public void setEnabled(boolean);
+    method public void setInterruptionFilter(int);
+    method public void setName(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.AutomaticZenRule> CREATOR;
+  }
+
   public class BroadcastOptions {
     method public static android.app.BroadcastOptions makeBasic();
     method public void setTemporaryAppWhitelistDuration(long);
@@ -5178,15 +5195,20 @@
   }
 
   public class NotificationManager {
+    method public boolean addOrUpdateAutomaticZenRule(android.app.AutomaticZenRule);
     method public void cancel(int);
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
+    method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
+    method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules();
     method public final int getCurrentInterruptionFilter();
     method public android.app.NotificationManager.Policy getNotificationPolicy();
     method public boolean isNotificationPolicyAccessGranted();
     method public void notify(int, android.app.Notification);
     method public void notify(java.lang.String, int, android.app.Notification);
+    method public boolean removeAutomaticZenRule(java.lang.String);
+    method public boolean renameAutomaticZenRule(java.lang.String, java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
@@ -9496,6 +9518,7 @@
     method public void setAppPackageName(java.lang.String);
     method public void setGrantedRuntimePermissions(java.lang.String[]);
     method public void setInstallLocation(int);
+    method public void setOriginatingUid(int);
     method public void setOriginatingUri(android.net.Uri);
     method public void setReferrerUri(android.net.Uri);
     method public void setSize(long);
@@ -25519,7 +25542,7 @@
     method public static final int myPid();
     method public static final int myTid();
     method public static final int myUid();
-    method public static final android.os.UserHandle myUserHandle();
+    method public static android.os.UserHandle myUserHandle();
     method public static final void sendSignal(int, int);
     method public static final void setThreadPriority(int, int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
     method public static final void setThreadPriority(int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
@@ -47970,7 +47993,10 @@
   }
 
   public final class Constructor extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+    method public boolean equals(java.lang.Object);
     method public A getAnnotation(java.lang.Class<A>);
+    method public java.lang.annotation.Annotation[] getAnnotations();
+    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.Class<T> getDeclaringClass();
     method public java.lang.Class<?>[] getExceptionTypes();
     method public java.lang.reflect.Type[] getGenericExceptionTypes();
@@ -47980,6 +48006,7 @@
     method public java.lang.annotation.Annotation[][] getParameterAnnotations();
     method public java.lang.Class<?>[] getParameterTypes();
     method public java.lang.reflect.TypeVariable<java.lang.reflect.Constructor<T>>[] getTypeParameters();
+    method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
     method public boolean isSynthetic();
     method public boolean isVarArgs();
     method public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
@@ -48053,7 +48080,10 @@
   }
 
   public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+    method public boolean equals(java.lang.Object);
     method public A getAnnotation(java.lang.Class<A>);
+    method public java.lang.annotation.Annotation[] getAnnotations();
+    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.Class<?> getDeclaringClass();
     method public java.lang.Object getDefaultValue();
     method public java.lang.Class<?>[] getExceptionTypes();
@@ -48067,6 +48097,7 @@
     method public java.lang.Class<?> getReturnType();
     method public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
     method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
+    method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
     method public boolean isBridge();
     method public boolean isSynthetic();
     method public boolean isVarArgs();
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 40eb799..373a23f 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -55,4 +55,13 @@
      * @param userId ID of the user or {@link android.os.UserHandle#USER_ALL}
      */
     public abstract ComponentName getHomeActivityForUser(int userId);
+
+    /**
+     * Called when a user has been deleted. This can happen during normal device usage
+     * or just at startup, when partially removed users are purged. Any state persisted by the
+     * ActivityManager should be purged now.
+     *
+     * @param userId The user being cleaned up.
+     */
+    public abstract void onUserRemoved(int userId);
 }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0d53dbe..f29dba2 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1344,7 +1344,7 @@
         final VerificationParams verificationParams = new VerificationParams(null, null,
                 null, VerificationParams.NO_UID, null);
         installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
-                installerPackageName, verificationParams, null, UserHandle.myUserId());
+                installerPackageName, verificationParams, null, mContext.getUserId());
     }
 
     @Override
@@ -1354,7 +1354,7 @@
         final VerificationParams verificationParams = new VerificationParams(verificationURI, null,
                 null, VerificationParams.NO_UID, manifestDigest);
         installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
-                installerPackageName, verificationParams, encryptionParams, UserHandle.myUserId());
+                installerPackageName, verificationParams, encryptionParams, mContext.getUserId());
     }
 
     @Override
@@ -1362,14 +1362,14 @@
             IPackageInstallObserver observer, int flags, String installerPackageName,
             VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
         installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
-                installerPackageName, verificationParams, encryptionParams, UserHandle.myUserId());
+                installerPackageName, verificationParams, encryptionParams, mContext.getUserId());
     }
 
     @Override
     public void installPackage(Uri packageURI, PackageInstallObserver observer,
             int flags, String installerPackageName) {
         installPackageAsUser(packageURI, observer, flags, installerPackageName,
-                UserHandle.myUserId());
+                mContext.getUserId());
     }
 
     @Override
@@ -1389,7 +1389,7 @@
         final VerificationParams verificationParams = new VerificationParams(verificationURI, null,
                 null, VerificationParams.NO_UID, manifestDigest);
         installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
-                encryptionParams, UserHandle.myUserId());
+                encryptionParams, mContext.getUserId());
     }
 
     @Override
@@ -1397,7 +1397,7 @@
             PackageInstallObserver observer, int flags, String installerPackageName,
             VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
         installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
-                encryptionParams, UserHandle.myUserId());
+                encryptionParams, mContext.getUserId());
     }
 
     private void installCommon(Uri packageURI,
@@ -1421,7 +1421,7 @@
 
     @Override
     public int installExistingPackage(String packageName) throws NameNotFoundException {
-        return installExistingPackageAsUser(packageName, UserHandle.myUserId());
+        return installExistingPackageAsUser(packageName, mContext.getUserId());
     }
 
     @Override
@@ -1726,7 +1726,7 @@
 
     @Override
     public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
-        deletePackageAsUser(packageName, observer, flags, UserHandle.myUserId());
+        deletePackageAsUser(packageName, observer, flags, mContext.getUserId());
     }
 
     @Override
@@ -1838,7 +1838,7 @@
     public void replacePreferredActivity(IntentFilter filter,
                                          int match, ComponentName[] set, ComponentName activity) {
         try {
-            mPM.replacePreferredActivity(filter, match, set, activity, UserHandle.myUserId());
+            mPM.replacePreferredActivity(filter, match, set, activity, mContext.getUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -2169,7 +2169,7 @@
     }
 
     private UserInfo getUserIfProfile(int userHandle) {
-        List<UserInfo> userProfiles = getUserManager().getProfiles(UserHandle.myUserId());
+        List<UserInfo> userProfiles = getUserManager().getProfiles(mContext.getUserId());
         for (UserInfo user : userProfiles) {
             if (user.id == userHandle) {
                 return user;
diff --git a/core/java/android/app/AutomaticZenRule.aidl b/core/java/android/app/AutomaticZenRule.aidl
new file mode 100644
index 0000000..feb21d6
--- /dev/null
+++ b/core/java/android/app/AutomaticZenRule.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.app;
+
+parcelable AutomaticZenRule;
\ No newline at end of file
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
new file mode 100644
index 0000000..fea5624
--- /dev/null
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -0,0 +1,190 @@
+/**
+ * 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.app;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Rule instance information for zen mode.
+ */
+public class AutomaticZenRule implements Parcelable {
+
+    private boolean enabled = false;
+    private String name;
+    private int interruptionFilter;
+    private Uri conditionId;
+    private ComponentName owner;
+
+    /**
+     * Creates an automatic zen rule.
+     *
+     * @param name The name of the rule.
+     * @param owner The Condition Provider service that owns this rule.
+     * @param conditionId A representation of the state that should cause the Condition Provider
+     *                    service to apply the interruption filter.
+     * @param interruptionFilter The interruption filter defines which notifications are allowed to
+     *                           interrupt the user (e.g. via sound &amp; vibration) while this rule
+     *                           is active.
+     * @param enabled Whether the rule is enabled.
+     */
+    public AutomaticZenRule(String name, ComponentName owner, Uri conditionId,
+            int interruptionFilter, boolean enabled) {
+        this.name = name;
+        this.owner = owner;
+        this.conditionId = conditionId;
+        this.interruptionFilter = interruptionFilter;
+        this.enabled = enabled;
+    }
+
+    public AutomaticZenRule(Parcel source) {
+        enabled = source.readInt() == 1;
+        if (source.readInt() == 1) {
+            name = source.readString();
+        }
+        interruptionFilter = source.readInt();
+        conditionId = source.readParcelable(null);
+        owner = source.readParcelable(null);
+    }
+
+    /**
+     * Returns the {@link ComponentName} of the condition provider service that owns this rule.
+     */
+    public ComponentName getOwner() {
+        return owner;
+    }
+
+    /**
+     * Returns the representation of the state that causes this rule to become active.
+     */
+    public Uri getConditionId() {
+        return conditionId;
+    }
+
+    /**
+     * Returns the interruption filter that is applied when this rule is active.
+     */
+    public int getInterruptionFilter() {
+        return interruptionFilter;
+    }
+
+    /**
+     * Returns the name of this rule.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns whether this rule is enabled.
+     */
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    /**
+     * Sets the representation of the state that causes this rule to become active.
+     */
+    public void setConditionId(Uri conditionId) {
+        this.conditionId = conditionId;
+    }
+
+    /**
+     * Sets the interruption filter that is applied when this rule is active.
+     * @param interruptionFilter One of the INTERRUPTION_FILTER_ constants in NotificationManager.
+     */
+    public void setInterruptionFilter(int interruptionFilter) {
+        this.interruptionFilter = interruptionFilter;
+    }
+
+    /**
+     * Sets the name of this rule.
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Enables this rule.
+     */
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(enabled ? 1 : 0);
+        if (name != null) {
+            dest.writeInt(1);
+            dest.writeString(name);
+        } else {
+            dest.writeInt(0);
+        }
+        dest.writeInt(interruptionFilter);
+        dest.writeParcelable(conditionId, 0);
+        dest.writeParcelable(owner, 0);
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(AutomaticZenRule.class.getSimpleName()).append('[')
+                .append("enabled=").append(enabled)
+                .append(",name=").append(name)
+                .append(",interruptionFilter=").append(interruptionFilter)
+                .append(",conditionId=").append(conditionId)
+                .append(",owner=").append(owner)
+                .append(']').toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof AutomaticZenRule)) return false;
+        if (o == this) return true;
+        final AutomaticZenRule other = (AutomaticZenRule) o;
+        return other.enabled == enabled
+                && Objects.equals(other.name, name)
+                && other.interruptionFilter == interruptionFilter
+                && Objects.equals(other.conditionId, conditionId)
+                && Objects.equals(other.owner, owner);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(enabled, name, interruptionFilter, conditionId, owner);
+    }
+
+    public static final Parcelable.Creator<AutomaticZenRule> CREATOR
+            = new Parcelable.Creator<AutomaticZenRule>() {
+        @Override
+        public AutomaticZenRule createFromParcel(Parcel source) {
+            return new AutomaticZenRule(source);
+        }
+        @Override
+        public AutomaticZenRule[] newArray(int size) {
+            return new AutomaticZenRule[size];
+        }
+    };
+}
\ No newline at end of file
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index f78fb47..920fbe9 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -30,6 +30,7 @@
 import android.service.notification.IConditionProvider;
 import android.service.notification.INotificationListener;
 import android.service.notification.StatusBarNotification;
+import android.app.AutomaticZenRule;
 import android.service.notification.ZenModeConfig;
 
 /** {@hide} */
@@ -92,6 +93,11 @@
     String[] getPackagesRequestingNotificationPolicyAccess();
     boolean isNotificationPolicyAccessGrantedForPackage(String pkg);
     void setNotificationPolicyAccessGranted(String pkg, boolean granted);
+    AutomaticZenRule getAutomaticZenRule(String name);
+    List<AutomaticZenRule> getAutomaticZenRules();
+    boolean addOrUpdateAutomaticZenRule(in AutomaticZenRule automaticZenRule);
+    boolean renameAutomaticZenRule(String oldName, String newName);
+    boolean removeAutomaticZenRule(String name);
 
     byte[] getBackupPayload(int user);
     void applyRestore(in byte[] payload, int user);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 605c006..cbf198b 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -420,6 +420,106 @@
     }
 
     /**
+     * Returns AutomaticZenRules owned by the caller.
+     *
+     * <p>
+     * Only available if policy access is granted to this package.
+     * See {@link #isNotificationPolicyAccessGranted}.
+     */
+    public List<AutomaticZenRule> getAutomaticZenRules() {
+        INotificationManager service = getService();
+        try {
+            return service.getAutomaticZenRules();
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
+
+    /**
+     * Returns the AutomaticZenRule with the given name, if it exists and the caller has access.
+     *
+     * <p>
+     * Only available if policy access is granted to this package.
+     * See {@link #isNotificationPolicyAccessGranted}.
+     *
+     * <p>
+     * Returns null if there are no zen rules that match the given name, or if the calling package
+     * doesn't own the matching rule. See {@link AutomaticZenRule#getOwner}.
+     */
+    public AutomaticZenRule getAutomaticZenRule(String name) {
+        INotificationManager service = getService();
+        try {
+            return service.getAutomaticZenRule(name);
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
+
+    /**
+     * Creates or updates the given zen rule.
+     *
+     * <p>
+     * Only available if policy access is granted to this package.
+     * See {@link #isNotificationPolicyAccessGranted}.
+     *
+     * <p>
+     * Callers can only update rules that they own. See {@link AutomaticZenRule#getOwner}.
+     * @param automaticZenRule the rule to create or update.
+     * @return Whether the rule was successfully created or updated.
+     */
+    public boolean addOrUpdateAutomaticZenRule(AutomaticZenRule automaticZenRule) {
+        INotificationManager service = getService();
+        try {
+            return service.addOrUpdateAutomaticZenRule(automaticZenRule);
+        } catch (RemoteException e) {
+        }
+        return false;
+    }
+
+    /**
+     * Renames a zen rule.
+     *
+     * <p>
+     * Only available if policy access is granted to this package.
+     * See {@link #isNotificationPolicyAccessGranted}.
+     *
+     * <p>
+     * Callers can only update rules that they own. See {@link AutomaticZenRule#getOwner}.
+     * @param oldName The name of the rule to update.
+     * @param newName The new name for the rule.
+     * @return Whether the rule was successfully updated.
+     */
+    public boolean renameAutomaticZenRule(String oldName, String newName) {
+        INotificationManager service = getService();
+        try {
+            return service.renameAutomaticZenRule(oldName, newName);
+        } catch (RemoteException e) {
+        }
+        return false;
+    }
+
+    /**
+     * Deletes the automatic zen rule with the given name.
+     *
+     * <p>
+     * Only available if policy access is granted to this package.
+     * See {@link #isNotificationPolicyAccessGranted}.
+     *
+     * <p>
+     * Callers can only delete rules that they own. See {@link AutomaticZenRule#getOwner}.
+     * @param name the name of the rule to delete.
+     * @return Whether the rule was successfully deleted.
+     */
+    public boolean removeAutomaticZenRule(String name) {
+        INotificationManager service = getService();
+        try {
+            return service.removeAutomaticZenRule(name);
+        } catch (RemoteException e) {
+        }
+        return false;
+    }
+
+    /**
      * Checks the ability to read/modify notification policy for the calling package.
      *
      * <p>
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index e6484e9..a118f16 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2438,6 +2438,17 @@
     }
 
     /**
+     * Determine whether or not creating a guest user has been disabled for the device
+     *
+     * @hide
+     */
+    public boolean getGuestUserDisabled(@Nullable ComponentName admin) {
+        // Currently guest users can always be created if multi-user is enabled
+        // TODO introduce a policy for guest user creation
+        return false;
+    }
+
+    /**
      * Called by a device/profile owner to set whether the screen capture is disabled. Disabling
      * screen capture also prevents the content from being shown on display devices that do not have
      * a secure video output. See {@link android.view.Display#FLAG_SECURE} for more details about
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 9341be1..3283005 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -868,6 +868,9 @@
         public static final int MODE_INHERIT_EXISTING = 2;
 
         /** {@hide} */
+        public static final int UID_UNKNOWN = -1;
+
+        /** {@hide} */
         public int mode = MODE_INVALID;
         /** {@hide} */
         public int installFlags;
@@ -886,6 +889,8 @@
         /** {@hide} */
         public Uri originatingUri;
         /** {@hide} */
+        public int originatingUid = UID_UNKNOWN;
+        /** {@hide} */
         public Uri referrerUri;
         /** {@hide} */
         public String abiOverride;
@@ -915,6 +920,7 @@
             appIcon = source.readParcelable(null);
             appLabel = source.readString();
             originatingUri = source.readParcelable(null);
+            originatingUid = source.readInt();
             referrerUri = source.readParcelable(null);
             abiOverride = source.readString();
             volumeUuid = source.readString();
@@ -983,6 +989,15 @@
         }
 
         /**
+         * Sets the UID that initiated package installation. Used for verification purposes.
+         *
+         * @see PackageManager#EXTRA_VERIFICATION_INSTALLER_UID
+         */
+        public void setOriginatingUid(int originatingUid) {
+            this.originatingUid = originatingUid;
+        }
+
+        /**
          * Optionally set the URI that referred you to install this package. Used
          * for verification purposes.
          *
@@ -1022,6 +1037,11 @@
         }
 
         /** {@hide} */
+        public void setInstallFlagsForcePermissionPrompt() {
+            installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT;
+        }
+
+        /** {@hide} */
         public void dump(IndentingPrintWriter pw) {
             pw.printPair("mode", mode);
             pw.printHexPair("installFlags", installFlags);
@@ -1031,6 +1051,7 @@
             pw.printPair("appIcon", (appIcon != null));
             pw.printPair("appLabel", appLabel);
             pw.printPair("originatingUri", originatingUri);
+            pw.printPair("originatingUid", originatingUid);
             pw.printPair("referrerUri", referrerUri);
             pw.printPair("abiOverride", abiOverride);
             pw.printPair("volumeUuid", volumeUuid);
@@ -1053,6 +1074,7 @@
             dest.writeParcelable(appIcon, flags);
             dest.writeString(appLabel);
             dest.writeParcelable(originatingUri, flags);
+            dest.writeInt(originatingUid);
             dest.writeParcelable(referrerUri, flags);
             dest.writeString(abiOverride);
             dest.writeString(volumeUuid);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 697b946..82cbbbe 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -422,6 +422,15 @@
     public static final int INSTALL_FORCE_VOLUME_UUID = 0x00000200;
 
     /**
+     * Flag parameter for {@link #installPackage} to indicate that we always want to force
+     * the prompt for permission approval. This overrides any special behaviour for internal
+     * components.
+     *
+     * @hide
+     */
+    public static final int INSTALL_FORCE_PERMISSION_PROMPT = 0x00000400;
+
+    /**
      * Flag parameter for
      * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
      * that you don't want to kill the app containing the component.  Be careful when you set this
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e29bd2c..0606e35 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -16,24 +16,14 @@
 
 package android.content.res;
 
-import android.annotation.AttrRes;
-import android.annotation.ColorInt;
-import android.annotation.StyleRes;
-import android.annotation.StyleableRes;
-import android.graphics.drawable.DrawableInflater;
-import android.icu.text.PluralRules;
-import com.android.internal.util.GrowingArrayUtils;
-import com.android.internal.util.XmlUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.animation.Animator;
 import android.animation.StateListAnimator;
 import android.annotation.AnimRes;
 import android.annotation.AnyRes;
 import android.annotation.ArrayRes;
+import android.annotation.AttrRes;
 import android.annotation.BoolRes;
+import android.annotation.ColorInt;
 import android.annotation.ColorRes;
 import android.annotation.DimenRes;
 import android.annotation.DrawableRes;
@@ -45,18 +35,23 @@
 import android.annotation.PluralsRes;
 import android.annotation.RawRes;
 import android.annotation.StringRes;
+import android.annotation.StyleRes;
+import android.annotation.StyleableRes;
 import android.annotation.XmlRes;
 import android.content.pm.ActivityInfo;
 import android.graphics.Movie;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Drawable.ConstantState;
+import android.graphics.drawable.DrawableInflater;
+import android.icu.text.PluralRules;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Trace;
 import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
+import android.util.LocaleList;
 import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.Pools.SynchronizedPool;
@@ -65,6 +60,12 @@
 import android.view.ViewDebug;
 import android.view.ViewHierarchyEncoder;
 
+import com.android.internal.util.GrowingArrayUtils;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
@@ -372,7 +373,7 @@
     private PluralRules getPluralRule() {
         synchronized (sSync) {
             if (mPluralRule == null) {
-                mPluralRule = PluralRules.forLocale(mConfiguration.locale);
+                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().getPrimary());
             }
             return mPluralRule;
         }
@@ -435,7 +436,7 @@
     @NonNull
     public String getString(@StringRes int id, Object... formatArgs) throws NotFoundException {
         final String raw = getString(id);
-        return String.format(mConfiguration.locale, raw, formatArgs);
+        return String.format(mConfiguration.getLocales().getPrimary(), raw, formatArgs);
     }
 
     /**
@@ -466,7 +467,7 @@
     public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
             throws NotFoundException {
         String raw = getQuantityText(id, quantity).toString();
-        return String.format(mConfiguration.locale, raw, formatArgs);
+        return String.format(mConfiguration.getLocales().getPrimary(), raw, formatArgs);
     }
 
     /**
@@ -1971,9 +1972,10 @@
             mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
 
             final int configChanges = calcConfigChanges(config);
-            if (mConfiguration.locale == null) {
-                mConfiguration.locale = Locale.getDefault();
-                mConfiguration.setLayoutDirection(mConfiguration.locale);
+            LocaleList locales = mConfiguration.getLocales();
+            if (locales.isEmpty()) {
+                locales = LocaleList.getDefault();
+                mConfiguration.setLocales(locales);
             }
             if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
                 mMetrics.densityDpi = mConfiguration.densityDpi;
@@ -1981,11 +1983,6 @@
             }
             mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
 
-            String locale = null;
-            if (mConfiguration.locale != null) {
-                locale = adjustLanguageTag(mConfiguration.locale.toLanguageTag());
-            }
-
             final int width, height;
             if (mMetrics.widthPixels >= mMetrics.heightPixels) {
                 width = mMetrics.widthPixels;
@@ -2005,8 +2002,10 @@
                 keyboardHidden = mConfiguration.keyboardHidden;
             }
 
+            // TODO: Pass the whole locale list to setConfiguration()
             mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
-                    locale, mConfiguration.orientation,
+                    adjustLanguageTag(locales.getPrimary().toLanguageTag()),
+                    mConfiguration.orientation,
                     mConfiguration.touchscreen,
                     mConfiguration.densityDpi, mConfiguration.keyboard,
                     keyboardHidden, mConfiguration.navigation, width, height,
@@ -2030,7 +2029,7 @@
         }
         synchronized (sSync) {
             if (mPluralRule != null) {
-                mPluralRule = PluralRules.forLocale(config.locale);
+                mPluralRule = PluralRules.forLocale(config.getLocales().getPrimary());
             }
         }
     }
@@ -2049,9 +2048,8 @@
 
             mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
 
-            if (mTmpConfig.locale == null) {
-                mTmpConfig.locale = Locale.getDefault();
-                mTmpConfig.setLayoutDirection(mTmpConfig.locale);
+            if (mTmpConfig.getLocales().isEmpty()) {
+                mTmpConfig.setLocales(LocaleList.getDefault());
             }
             configChanges = mConfiguration.updateFrom(mTmpConfig);
             configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index c4f62ba..9fdbec3 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -23,8 +23,11 @@
 
 interface IPowerManager
 {
-    // WARNING: The first five methods must remain the first five methods because their
-    // transaction numbers must not change unless IPowerManager.cpp is also updated.
+    // WARNING: When methods are inserted or deleted, the transaction IDs in
+    // frameworks/native/include/powermanager/IPowerManager.h must be updated to match the order in this file.
+    //
+    // When a method's argument list is changed, BnPowerManager's corresponding serialization code (if any) in
+    // frameworks/native/services/powermanager/IPowerManager.cpp must be updated.
     void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws,
             String historyTag);
     void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName,
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 37467ca..d178d20 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -20,6 +20,7 @@
 import android.annotation.SystemApi;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
@@ -1337,12 +1338,15 @@
     }
 
     /**
-     * Returns true if the user switcher should be shown, this will be if there
-     * are multiple users that aren't managed profiles.
+     * Returns true if the user switcher should be shown, this will be if device supports multi-user
+     * and there are at least 2 users available that are not managed profiles.
      * @hide
      * @return true if user switcher should be shown.
      */
     public boolean isUserSwitcherEnabled() {
+        if (!supportsMultipleUsers()) {
+            return false;
+        }
         List<UserInfo> users = getUsers(true);
         if (users == null) {
            return false;
@@ -1353,8 +1357,8 @@
                 ++switchableUserCount;
             }
         }
-        final boolean guestEnabled = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.GUEST_USER_ENABLED, 0) == 1;
+        final boolean guestEnabled = !mContext.getSystemService(DevicePolicyManager.class)
+                .getGuestUserDisabled(null);
         return switchableUserCount > 1 || guestEnabled;
     }
 
diff --git a/core/java/android/preference/SeekBarPreference.java b/core/java/android/preference/SeekBarPreference.java
index 67f6409..5414f00 100644
--- a/core/java/android/preference/SeekBarPreference.java
+++ b/core/java/android/preference/SeekBarPreference.java
@@ -96,18 +96,15 @@
 
     @Override
     public boolean onKey(View v, int keyCode, KeyEvent event) {
-        if (event.getAction() != KeyEvent.ACTION_UP) {
-            if (keyCode == KeyEvent.KEYCODE_PLUS
-                    || keyCode == KeyEvent.KEYCODE_EQUALS) {
-                setProgress(getProgress() + 1);
-                return true;
-            }
-            if (keyCode == KeyEvent.KEYCODE_MINUS) {
-                setProgress(getProgress() - 1);
-                return true;
-            }
+        if (event.getAction() != KeyEvent.ACTION_DOWN) {
+            return false;
         }
-        return false;
+
+        SeekBar seekBar = (SeekBar) v.findViewById(com.android.internal.R.id.seekbar);
+        if (seekBar == null) {
+            return false;
+        }
+        return seekBar.onKeyDown(keyCode, event);
     }
 
     public void setMax(int max) {
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 1a83cd5..241e6db 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -19,6 +19,7 @@
 import static android.net.TrafficStats.KB_IN_BYTES;
 import static android.system.OsConstants.SEEK_SET;
 
+import android.annotation.Nullable;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -136,6 +137,9 @@
      */
     private static final int THUMBNAIL_BUFFER_SIZE = (int) (128 * KB_IN_BYTES);
 
+    /** {@hide} */
+    public static final String PACKAGE_DOCUMENTS_UI = "com.android.documentsui";
+
     /**
      * Constants related to a document, including {@link Cursor} column names
      * and flags.
@@ -761,19 +765,33 @@
      * @see #buildDocumentUri(String, String)
      * @see #buildDocumentUriUsingTree(Uri, String)
      */
-    public static boolean isDocumentUri(Context context, Uri uri) {
-        final List<String> paths = uri.getPathSegments();
-        if (paths.size() == 2 && PATH_DOCUMENT.equals(paths.get(0))) {
-            return isDocumentsProvider(context, uri.getAuthority());
-        }
-        if (paths.size() == 4 && PATH_TREE.equals(paths.get(0))
-                && PATH_DOCUMENT.equals(paths.get(2))) {
-            return isDocumentsProvider(context, uri.getAuthority());
+    public static boolean isDocumentUri(Context context, @Nullable Uri uri) {
+        if (isContentUri(uri) && isDocumentsProvider(context, uri.getAuthority())) {
+            final List<String> paths = uri.getPathSegments();
+            if (paths.size() == 2) {
+                return PATH_DOCUMENT.equals(paths.get(0));
+            } else if (paths.size() == 4) {
+                return PATH_TREE.equals(paths.get(0)) && PATH_DOCUMENT.equals(paths.get(2));
+            }
         }
         return false;
     }
 
     /** {@hide} */
+    public static boolean isRootUri(Context context, @Nullable Uri uri) {
+        if (isContentUri(uri) && isDocumentsProvider(context, uri.getAuthority())) {
+            final List<String> paths = uri.getPathSegments();
+            return (paths.size() == 2 && PATH_ROOT.equals(paths.get(0)));
+        }
+        return false;
+    }
+
+    /** {@hide} */
+    public static boolean isContentUri(@Nullable Uri uri) {
+        return uri != null && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme());
+    }
+
+    /** {@hide} */
     public static boolean isTreeUri(Uri uri) {
         final List<String> paths = uri.getPathSegments();
         return (paths.size() >= 2 && PATH_TREE.equals(paths.get(0)));
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 225f0cf..d601831 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7689,14 +7689,6 @@
         public static final String DEVICE_NAME = "device_name";
 
         /**
-         * Whether it should be possible to create a guest user on the device.
-         * <p>
-         * Type: int (0 for disabled, 1 for enabled)
-         * @hide
-         */
-        public static final String GUEST_USER_ENABLED = "guest_user_enabled";
-
-        /**
          * Whether the NetworkScoringService has been first initialized.
          * <p>
          * Type: int (0 for false, 1 for true)
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 6310570..4de903e 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -755,6 +755,10 @@
         return rt;
     }
 
+    public static ComponentName getScheduleConditionProvider() {
+        return new ComponentName(SYSTEM_AUTHORITY, "ScheduleConditionProvider");
+    }
+
     public static class ScheduleInfo {
         public int[] days;
         public int startHour;
@@ -827,6 +831,10 @@
         return rt;
     }
 
+    public static ComponentName getEventConditionProvider() {
+        return new ComponentName(SYSTEM_AUTHORITY, "EventConditionProvider");
+    }
+
     public static class EventInfo {
         public static final int REPLY_ANY_EXCEPT_NO = 0;
         public static final int REPLY_YES_OR_MAYBE = 1;
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index 1665c75..f2b6041 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -16,15 +16,17 @@
 
 package android.text;
 
-import com.android.internal.annotations.GuardedBy;
-
 import android.annotation.Nullable;
 import android.util.Log;
 
-import libcore.io.IoUtils;
+import com.android.internal.annotations.GuardedBy;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
 import java.util.HashMap;
 import java.util.Locale;
 
@@ -45,12 +47,18 @@
     @GuardedBy("sLock")
     final static HashMap<Locale, Hyphenator> sMap = new HashMap<Locale, Hyphenator>();
 
-    final static Hyphenator sEmptyHyphenator = new Hyphenator(StaticLayout.nLoadHyphenator(""));
+    final static Hyphenator sEmptyHyphenator =
+            new Hyphenator(StaticLayout.nLoadHyphenator(null, 0), null);
 
     final private long mNativePtr;
 
-    private Hyphenator(long nativePtr) {
+    // We retain a reference to the buffer to keep the memory mapping valid
+    @SuppressWarnings("unused")
+    final private ByteBuffer mBuffer;
+
+    private Hyphenator(long nativePtr, ByteBuffer b) {
         mNativePtr = nativePtr;
+        mBuffer = b;
     }
 
     public long getNativePtr() {
@@ -94,12 +102,18 @@
     }
 
     private static Hyphenator loadHyphenator(String languageTag) {
-        String patternFilename = "hyph-"+languageTag.toLowerCase(Locale.US)+".pat.txt";
+        String patternFilename = "hyph-" + languageTag.toLowerCase(Locale.US) + ".hyb";
         File patternFile = new File(getSystemHyphenatorLocation(), patternFilename);
         try {
-            String patternData = IoUtils.readFileAsString(patternFile.getAbsolutePath());
-            long nativePtr = StaticLayout.nLoadHyphenator(patternData);
-            return new Hyphenator(nativePtr);
+            RandomAccessFile f = new RandomAccessFile(patternFile, "r");
+            try {
+                FileChannel fc = f.getChannel();
+                MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
+                long nativePtr = StaticLayout.nLoadHyphenator(buf, 0);
+                return new Hyphenator(nativePtr, buf);
+            } finally {
+                f.close();
+            }
         } catch (IOException e) {
             Log.e(TAG, "error loading hyphenation " + patternFile, e);
             return null;
@@ -152,7 +166,7 @@
         sMap.put(null, null);
 
         // TODO: replace this with a discovery-based method that looks into /system/usr/hyphen-data
-        String[] availableLanguages = {"en-US", "eu", "hu", "hy", "nb", "nn", "sa", "und-Ethi"};
+        String[] availableLanguages = {"en-US", "eu", "hu", "hy", "nb", "nn", "und-Ethi"};
         for (int i = 0; i < availableLanguages.length; i++) {
             String languageTag = availableLanguages[i];
             Hyphenator h = loadHyphenator(languageTag);
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 79c4a55..6ece091 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -29,6 +29,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
+import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Locale;
 
@@ -1244,7 +1245,7 @@
     private static native void nFreeBuilder(long nativePtr);
     private static native void nFinishBuilder(long nativePtr);
 
-    /* package */ static native long nLoadHyphenator(String patternData);
+    /* package */ static native long nLoadHyphenator(ByteBuffer buf, int offset);
 
     private static native void nSetLocale(long nativePtr, String locale, long nativeHyphenator);
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 263ec7d1..2c7a436 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6649,12 +6649,24 @@
     }
 
     /**
-     * Sets a delegate for implementing accessibility support via composition as
-     * opposed to inheritance. The delegate's primary use is for implementing
-     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
+     * Sets a delegate for implementing accessibility support via composition
+     * (as opposed to inheritance). For more details, see
+     * {@link AccessibilityDelegate}.
+     * <p>
+     * <strong>Note:</strong> On platform versions prior to
+     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
+     * views in the {@code android.widget.*} package are called <i>before</i>
+     * host methods. This prevents certain properties such as class name from
+     * being modified by overriding
+     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
+     * as any changes will be overwritten by the host class.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
+     * methods are called <i>after</i> host methods, which all properties to be
+     * modified without being overwritten by the host class.
      *
-     * @param delegate The delegate instance.
-     *
+     * @param delegate the object to which accessibility method calls should be
+     *                 delegated
      * @see AccessibilityDelegate
      */
     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
@@ -22277,6 +22289,18 @@
      * corresponding delegate method without altering the behavior of the rest
      * accessibility related methods of the host view.
      * </p>
+     * <p>
+     * <strong>Note:</strong> On platform versions prior to
+     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
+     * views in the {@code android.widget.*} package are called <i>before</i>
+     * host methods. This prevents certain properties such as class name from
+     * being modified by overriding
+     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
+     * as any changes will be overwritten by the host class.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
+     * methods are called <i>after</i> host methods, which all properties to be
+     * modified without being overwritten by the host class.
      */
     public static class AccessibilityDelegate {
 
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 68855ff..10aefe4 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -666,7 +666,7 @@
         progress += scale * max;
 
         setHotspot(x, (int) event.getY());
-        setProgress((int) progress, true);
+        setProgressInternal((int) progress, true, false);
     }
 
     /**
@@ -706,9 +706,12 @@
             int increment = mKeyProgressIncrement;
             switch (keyCode) {
                 case KeyEvent.KEYCODE_DPAD_LEFT:
+                case KeyEvent.KEYCODE_MINUS:
                     increment = -increment;
                     // fallthrough
                 case KeyEvent.KEYCODE_DPAD_RIGHT:
+                case KeyEvent.KEYCODE_PLUS:
+                case KeyEvent.KEYCODE_EQUALS:
                     increment = isLayoutRtl() ? -increment : increment;
 
                     if (setProgressInternal(getProgress() + increment, true, true)) {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 2172b5c..f0e216f 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -40,6 +40,7 @@
 import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.DocumentsContract;
 import android.service.chooser.ChooserTarget;
 import android.service.chooser.ChooserTargetService;
 import android.service.chooser.IChooserTargetResult;
@@ -269,7 +270,20 @@
     }
 
     @Override
-    boolean shouldAutoLaunchSingleChoice() {
+    boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
+        final Intent intent = target.getResolvedIntent();
+        final ResolveInfo resolve = target.getResolveInfo();
+
+        // When GET_CONTENT is handled by the DocumentsUI system component,
+        // we're okay automatically launching it, since it offers it's own
+        // intent disambiguation UI.
+        if (intent != null && Intent.ACTION_GET_CONTENT.equals(intent.getAction())
+                && resolve != null && resolve.priority > 0
+                && resolve.activityInfo != null && DocumentsContract.PACKAGE_DOCUMENTS_UI
+                        .equals(resolve.activityInfo.packageName)) {
+            return true;
+        }
+
         return false;
     }
 
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ef9d1ce..1710489 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -796,7 +796,7 @@
         return false;
     }
 
-    boolean shouldAutoLaunchSingleChoice() {
+    boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
         return true;
     }
 
@@ -837,18 +837,21 @@
         mAlwaysUseOption = alwaysUseOption;
 
         int count = mAdapter.getUnfilteredCount();
-        if ((!shouldAutoLaunchSingleChoice() && count > 0)
-                || count > 1
-                || (count == 1 && mAdapter.getOtherProfile() != null)) {
+        if (count == 1 && mAdapter.getOtherProfile() == null) {
+            // Only one target, so we're a candidate to auto-launch!
+            final TargetInfo target = mAdapter.targetInfoForPosition(0, false);
+            if (shouldAutoLaunchSingleChoice(target)) {
+                safelyStartActivity(target);
+                mPackageMonitor.unregister();
+                mRegistered = false;
+                finish();
+                return true;
+            }
+        }
+        if (count > 0) {
             setContentView(layoutId);
             mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
             onPrepareAdapterView(mAdapterView, mAdapter, alwaysUseOption);
-        } else if (count == 1) {
-            safelyStartActivity(mAdapter.targetInfoForPosition(0, false));
-            mPackageMonitor.unregister();
-            mRegistered = false;
-            finish();
-            return true;
         } else {
             setContentView(R.layout.resolver_list);
 
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
index 6ab306c..56cf921 100644
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -57,7 +57,8 @@
  * </ul>
  * This will be mitigated once b/22527834 will be addressed.
  */
-public class NonClientDecorView extends LinearLayout implements View.OnClickListener {
+public class NonClientDecorView extends LinearLayout
+        implements View.OnClickListener, View.OnTouchListener {
     private final static String TAG = "NonClientDecorView";
     // The height of a window which has focus in DIP.
     private final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20;
@@ -112,7 +113,7 @@
     }
 
     @Override
-    public boolean onTouchEvent(MotionEvent e) {
+    public boolean onTouch(View v, MotionEvent e) {
         // Note: There are no mixed events. When a new device gets used (e.g. 1. Mouse, 2. touch)
         // the old input device events get cancelled first. So no need to remember the kind of
         // input device we are listening to.
@@ -224,6 +225,7 @@
         boolean invisible = isFillingScreen() || !mShowDecor;
         View caption = getChildAt(0);
         caption.setVisibility(invisible ? GONE : VISIBLE);
+        caption.setOnTouchListener(this);
         mVisible = !invisible;
     }
 
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index a151e00..83f76ea 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -117,9 +117,17 @@
     b->finish();
 }
 
-static jlong nLoadHyphenator(JNIEnv* env, jclass, jstring patternData) {
-    ScopedStringChars str(env, patternData);
-    Hyphenator* hyphenator = Hyphenator::load(str.get(), str.size());
+static jlong nLoadHyphenator(JNIEnv* env, jclass, jobject buffer, jint offset) {
+    const uint8_t* bytebuf = nullptr;
+    if (buffer != nullptr) {
+        void* rawbuf = env->GetDirectBufferAddress(buffer);
+        if (rawbuf != nullptr) {
+            bytebuf = reinterpret_cast<const uint8_t*>(rawbuf) + offset;
+        } else {
+            ALOGE("failed to get direct buffer address");
+        }
+    }
+    Hyphenator* hyphenator = Hyphenator::loadBinary(bytebuf);
     return reinterpret_cast<jlong>(hyphenator);
 }
 
@@ -177,7 +185,7 @@
     {"nNewBuilder", "()J", (void*) nNewBuilder},
     {"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
     {"nFinishBuilder", "(J)V", (void*) nFinishBuilder},
-    {"nLoadHyphenator", "(Ljava/lang/String;)J", (void*) nLoadHyphenator},
+    {"nLoadHyphenator", "(Ljava/nio/ByteBuffer;I)J", (void*) nLoadHyphenator},
     {"nSetLocale", "(JLjava/lang/String;J)V", (void*) nSetLocale},
     {"nSetupParagraph", "(J[CIFIF[IIII)V", (void*) nSetupParagraph},
     {"nSetIndents", "(J[I)V", (void*) nSetIndents},
diff --git a/core/res/res/color/btn_colored_text_material.xml b/core/res/res/color/btn_colored_text_material.xml
index 23d05a9..c80fea6 100644
--- a/core/res/res/color/btn_colored_text_material.xml
+++ b/core/res/res/color/btn_colored_text_material.xml
@@ -18,6 +18,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
           android:alpha="?attr/disabledAlpha"
-          android:color="?attr/textColorSecondary" />
-    <item android:color="?attr/textColorSecondaryInverse" />
+          android:color="?attr/textColorPrimary" />
+    <item android:color="?attr/textColorPrimaryInverse" />
 </selector>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index a08f040..2f1627b 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -227,23 +227,23 @@
     <string name="user_owner_label" msgid="2804351898001038951">"Persoonlik"</string>
     <string name="managed_profile_label" msgid="6260850669674791528">"Werk"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakte"</string>
-    <string name="permgroupdesc_contacts" msgid="6951499528303668046">"gaan by jou kontakte in"</string>
+    <string name="permgroupdesc_contacts" msgid="6951499528303668046">"in te gaan by jou kontakte"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Ligging"</string>
-    <string name="permgroupdesc_location" msgid="1346617465127855033">"verkry toegang tot hierdie toestel se ligging"</string>
+    <string name="permgroupdesc_location" msgid="1346617465127855033">"toegang te verkry tot hierdie toestel se ligging"</string>
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalender"</string>
-    <string name="permgroupdesc_calendar" msgid="3889615280211184106">"gaan by jou kalender in"</string>
+    <string name="permgroupdesc_calendar" msgid="3889615280211184106">"by jou kalender in te gaan"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
-    <string name="permgroupdesc_sms" msgid="4656988620100940350">"stuur en bekyk SMS-boodskappe"</string>
+    <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS-boodskappe te stuur en te bekyk"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Stoor"</string>
-    <string name="permgroupdesc_storage" msgid="637758554581589203">"verkry toegang tot foto\'s, media en lêers op jou toestel"</string>
+    <string name="permgroupdesc_storage" msgid="637758554581589203">"toegang te verkry tot foto\'s, media en lêers op jou toestel"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofoon"</string>
-    <string name="permgroupdesc_microphone" msgid="4988812113943554584">"neem oudio op"</string>
+    <string name="permgroupdesc_microphone" msgid="4988812113943554584">"oudio op te neem"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
-    <string name="permgroupdesc_camera" msgid="3250611594678347720">"neem foto\'s en neem video op"</string>
+    <string name="permgroupdesc_camera" msgid="3250611594678347720">"foto\'s en video te neem"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"Foon"</string>
-    <string name="permgroupdesc_phone" msgid="6234224354060641055">"maak en bestuur foonoproepe"</string>
+    <string name="permgroupdesc_phone" msgid="6234224354060641055">"foonoproepe te maak en te bestuur"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Liggaamsensors"</string>
-    <string name="permgroupdesc_sensors" msgid="7147968539346634043">"kry toegang tot sensordata oor jou lewenstekens"</string>
+    <string name="permgroupdesc_sensors" msgid="7147968539346634043">"toegang te verkry tot sensordata oor jou lewenstekens"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Haal venster-inhoud op"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Ondersoek die inhoud van \'n venster waarmee jy interaksie het."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Skakel Verken deur raak aan"</string>
@@ -272,7 +272,7 @@
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Laat die program toe om seluitsending-boodskappe te lees wat deur jou toestel ontvang word. Seluitsending-waarskuwings word in sommige plekke afgelewer om jou van noodsituasies te waarsku. Kwaadwillige programme mag inmeng met die prestasie of die werking van jou toestel wanneer \'n noodgeval se seluitsending ontvang word."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lees ingetekende nuus"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Laat die program toe om details oor die tans gesinkroniseerde strome te kry."</string>
-    <string name="permlab_sendSms" msgid="7544599214260982981">"stuur en bekyk SMS-boodskappe"</string>
+    <string name="permlab_sendSms" msgid="7544599214260982981">"SMS-boodskappe te stuur en te bekyk"</string>
     <string name="permdesc_sendSms" msgid="7094729298204937667">"Laat die program toe om SMS-boodskappe te stuur. Dit kan tot onverwagse heffings lei. Kwaadwillige programme kan jou geld kos deur boodskappe sonder jou bevestiging te stuur."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"lees jou teksboodskappe (SMS of MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Laat die program toe om SMS-boodskappe wat op jou tablet of SIM-kaart gestoor is, te lees. Dit laat die program toe om alle SMS-boodskappe te lees, ongeag van die inhoud of vertroulikheid daarvan."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index af80ed3..0621bbe 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -915,7 +915,7 @@
     <string name="anr_application_process" msgid="8941757607340481057">"Приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" не отвечает. Закрыть его?"</string>
     <string name="anr_process" msgid="6513209874880517125">"Приложение \"<xliff:g id="PROCESS">%1$s</xliff:g>\" не отвечает.\n\nЗакрыть его?"</string>
     <string name="force_close" msgid="8346072094521265605">"ОК"</string>
-    <string name="report" msgid="4060218260984795706">"Создать отчет"</string>
+    <string name="report" msgid="4060218260984795706">"Отправить отчет"</string>
     <string name="wait" msgid="7147118217226317732">"Подождать"</string>
     <string name="webpage_unresponsive" msgid="3272758351138122503">"Страница не отвечает.\n\nЗакрыть ее?"</string>
     <string name="launch_warning_title" msgid="1547997780506713581">"Приложение перенаправлено"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 488470f..29fd6a1 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1235,7 +1235,7 @@
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Bara en gång"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s har inte stöd för arbetsprofil"</string>
     <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Surfplatta"</string>
-    <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Tv"</string>
+    <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string>
     <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Mobil"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hörlurar"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockningsstationens högtalare"</string>
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index a81ffb9..e0bf26d 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -533,7 +533,11 @@
 
         if (deferInfo.mergeable) {
             // Try to merge with any existing batch with same mergeId.
-            if (mMergingBatches[deferInfo.batchId].get(deferInfo.mergeId, targetBatch)) {
+            std::unordered_map<mergeid_t, DrawBatch*>& mergingBatch
+                    = mMergingBatches[deferInfo.batchId];
+            auto getResult = mergingBatch.find(deferInfo.mergeId);
+            if (getResult != mergingBatch.end()) {
+                targetBatch = getResult->second;
                 if (!((MergingDrawBatch*) targetBatch)->canMergeWith(op, state)) {
                     targetBatch = nullptr;
                 }
@@ -577,7 +581,8 @@
         if (deferInfo.mergeable) {
             targetBatch = new MergingDrawBatch(deferInfo,
                     renderer.getViewportWidth(), renderer.getViewportHeight());
-            mMergingBatches[deferInfo.batchId].put(deferInfo.mergeId, targetBatch);
+            mMergingBatches[deferInfo.batchId].insert(
+                    std::make_pair(deferInfo.mergeId, targetBatch));
         } else {
             targetBatch = new DrawBatch(deferInfo);
             mBatchLookup[deferInfo.batchId] = targetBatch;
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 4f2dca5..748bff6 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -17,9 +17,10 @@
 #ifndef ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
 #define ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
 
+#include <unordered_map>
+
 #include <utils/Errors.h>
 #include <utils/LinearAllocator.h>
-#include <utils/TinyHashMap.h>
 
 #include "Matrix.h"
 #include "OpenGLRenderer.h"
@@ -177,7 +178,7 @@
      * MergingDrawBatch of that id. These ids are unique per draw type and guaranteed to not
      * collide, which avoids the need to resolve mergeid collisions.
      */
-    TinyHashMap<mergeid_t, DrawBatch*> mMergingBatches[kOpBatch_Count];
+    std::unordered_map<mergeid_t, DrawBatch*> mMergingBatches[kOpBatch_Count];
 
     LinearAllocator mAllocator;
 };
diff --git a/libs/hwui/utils/TinyHashMap.h b/libs/hwui/utils/TinyHashMap.h
deleted file mode 100644
index 4ff9a42..0000000
--- a/libs/hwui/utils/TinyHashMap.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef ANDROID_HWUI_TINYHASHMAP_H
-#define ANDROID_HWUI_TINYHASHMAP_H
-
-#include <utils/BasicHashtable.h>
-
-namespace android {
-namespace uirenderer {
-
-/**
- * A very simple hash map that doesn't allow duplicate keys, overwriting the older entry.
- */
-template <typename TKey, typename TValue>
-class TinyHashMap {
-public:
-    typedef key_value_pair_t<TKey, TValue> TEntry;
-
-    /**
-     * Puts an entry in the hash, removing any existing entry with the same key
-     */
-    void put(TKey key, TValue value) {
-        hash_t hash = android::hash_type(key);
-
-        ssize_t index = mTable.find(-1, hash, key);
-        if (index != -1) {
-            mTable.removeAt(index);
-        }
-
-        TEntry initEntry(key, value);
-        mTable.add(hash, initEntry);
-    }
-
-    /**
-     * Return true if key is in the map, in which case stores the value in the output ref
-     */
-    bool get(TKey key, TValue& outValue) {
-        hash_t hash = android::hash_type(key);
-        ssize_t index = mTable.find(-1, hash, key);
-        if (index == -1) {
-            return false;
-        }
-        outValue = mTable.entryAt(index).value;
-        return true;
-    }
-
-    void clear() { mTable.clear(); }
-
-private:
-    BasicHashtable<TKey, TEntry> mTable;
-};
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_TINYHASHMAP_H
diff --git a/media/java/android/media/SRTRenderer.java b/media/java/android/media/SRTRenderer.java
index ee4edee..a3e2abd 100644
--- a/media/java/android/media/SRTRenderer.java
+++ b/media/java/android/media/SRTRenderer.java
@@ -165,7 +165,6 @@
             return;
         }
 
-        final int _ = 0;
         for (Cue cue : activeCues) {
             TextTrackCue ttc = (TextTrackCue) cue;
 
@@ -184,7 +183,8 @@
             parcel.writeInt(buf.length);
             parcel.writeByteArray(buf);
 
-            Message msg = mEventHandler.obtainMessage(MEDIA_TIMED_TEXT, _, _, parcel);
+            Message msg = mEventHandler.obtainMessage(MEDIA_TIMED_TEXT, 0 /* arg1 */, 0 /* arg2 */,
+                    parcel);
             mEventHandler.sendMessage(msg);
         }
         activeCues.clear();
diff --git a/packages/DocumentsUI/res/layout/drawer_layout.xml b/packages/DocumentsUI/res/layout/drawer_layout.xml
index dec4e92..0dac0d5 100644
--- a/packages/DocumentsUI/res/layout/drawer_layout.xml
+++ b/packages/DocumentsUI/res/layout/drawer_layout.xml
@@ -14,62 +14,71 @@
      limitations under the License.
 -->
 
-<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/drawer_layout"
+<!-- CoordinatorLayout is necessary for various components (e.g. Snackbars, and
+     floating action buttons) to operate correctly. -->
+<android.support.design.widget.CoordinatorLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:id="@+id/coordinator_layout">
 
-    <LinearLayout
+    <android.support.v4.widget.DrawerLayout
+        android:id="@+id/drawer_layout"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical">
+        android:layout_height="match_parent">
 
-        <com.android.documentsui.DocumentsToolBar
-            android:id="@+id/toolbar"
+        <LinearLayout
             android:layout_width="match_parent"
-            android:layout_height="?android:attr/actionBarSize"
-            android:background="?android:attr/colorPrimary"
-            android:elevation="8dp"
-            android:theme="?actionBarTheme"
-            android:popupTheme="?actionBarPopupTheme">
+            android:layout_height="match_parent"
+            android:orientation="vertical">
 
-            <Spinner
-                android:id="@+id/stack"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginStart="4dp"
-                android:overlapAnchor="true" />
+            <com.android.documentsui.DocumentsToolBar
+                android:id="@+id/toolbar"
+                android:layout_width="match_parent"
+                android:layout_height="?android:attr/actionBarSize"
+                android:background="?android:attr/colorPrimary"
+                android:elevation="8dp"
+                android:theme="?actionBarTheme"
+                android:popupTheme="?actionBarPopupTheme">
 
-        </com.android.documentsui.DocumentsToolBar>
+                <Spinner
+                    android:id="@+id/stack"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginStart="4dp"
+                    android:overlapAnchor="true" />
 
-        <include layout="@layout/directory_cluster"/>
+            </com.android.documentsui.DocumentsToolBar>
 
-    </LinearLayout>
+            <include layout="@layout/directory_cluster"/>
 
-    <LinearLayout
-        android:id="@+id/drawer_roots"
-        android:layout_width="256dp"
-        android:layout_height="match_parent"
-        android:layout_gravity="start"
-        android:orientation="vertical"
-        android:elevation="16dp"
-        android:background="@*android:color/white">
+        </LinearLayout>
 
-        <Toolbar
-            android:id="@+id/roots_toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="?android:attr/actionBarSize"
-            android:background="?android:attr/colorPrimary"
-            android:elevation="8dp"
-            android:theme="?actionBarTheme"
-            android:popupTheme="?actionBarPopupTheme" />
+        <LinearLayout
+            android:id="@+id/drawer_roots"
+            android:layout_width="256dp"
+            android:layout_height="match_parent"
+            android:layout_gravity="start"
+            android:orientation="vertical"
+            android:elevation="16dp"
+            android:background="@*android:color/white">
 
-        <FrameLayout
-            android:id="@+id/container_roots"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_weight="1" />
+            <Toolbar
+                android:id="@+id/roots_toolbar"
+                android:layout_width="match_parent"
+                android:layout_height="?android:attr/actionBarSize"
+                android:background="?android:attr/colorPrimary"
+                android:elevation="8dp"
+                android:theme="?actionBarTheme"
+                android:popupTheme="?actionBarPopupTheme" />
 
-    </LinearLayout>
+            <FrameLayout
+                android:id="@+id/container_roots"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_weight="1" />
 
-</android.support.v4.widget.DrawerLayout>
+        </LinearLayout>
+
+    </android.support.v4.widget.DrawerLayout>
+</android.support.design.widget.CoordinatorLayout>
diff --git a/packages/DocumentsUI/res/layout/fixed_layout.xml b/packages/DocumentsUI/res/layout/fixed_layout.xml
index eba9af4..403c667 100644
--- a/packages/DocumentsUI/res/layout/fixed_layout.xml
+++ b/packages/DocumentsUI/res/layout/fixed_layout.xml
@@ -14,49 +14,59 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<!-- CoordinatorLayout is necessary for various components (e.g. Snackbars, and
+     floating action buttons) to operate correctly. -->
+<android.support.design.widget.CoordinatorLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical">
+    android:id="@+id/coordinator_layout">
 
-    <com.android.documentsui.DocumentsToolBar
-        android:id="@+id/toolbar"
+    <LinearLayout 
         android:layout_width="match_parent"
-        android:layout_height="?android:attr/actionBarSize"
-        android:background="?android:attr/colorPrimary"
-        android:elevation="8dp"
-        android:theme="?actionBarTheme"
-        android:popupTheme="?actionBarPopupTheme">
+        android:layout_height="match_parent"
+        android:orientation="vertical">
 
-        <Spinner
-            android:id="@+id/stack"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="4dp"
-            android:overlapAnchor="true" />
-
-    </com.android.documentsui.DocumentsToolBar>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1"
-        android:orientation="horizontal"
-        android:baselineAligned="false"
-        android:divider="?android:attr/dividerVertical"
-        android:showDividers="middle">
-
-        <FrameLayout
-            android:id="@+id/container_roots"
-            android:layout_width="256dp"
-            android:layout_height="match_parent" />
-
-        <include layout="@layout/directory_cluster"
-            android:layout_width="0dp"
-            android:layout_weight="1"
+        <com.android.documentsui.DocumentsToolBar
+            android:id="@+id/toolbar"
+            android:layout_width="match_parent"
+            android:layout_height="?android:attr/actionBarSize"
+            android:background="?android:attr/colorPrimary"
             android:elevation="8dp"
-            android:background="@color/material_grey_50" />
+            android:theme="?actionBarTheme"
+            android:popupTheme="?actionBarPopupTheme">
+
+            <Spinner
+                android:id="@+id/stack"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="4dp"
+                android:overlapAnchor="true" />
+
+        </com.android.documentsui.DocumentsToolBar>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:orientation="horizontal"
+            android:baselineAligned="false"
+            android:divider="?android:attr/dividerVertical"
+            android:showDividers="middle">
+
+            <FrameLayout
+                android:id="@+id/container_roots"
+                android:layout_width="256dp"
+                android:layout_height="match_parent" />
+
+            <include layout="@layout/directory_cluster"
+                android:layout_width="0dp"
+                android:layout_weight="1"
+                android:elevation="8dp"
+                android:background="@color/material_grey_50" />
+
+        </LinearLayout>
 
     </LinearLayout>
 
-</LinearLayout>
+</android.support.design.widget.CoordinatorLayout>
diff --git a/packages/DocumentsUI/res/layout/single_pane_layout.xml b/packages/DocumentsUI/res/layout/single_pane_layout.xml
index 20c3232..c5a5745 100644
--- a/packages/DocumentsUI/res/layout/single_pane_layout.xml
+++ b/packages/DocumentsUI/res/layout/single_pane_layout.xml
@@ -14,29 +14,39 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<!-- CoordinatorLayout is necessary for various components (e.g. Snackbars, and
+     floating action buttons) to operate correctly. -->
+<android.support.design.widget.CoordinatorLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical">
+    android:id="@+id/coordinator_layout">
 
-    <com.android.documentsui.DocumentsToolBar
-        android:id="@+id/toolbar"
+    <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="?android:attr/actionBarSize"
-        android:background="?android:attr/colorPrimary"
-        android:elevation="8dp"
-        android:theme="?actionBarTheme"
-        android:popupTheme="?actionBarPopupTheme">
+        android:layout_height="match_parent"
+        android:orientation="vertical">
 
-        <Spinner
-            android:id="@+id/stack"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="4dp"
-            android:overlapAnchor="true" />
+        <com.android.documentsui.DocumentsToolBar
+            android:id="@+id/toolbar"
+            android:layout_width="match_parent"
+            android:layout_height="?android:attr/actionBarSize"
+            android:background="?android:attr/colorPrimary"
+            android:elevation="8dp"
+            android:theme="?actionBarTheme"
+            android:popupTheme="?actionBarPopupTheme">
 
-    </com.android.documentsui.DocumentsToolBar>
+            <Spinner
+                android:id="@+id/stack"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="4dp"
+                android:overlapAnchor="true" />
 
-    <include layout="@layout/directory_cluster"/>
+        </com.android.documentsui.DocumentsToolBar>
 
-</LinearLayout>
+        <include layout="@layout/directory_cluster"/>
+
+    </LinearLayout>
+
+</android.support.design.widget.CoordinatorLayout>
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index ed7820b..ce5b174 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <bool name="productivity_device">true</bool>
+    <bool name="productivity_device">false</bool>
 </resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index a6a45e5..ab0f666 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -20,6 +20,7 @@
 import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
 import static com.android.documentsui.DirectoryFragment.ANIM_SIDE;
 import static com.android.documentsui.DirectoryFragment.ANIM_UP;
+import static com.android.documentsui.Shared.DEBUG;
 import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.app.Activity;
@@ -150,12 +151,10 @@
         fileSize.setTitle(LocalPreferences.getDisplayFileSize(this)
                 ? R.string.menu_file_size_hide : R.string.menu_file_size_show);
 
-        State state = getDisplayState();
-
-        sortSize.setVisible(state.showSize); // Only sort by size when visible
-        fileSize.setVisible(!state.showSize);
-        grid.setVisible(state.derivedMode != State.MODE_GRID);
-        list.setVisible(state.derivedMode != State.MODE_LIST);
+        sortSize.setVisible(mState.showSize); // Only sort by size when visible
+        fileSize.setVisible(!mState.showSize);
+        grid.setVisible(mState.derivedMode != State.MODE_GRID);
+        list.setVisible(mState.derivedMode != State.MODE_LIST);
         advanced.setVisible(!mState.showAdvanced);
         settings.setVisible((root.flags & Root.FLAG_HAS_SETTINGS) != 0);
 
@@ -185,12 +184,10 @@
     void onStackRestored(boolean restored, boolean external) {}
 
     void onRootPicked(RootInfo root) {
-        State state = getDisplayState();
-
         // Clear entire backstack and start in new root
-        state.stack.root = root;
-        state.stack.clear();
-        state.stackTouched = true;
+        mState.stack.root = root;
+        mState.stack.clear();
+        mState.stackTouched = true;
 
         mSearchManager.update(root);
 
@@ -289,8 +286,8 @@
     }
 
     void openDirectory(DocumentInfo doc) {
-        getDisplayState().stack.push(doc);
-        getDisplayState().stackTouched = true;
+        mState.stack.push(doc);
+        mState.stackTouched = true;
         onCurrentDirectoryChanged(ANIM_DOWN);
     }
 
@@ -367,16 +364,15 @@
     }
 
     void setDisplayAdvancedDevices(boolean display) {
-        State state = getDisplayState();
         LocalPreferences.setDisplayAdvancedDevices(this, display);
-        state.showAdvanced = state.forceAdvanced | display;
+        mState.showAdvanced = mState.forceAdvanced | display;
         RootsFragment.get(getFragmentManager()).onDisplayStateChanged();
         invalidateOptionsMenu();
     }
 
     void setDisplayFileSize(boolean display) {
         LocalPreferences.setDisplayFileSize(this, display);
-        getDisplayState().showSize = display;
+        mState.showSize = display;
         DirectoryFragment.get(getFragmentManager()).onDisplayStateChanged();
         invalidateOptionsMenu();
     }
@@ -389,7 +385,7 @@
      * Set state sort order based on explicit user action.
      */
     void setUserSortOrder(int sortOrder) {
-        getDisplayState().userSortOrder = sortOrder;
+        mState.userSortOrder = sortOrder;
         DirectoryFragment.get(getFragmentManager()).onUserSortOrderChanged();
     }
 
@@ -397,7 +393,7 @@
      * Set state mode based on explicit user action.
      */
     void setUserMode(int mode) {
-        getDisplayState().userMode = mode;
+        mState.userMode = mode;
         DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
     }
 
@@ -411,7 +407,7 @@
     @Override
     protected void onSaveInstanceState(Bundle state) {
         super.onSaveInstanceState(state);
-        state.putParcelable(EXTRA_STATE, getDisplayState());
+        state.putParcelable(EXTRA_STATE, mState);
     }
 
     @Override
@@ -420,16 +416,15 @@
     }
 
     RootInfo getCurrentRoot() {
-        State state = getDisplayState();
-        if (state.stack.root != null) {
-            return state.stack.root;
+        if (mState.stack.root != null) {
+            return mState.stack.root;
         } else {
             return mRoots.getRecentsRoot();
         }
     }
 
     public DocumentInfo getCurrentDirectory() {
-        return getDisplayState().stack.peek();
+        return mState.stack.peek();
     }
 
     public Executor getExecutorForCurrentDirectory() {
@@ -470,9 +465,8 @@
             // Update the restored stack to ensure we have freshest data
             stack.updateDocuments(getContentResolver());
 
-            State state = getDisplayState();
-            state.stack = stack;
-            state.stackTouched = true;
+            mState.stack = stack;
+            mState.stackTouched = true;
             onCurrentDirectoryChanged(ANIM_SIDE);
 
         } catch (FileNotFoundException e) {
@@ -502,9 +496,8 @@
         @Override
         protected void onPostExecute(DocumentInfo result) {
             if (result != null) {
-                State state = getDisplayState();
-                state.stack.push(result);
-                state.stackTouched = true;
+                mState.stack.push(result);
+                mState.stackTouched = true;
                 onCurrentDirectoryChanged(ANIM_SIDE);
             }
         }
@@ -516,7 +509,9 @@
 
         @Override
         protected Void doInBackground(Void... params) {
-            State state = getDisplayState();
+            if (DEBUG && !mState.stack.isEmpty()) {
+                Log.w(mTag, "Overwriting existing stack.");
+            }
             RootsCache roots = DocumentsApplication.getRootsCache(BaseActivity.this);
 
             // Restore last stack for calling package
@@ -528,7 +523,7 @@
                     mExternal = cursor.getInt(cursor.getColumnIndex(ResumeColumns.EXTERNAL)) != 0;
                     final byte[] rawStack = cursor.getBlob(
                             cursor.getColumnIndex(ResumeColumns.STACK));
-                    DurableUtils.readFromArray(rawStack, state.stack);
+                    DurableUtils.readFromArray(rawStack, mState.stack);
                     mRestoredStack = true;
                 }
             } catch (IOException e) {
@@ -539,13 +534,13 @@
 
             if (mRestoredStack) {
                 // Update the restored stack to ensure we have freshest data
-                final Collection<RootInfo> matchingRoots = roots.getMatchingRootsBlocking(state);
+                final Collection<RootInfo> matchingRoots = roots.getMatchingRootsBlocking(mState);
                 try {
-                    state.stack.updateRoot(matchingRoots);
-                    state.stack.updateDocuments(getContentResolver());
+                    mState.stack.updateRoot(matchingRoots);
+                    mState.stack.updateDocuments(getContentResolver());
                 } catch (FileNotFoundException e) {
                     Log.w(mTag, "Failed to restore stack: " + e);
-                    state.stack.reset();
+                    mState.stack.reset();
                     mRestoredStack = false;
                 }
             }
@@ -556,7 +551,7 @@
         @Override
         protected void onPostExecute(Void result) {
             if (isDestroyed()) return;
-            getDisplayState().restored = true;
+            mState.restored = true;
             onCurrentDirectoryChanged(ANIM_NONE);
             onStackRestored(mRestoredStack, mExternal);
         }
@@ -600,10 +595,9 @@
                 return;
             }
 
-            State state = getDisplayState();
-            while (state.stack.size() > position + 1) {
-                state.stackTouched = true;
-                state.stack.pop();
+            while (mState.stack.size() > position + 1) {
+                mState.stackTouched = true;
+                mState.stack.pop();
             }
             onCurrentDirectoryChanged(ANIM_UP);
         }
@@ -620,13 +614,12 @@
     final class StackAdapter extends BaseAdapter {
         @Override
         public int getCount() {
-            return getDisplayState().stack.size();
+            return mState.stack.size();
         }
 
         @Override
         public DocumentInfo getItem(int position) {
-            State state = getDisplayState();
-            return state.stack.get(state.stack.size() - position - 1);
+            return mState.stack.get(mState.stack.size() - position - 1);
         }
 
         @Override
@@ -714,13 +707,12 @@
                 return;
             }
 
-            State state = getDisplayState();
-            if (state.currentSearch != null) {
+            if (mState.currentSearch != null) {
                 mMenu.expandActionView();
 
                 mView.setIconified(false);
                 mView.clearFocus();
-                mView.setQuery(state.currentSearch, false);
+                mView.setQuery(mState.currentSearch, false);
             } else {
                 mView.clearFocus();
                 if (!mView.isIconified()) {
@@ -746,7 +738,7 @@
 
             mMenu.setVisible(visible);
             if (!visible) {
-                getDisplayState().currentSearch = null;
+                mState.currentSearch = null;
             }
         }
 
@@ -764,7 +756,7 @@
         }
 
         boolean isSearching() {
-            return getDisplayState().currentSearch != null;
+            return mState.currentSearch != null;
         }
 
         boolean isExpanded() {
@@ -779,7 +771,7 @@
                 return false;
             }
 
-            getDisplayState().currentSearch = null;
+            mState.currentSearch = null;
             onCurrentDirectoryChanged(ANIM_NONE);
             return false;
         }
@@ -798,7 +790,7 @@
                 mIgnoreNextCollapse = false;
                 return true;
             }
-            getDisplayState().currentSearch = null;
+            mState.currentSearch = null;
             onCurrentDirectoryChanged(ANIM_NONE);
             return true;
         }
@@ -806,7 +798,7 @@
         @Override
         public boolean onQueryTextSubmit(String query) {
             mSearchExpanded = true;
-            getDisplayState().currentSearch = query;
+            mState.currentSearch = query;
             mView.clearFocus();
             onCurrentDirectoryChanged(ANIM_NONE);
             return true;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
index f1492dc7..362052c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
@@ -20,6 +20,7 @@
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
 
+import android.app.Activity;
 import android.app.IntentService;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -37,6 +38,7 @@
 import android.os.SystemClock;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
+import android.support.design.widget.Snackbar;
 import android.text.format.DateUtils;
 import android.util.Log;
 import android.widget.Toast;
@@ -60,7 +62,6 @@
 
     private static final String EXTRA_CANCEL = "com.android.documentsui.CANCEL";
     public static final String EXTRA_SRC_LIST = "com.android.documentsui.SRC_LIST";
-    public static final String EXTRA_STACK = "com.android.documentsui.STACK";
     public static final String EXTRA_FAILURE = "com.android.documentsui.FAILURE";
     public static final String EXTRA_TRANSFER_MODE = "com.android.documentsui.TRANSFER_MODE";
 
@@ -107,21 +108,21 @@
      * @param srcDocs A list of src files to copy.
      * @param dstStack The copy destination stack.
      */
-    public static void start(Context context, List<DocumentInfo> srcDocs, DocumentStack dstStack,
+    public static void start(Activity activity, List<DocumentInfo> srcDocs, DocumentStack dstStack,
             int mode) {
-        final Resources res = context.getResources();
-        final Intent copyIntent = new Intent(context, CopyService.class);
+        final Resources res = activity.getResources();
+        final Intent copyIntent = new Intent(activity, CopyService.class);
         copyIntent.putParcelableArrayListExtra(
                 EXTRA_SRC_LIST, new ArrayList<DocumentInfo>(srcDocs));
-        copyIntent.putExtra(EXTRA_STACK, (Parcelable) dstStack);
+        copyIntent.putExtra(Shared.EXTRA_STACK, (Parcelable) dstStack);
         copyIntent.putExtra(EXTRA_TRANSFER_MODE, mode);
 
         int toastMessage = (mode == TRANSFER_MODE_COPY) ? R.plurals.copy_begin
                 : R.plurals.move_begin;
-        Toast.makeText(context,
+        Shared.makeSnackbar(activity,
                 res.getQuantityString(toastMessage, srcDocs.size(), srcDocs.size()),
-                Toast.LENGTH_SHORT).show();
-        context.startService(copyIntent);
+                Snackbar.LENGTH_SHORT).show();
+        activity.startService(copyIntent);
     }
 
     @Override
@@ -140,7 +141,7 @@
         }
 
         final ArrayList<DocumentInfo> srcs = intent.getParcelableArrayListExtra(EXTRA_SRC_LIST);
-        final DocumentStack stack = intent.getParcelableExtra(EXTRA_STACK);
+        final DocumentStack stack = intent.getParcelableExtra(Shared.EXTRA_STACK);
         // Copy by default.
         final int transferMode = intent.getIntExtra(EXTRA_TRANSFER_MODE, TRANSFER_MODE_COPY);
 
@@ -171,7 +172,7 @@
                 Log.e(TAG, mFailedFiles.size() + " files failed to copy");
                 final Context context = getApplicationContext();
                 final Intent navigateIntent = new Intent(context, FilesActivity.class);
-                navigateIntent.putExtra(EXTRA_STACK, (Parcelable) stack);
+                navigateIntent.putExtra(Shared.EXTRA_STACK, (Parcelable) stack);
                 navigateIntent.putExtra(EXTRA_FAILURE, FAILURE_COPY);
                 navigateIntent.putExtra(EXTRA_TRANSFER_MODE, transferMode);
                 navigateIntent.putParcelableArrayListExtra(EXTRA_SRC_LIST, mFailedFiles);
@@ -219,7 +220,7 @@
 
         final Context context = getApplicationContext();
         final Intent navigateIntent = new Intent(context, FilesActivity.class);
-        navigateIntent.putExtra(EXTRA_STACK, (Parcelable) stack);
+        navigateIntent.putExtra(Shared.EXTRA_STACK, (Parcelable) stack);
 
         final String contentTitle = getString(copying ? R.string.copy_notification_title
                 : R.string.move_notification_title);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index e408e6e..9f44516 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -32,6 +32,7 @@
 import android.os.Bundle;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
+import android.support.design.widget.Snackbar;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -39,7 +40,6 @@
 import android.widget.EditText;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
-import android.widget.Toast;
 
 import com.android.documentsui.model.DocumentInfo;
 
@@ -147,7 +147,7 @@
                 // Navigate into newly created child
                 mActivity.onDirectoryCreated(result);
             } else {
-                Toast.makeText(mActivity, R.string.create_error, Toast.LENGTH_SHORT).show();
+                Shared.makeSnackbar(mActivity, R.string.create_error, Snackbar.LENGTH_SHORT).show();
             }
 
             mActivity.setPending(false);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 5eacf21..b3ce103 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -91,7 +91,6 @@
 import android.view.ViewParent;
 import android.widget.ImageView;
 import android.widget.TextView;
-import android.widget.Toast;
 
 import com.android.documentsui.BaseActivity.DocumentContext;
 import com.android.documentsui.MultiSelectManager.Selection;
@@ -424,7 +423,7 @@
         }
 
         CopyService.start(getActivity(), getDisplayState(this).selectedDocumentsForCopy,
-                (DocumentStack) data.getParcelableExtra(CopyService.EXTRA_STACK),
+                (DocumentStack) data.getParcelableExtra(Shared.EXTRA_STACK),
                 data.getIntExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_NONE));
     }
 
@@ -805,8 +804,8 @@
 
         mModel.markForDeletion(selected);
 
-        Activity activity = getActivity();
-        Snackbar.make(this.getView(), message, Snackbar.LENGTH_LONG)
+        final Activity activity = getActivity();
+        Shared.makeSnackbar(activity, message, Snackbar.LENGTH_LONG)
                 .setAction(
                         R.string.undo,
                         new android.view.View.OnClickListener() {
@@ -821,11 +820,11 @@
                                     mModel.undoDeletion();
                                 } else {
                                     mModel.finalizeDeletion(
-                                            new Runnable() {
+                                            new Model.DeletionListener() {
                                                 @Override
-                                                public void run() {
-                                                    Snackbar.make(
-                                                            DirectoryFragment.this.getView(),
+                                                public void onError() {
+                                                    Shared.makeSnackbar(
+                                                            activity,
                                                             R.string.toast_failed_delete,
                                                             Snackbar.LENGTH_LONG)
                                                             .show();
@@ -1245,9 +1244,11 @@
 
     private void copyDocuments(final List<DocumentInfo> docs, final DocumentInfo destination) {
         if (!canCopy(docs, destination)) {
-            Toast.makeText(
+            Shared.makeSnackbar(
                     getActivity(),
-                    R.string.clipboard_files_cannot_paste, Toast.LENGTH_SHORT).show();
+                    R.string.clipboard_files_cannot_paste,
+                    Snackbar.LENGTH_SHORT)
+                    .show();
             return;
         }
 
@@ -1297,10 +1298,10 @@
             void onDocumentsReady(List<DocumentInfo> docs) {
                 mClipper.clipDocuments(docs);
                 Activity activity = getActivity();
-                Toast.makeText(activity,
+                Shared.makeSnackbar(activity,
                         activity.getResources().getQuantityString(
                                 R.plurals.clipboard_files_clipped, docs.size(), docs.size()),
-                                Toast.LENGTH_SHORT).show();
+                                Snackbar.LENGTH_SHORT).show();
             }
         }.execute(items);
     }
@@ -1864,9 +1865,9 @@
          * @param view The view which will be used to interact with the user (e.g. surfacing
          * snackbars) for errors, info, etc.
          */
-        void finalizeDeletion(Runnable errorCallback) {
+        void finalizeDeletion(DeletionListener listener) {
             final ContentResolver resolver = mContext.getContentResolver();
-            DeleteFilesTask task = new DeleteFilesTask(resolver, errorCallback);
+            DeleteFilesTask task = new DeleteFilesTask(resolver, listener);
             task.execute();
         }
 
@@ -1876,16 +1877,16 @@
          */
         private class DeleteFilesTask extends AsyncTask<Void, Void, List<DocumentInfo>> {
             private ContentResolver mResolver;
-            private Runnable mErrorCallback;
+            private DeletionListener mListener;
 
             /**
              * @param resolver A ContentResolver for performing the actual file deletions.
              * @param errorCallback A Runnable that is executed in the event that one or more errors
              *     occured while copying files.  Execution will occur on the UI thread.
              */
-            public DeleteFilesTask(ContentResolver resolver, Runnable errorCallback) {
+            public DeleteFilesTask(ContentResolver resolver, DeletionListener listener) {
                 mResolver = resolver;
-                mErrorCallback = errorCallback;
+                mListener = listener;
             }
 
             @Override
@@ -1919,15 +1920,29 @@
 
                 if (hadTrouble) {
                     // TODO show which files failed? b/23720103
-                    mErrorCallback.run();
+                    mListener.onError();
                     if (DEBUG) Log.d(TAG, "Deletion task completed.  Some deletions failed.");
                 } else {
                     if (DEBUG) Log.d(TAG, "Deletion task completed successfully.");
                 }
                 mMarkedForDeletion.clear();
+
+                mListener.onCompletion();
             }
         }
 
+        static class DeletionListener {
+            /**
+             * Called when deletion has completed (regardless of whether an error occurred).
+             */
+            void onCompletion() {}
+
+            /**
+             * Called at the end of a deletion operation that produced one or more errors.
+             */
+            void onError() {}
+        }
+
         void addUpdateListener(UpdateListener listener) {
             checkState(mUpdateListener == null);
             mUpdateListener = listener;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 4658fe3..ced03cc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -41,6 +41,7 @@
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.provider.DocumentsContract;
+import android.support.design.widget.Snackbar;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -48,7 +49,6 @@
 import android.view.WindowManager;
 import android.widget.BaseAdapter;
 import android.widget.Spinner;
-import android.widget.Toast;
 import android.widget.Toolbar;
 
 import com.android.documentsui.RecentsProvider.RecentColumns;
@@ -510,7 +510,7 @@
         } else if (mState.action == ACTION_OPEN_COPY_DESTINATION) {
             // Picking a copy destination is only used internally by us, so we
             // don't need to extend permissions to the caller.
-            intent.putExtra(CopyService.EXTRA_STACK, (Parcelable) mState.stack);
+            intent.putExtra(Shared.EXTRA_STACK, (Parcelable) mState.stack);
             intent.putExtra(CopyService.EXTRA_TRANSFER_MODE, mState.transferMode);
         } else {
             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
@@ -611,8 +611,8 @@
             if (result != null) {
                 onTaskFinished(result);
             } else {
-                Toast.makeText(DocumentsActivity.this, R.string.save_error, Toast.LENGTH_SHORT)
-                        .show();
+                Shared.makeSnackbar(
+                    DocumentsActivity.this, R.string.save_error, Snackbar.LENGTH_SHORT).show();
             }
 
             setPending(false);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FailureDialogFragment.java b/packages/DocumentsUI/src/com/android/documentsui/FailureDialogFragment.java
index ea0c18a..120f610 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FailureDialogFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FailureDialogFragment.java
@@ -66,7 +66,7 @@
         if (whichButton == DialogInterface.BUTTON_POSITIVE) {
             CopyService.start(getActivity(), mFailedSrcList,
                     (DocumentStack) getActivity().getIntent().getParcelableExtra(
-                            CopyService.EXTRA_STACK),
+                            Shared.EXTRA_STACK),
                             mTransferMode);
         }
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index e8d1088..f6a5131 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -30,7 +30,10 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Parcelable;
+import android.provider.DocumentsContract;
 import android.support.annotation.Nullable;
+import android.support.design.widget.Snackbar;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.Menu;
@@ -38,7 +41,6 @@
 import android.view.View;
 import android.widget.BaseAdapter;
 import android.widget.Spinner;
-import android.widget.Toast;
 import android.widget.Toolbar;
 
 import com.android.documentsui.RecentsProvider.ResumeColumns;
@@ -85,32 +87,49 @@
         mDrawer = DrawerController.create(this);
 
         RootsFragment.show(getFragmentManager(), null);
-        if (!mState.restored) {
-            Intent intent = getIntent();
-            Uri rootUri = intent.getData();
 
-            // If we've got a specific root to display, restore that root using a dedicated
-            // authority. That way a misbehaving provider won't result in an ANR.
-            if (rootUri != null && !LauncherActivity.isLaunchUri(rootUri)) {
-                new RestoreRootTask(rootUri).executeOnExecutor(
-                        ProviderExecutor.forAuthority(rootUri.getAuthority()));
+        if (mState.restored) {
+            onCurrentDirectoryChanged(ANIM_NONE);
+        } else {
+            Intent intent = getIntent();
+            Uri uri = intent.getData();
+
+            // If a non-empty stack is present in our state it was read (presumably)
+            // from EXTRA_STACK intent extra. In this case, we'll skip other means of
+            // loading or restoring the stack.
+            if (!mState.stack.isEmpty()) {
+                // When restoring from a stack, if a URI is present, it should only ever
+                // be a launch URI. Launch URIs support sensible activity management, but
+                // don't specify an real content target.
+                if (uri != null) {
+                    checkState(LauncherActivity.isLaunchUri(uri));
+                }
+                onCurrentDirectoryChanged(ANIM_NONE);
+            } else if (DocumentsContract.isRootUri(this, uri)) {
+                // If we've got a specific root to display, restore that root using a dedicated
+                // authority. That way a misbehaving provider won't result in an ANR.
+                new RestoreRootTask(uri).executeOnExecutor(
+                        ProviderExecutor.forAuthority(uri.getAuthority()));
             } else {
+                // Finally, we try to restore a stack from recents.
                 new RestoreStackTask().execute();
             }
 
+            // TODO: Ensure we're handling CopyService errors correctly across all activities.
             // Show a failure dialog if there was a failed operation.
-            final DocumentStack dstStack = intent.getParcelableExtra(CopyService.EXTRA_STACK);
             final int failure = intent.getIntExtra(CopyService.EXTRA_FAILURE, 0);
             final int transferMode = intent.getIntExtra(CopyService.EXTRA_TRANSFER_MODE,
                     CopyService.TRANSFER_MODE_NONE);
             if (failure != 0) {
                 final ArrayList<DocumentInfo> failedSrcList =
                         intent.getParcelableArrayListExtra(CopyService.EXTRA_SRC_LIST);
-                FailureDialogFragment.show(getFragmentManager(), failure, failedSrcList, dstStack,
+                FailureDialogFragment.show(
+                        getFragmentManager(),
+                        failure,
+                        failedSrcList,
+                        mState.stack,
                         transferMode);
             }
-        } else {
-            onCurrentDirectoryChanged(ANIM_NONE);
         }
     }
 
@@ -126,7 +145,7 @@
         // Options specific to the DocumentsActivity.
         checkArgument(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
 
-        final DocumentStack stack = intent.getParcelableExtra(CopyService.EXTRA_STACK);
+        final DocumentStack stack = intent.getParcelableExtra(Shared.EXTRA_STACK);
         if (stack != null) {
             state.stack = stack;
         }
@@ -240,7 +259,7 @@
                 showCreateDirectoryDialog();
                 return true;
             case R.id.menu_new_window:
-                startActivity(LauncherActivity.createLaunchIntent(this));
+                createNewWindow();
                 return true;
             case R.id.menu_paste_from_clipboard:
                 DirectoryFragment dir = DirectoryFragment.get(getFragmentManager());
@@ -252,6 +271,12 @@
         return super.onOptionsItemSelected(item);
     }
 
+    private void createNewWindow() {
+        Intent intent = LauncherActivity.createLaunchIntent(this);
+        intent.putExtra(Shared.EXTRA_STACK, (Parcelable) mState.stack);
+        startActivity(intent);
+    }
+
     @Override
     void onDirectoryChanged(int anim) {
         final FragmentManager fm = getFragmentManager();
@@ -322,7 +347,7 @@
         try {
             startActivity(intent);
         } catch (ActivityNotFoundException ex2) {
-            Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
+            Shared.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT).show();
         }
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
index 4754899..ed7333d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
@@ -31,12 +31,12 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.DocumentsContract;
+import android.support.design.widget.Snackbar;
 import android.util.Log;
 import android.view.Menu;
 import android.view.View;
 import android.widget.BaseAdapter;
 import android.widget.Spinner;
-import android.widget.Toast;
 import android.widget.Toolbar;
 
 import com.android.documentsui.RecentsProvider.ResumeColumns;
@@ -184,7 +184,8 @@
                 try {
                     startActivity(view);
                 } catch (ActivityNotFoundException ex2) {
-                    Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
+                    Shared.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT)
+                            .show();
                 }
             }
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 9c884d4..e06d6a5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -16,14 +16,18 @@
 
 package com.android.documentsui;
 
-import android.content.Context;
+import static com.android.internal.util.Preconditions.checkNotNull;
 
-/**
- * @hide
- */
+import android.app.Activity;
+import android.content.Context;
+import android.support.design.widget.Snackbar;
+import android.view.View;
+
+/** @hide */
 public final class Shared {
     public static final boolean DEBUG = true;
     public static final String TAG = "Documents";
+    public static final String EXTRA_STACK = "com.android.documentsui.STACK";
 
     /**
      * Generates a formatted quantity string.
@@ -31,4 +35,14 @@
     public static final String getQuantityString(Context context, int resourceId, int quantity) {
         return context.getResources().getQuantityString(resourceId, quantity, quantity);
     }
+
+    public static final Snackbar makeSnackbar(Activity activity, int messageId, int duration) {
+        return makeSnackbar(activity, activity.getResources().getText(messageId), duration);
+    }
+
+    public static final Snackbar makeSnackbar(Activity activity, CharSequence message, int duration)
+    {
+        final View view = checkNotNull(activity.findViewById(R.id.coordinator_layout));
+        return Snackbar.make(view, message, duration);
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java
index 568e9e4..fc42c3b 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java
@@ -425,7 +425,7 @@
         stack.push(DocumentInfo.fromUri(mResolver, dst));
         final Intent copyIntent = new Intent(mContext, CopyService.class);
         copyIntent.putParcelableArrayListExtra(CopyService.EXTRA_SRC_LIST, srcDocs);
-        copyIntent.putExtra(CopyService.EXTRA_STACK, (Parcelable) stack);
+        copyIntent.putExtra(Shared.EXTRA_STACK, (Parcelable) stack);
 
         // startService(copyIntent);
         return copyIntent;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
index 1895a6e..98ffb77 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
@@ -34,6 +34,9 @@
 import com.android.documentsui.model.DocumentInfo;
 
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 
 
 public class DirectoryFragmentModelTest extends AndroidTestCase {
@@ -77,14 +80,6 @@
         delete(2, 4);
 
         assertEquals(ITEM_COUNT - 2, model.getItemCount());
-
-        // Finalize the deletion.  Provide a callback that just ignores errors.
-        model.finalizeDeletion(
-              new Runnable() {
-                  @Override
-                  public void run() {}
-              });
-        assertEquals(ITEM_COUNT - 2, model.getItemCount());
     }
 
     // Tests that the item count is correct after a deletion is undone.
@@ -95,7 +90,6 @@
         // Undo the deletion
         model.undoDeletion();
         assertEquals(ITEM_COUNT, model.getItemCount());
-
     }
 
     // Tests that the right things are marked for deletion.
@@ -125,6 +119,15 @@
         assertEquals("0", docs.get(0).documentId);
         assertEquals("1", docs.get(1).documentId);
         assertEquals("4", docs.get(2).documentId);
+
+        TestDeletionListener testListener = new TestDeletionListener();
+        model.finalizeDeletion(testListener);
+        testListener.waitForDone();
+
+        docs = getDocumentInfo(0, 1, 2);
+        assertEquals("0", docs.get(0).documentId);
+        assertEquals("1", docs.get(1).documentId);
+        assertEquals("2", docs.get(2).documentId);
     }
 
     // Tests that Model.getItem returns the right items after a deletion is undone.
@@ -176,4 +179,20 @@
             return null;
         }
     }
+
+    private static class TestDeletionListener extends Model.DeletionListener {
+        final CountDownLatch mSignal = new CountDownLatch(1);
+
+        @Override
+        public void onCompletion() {
+            mSignal.countDown();
+        }
+
+        public void waitForDone() {
+            try {
+                boolean timeout = mSignal.await(10, TimeUnit.SECONDS);
+                assertTrue("Timed out waiting for deletion completion", timeout);
+            } catch (InterruptedException e) {}
+        }
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
index 25d4ed4..2447469 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.support.v7.widget.RecyclerView;
+import android.test.AndroidTestCase;
 import android.util.SparseBooleanArray;
 import android.view.MotionEvent;
 import android.view.View;
@@ -27,8 +28,6 @@
 
 import com.android.documentsui.MultiSelectManager.Selection;
 
-import org.junit.Before;
-import org.junit.Test;
 import org.mockito.Mockito;
 
 import java.util.ArrayList;
@@ -36,7 +35,7 @@
 import java.util.List;
 import java.util.Set;
 
-public class MultiSelectManagerTest {
+public class MultiSelectManagerTest extends AndroidTestCase {
 
     private static final List<String> items;
     static {
@@ -54,7 +53,6 @@
     private TestCallback mCallback;
     private EventHelper mEventHelper;
 
-    @Before
     public void setUp() throws Exception {
         mAdapter = new TestAdapter(items);
         mCallback = new TestCallback();
@@ -63,65 +61,61 @@
         mManager.addCallback(mCallback);
     }
 
-    @Test
-    public void mouseClick_StartsSelectionMode() {
+    public void testMouseClick_StartsSelectionMode() {
         click(7);
         assertSelection(7);
     }
 
-    @Test
-    public void mouseClick_ShiftClickExtendsSelection() {
+    public void testMouseClick_NotifiesSelectionChanged() {
+        click(7);
+        mCallback.assertSelectionChanged();
+    }
+
+    public void testMouseClick_ShiftClickExtendsSelection() {
         longPress(7);
         shiftClick(11);
         assertRangeSelection(7, 11);
     }
 
-    @Test
-    public void mouseClick_NoPosition_ClearsSelection() {
+    public void testMouseClick_NoPosition_ClearsSelection() {
         longPress(7);
         click(11);
         click(RecyclerView.NO_POSITION);
         assertSelection();
     }
 
-    @Test
-    public void setSelectionFocusBegin() {
+    public void testSetSelectionFocusBegin() {
         mManager.setItemSelected(7, true);
         mManager.setSelectionFocusBegin(7);
         shiftClick(11);
         assertRangeSelection(7, 11);
     }
 
-    @Test
-    public void longPress_StartsSelectionMode() {
+    public void testLongPress_StartsSelectionMode() {
         longPress(7);
         assertSelection(7);
     }
 
-    @Test
-    public void longPress_SecondPressExtendsSelection() {
+    public void testLongPress_SecondPressExtendsSelection() {
         longPress(7);
         longPress(99);
         assertSelection(7, 99);
     }
 
-    @Test
-    public void singleTapUp_UnselectsSelectedItem() {
+    public void testSingleTapUp_UnselectsSelectedItem() {
         longPress(7);
         tap(7);
         assertSelection();
     }
 
-    @Test
-    public void singleTapUp_NoPosition_ClearsSelection() {
+    public void testSingleTapUp_NoPosition_ClearsSelection() {
         longPress(7);
         tap(11);
         tap(RecyclerView.NO_POSITION);
         assertSelection();
     }
 
-    @Test
-    public void singleTapUp_ExtendsSelection() {
+    public void testSingleTapUp_ExtendsSelection() {
         longPress(99);
         tap(7);
         tap(13);
@@ -129,30 +123,26 @@
         assertSelection(7, 99, 13, 129899);
     }
 
-    @Test
-    public void singleTapUp_ShiftCreatesRangeSelection() {
+    public void testSingleTapUp_ShiftCreatesRangeSelection() {
         longPress(7);
         shiftTap(17);
         assertRangeSelection(7, 17);
     }
 
-    @Test
-    public void singleTapUp_ShiftCreatesRangeSeletion_Backwards() {
+    public void testSingleTapUp_ShiftCreatesRangeSeletion_Backwards() {
         longPress(17);
         shiftTap(7);
         assertRangeSelection(7, 17);
     }
 
-    @Test
-    public void singleTapUp_SecondShiftClickExtendsSelection() {
+    public void testSingleTapUp_SecondShiftClickExtendsSelection() {
         longPress(7);
         shiftTap(11);
         shiftTap(17);
         assertRangeSelection(7, 17);
     }
 
-    @Test
-    public void singleTapUp_MultipleContiguousRangesSelected() {
+    public void testSingleTapUp_MultipleContiguousRangesSelected() {
         longPress(7);
         shiftTap(11);
         tap(20);
@@ -162,16 +152,14 @@
         assertSelectionSize(11);
     }
 
-    @Test
-    public void singleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick() {
+    public void testSingleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick() {
         longPress(7);
         shiftTap(17);
         shiftTap(10);
         assertRangeSelection(7, 10);
     }
 
-    @Test
-    public void singleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick_Backwards() {
+    public void testSingleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick_Backwards() {
         mManager.onLongPress(TestInputEvent.tap(17));
         shiftTap(7);
         shiftTap(14);
@@ -179,16 +167,14 @@
     }
 
 
-    @Test
-    public void singleTapUp_ShiftReversesSelectionDirection() {
+    public void testSingleTapUp_ShiftReversesSelectionDirection() {
         longPress(7);
         shiftTap(17);
         shiftTap(0);
         assertRangeSelection(0, 7);
     }
 
-    @Test
-    public void singleSelectMode() {
+    public void testSingleSelectMode() {
         mManager = new MultiSelectManager(mAdapter, mEventHelper, MultiSelectManager.MODE_SINGLE);
         mManager.addCallback(mCallback);
         longPress(20);
@@ -196,8 +182,7 @@
         assertSelection(13);
     }
 
-    @Test
-    public void singleSelectMode_ShiftTap() {
+    public void testSingleSelectMode_ShiftTap() {
         mManager = new MultiSelectManager(mAdapter, mEventHelper, MultiSelectManager.MODE_SINGLE);
         mManager.addCallback(mCallback);
         longPress(13);
@@ -205,8 +190,7 @@
         assertSelection(20);
     }
 
-    @Test
-    public void provisionaSelection() {
+    public void testProvisionalSelection() {
         Selection s = mManager.getSelection();
         assertSelection();
 
@@ -298,6 +282,7 @@
         Set<Integer> ignored = new HashSet<>();
         private int mLastChangedPosition;
         private boolean mLastChangedSelected;
+        private boolean mSelectionChanged = false;
 
         @Override
         public void onItemStateChanged(int position, boolean selected) {
@@ -311,7 +296,13 @@
         }
 
         @Override
-        public void onSelectionChanged() {}
+        public void onSelectionChanged() {
+            mSelectionChanged = true;
+        }
+
+        void assertSelectionChanged() {
+            assertTrue(mSelectionChanged);
+        }
     }
 
     private static final class TestHolder extends RecyclerView.ViewHolder {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java
index 87d7e15..aa50b48 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java
@@ -22,14 +22,12 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.support.v7.widget.RecyclerView.OnScrollListener;
+import android.test.AndroidTestCase;
 import android.util.SparseBooleanArray;
 
 import com.android.documentsui.MultiSelectManager.GridModel;
 
-import org.junit.After;
-import org.junit.Test;
-
-public class MultiSelectManager_GridModelTest {
+public class MultiSelectManager_GridModelTest extends AndroidTestCase {
 
     private static final int VIEW_PADDING_PX = 5;
     private static final int CHILD_VIEW_EDGE_PX = 100;
@@ -53,14 +51,13 @@
                 });
     }
 
-    @After
+    @Override
     public void tearDown() {
         model = null;
         helper = null;
         lastSelection = null;
     }
 
-    @Test
     public void testSelectionLeftOfItems() {
         setUp(20, 5);
         model.startSelection(new Point(0, 10));
@@ -69,7 +66,6 @@
         assertEquals(GridModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
-    @Test
     public void testSelectionRightOfItems() {
         setUp(20, 4);
         model.startSelection(new Point(viewWidth - 1, 10));
@@ -78,7 +74,6 @@
         assertEquals(GridModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
-    @Test
     public void testSelectionAboveItems() {
         setUp(20, 4);
         model.startSelection(new Point(10, 0));
@@ -87,7 +82,6 @@
         assertEquals(GridModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
-    @Test
     public void testSelectionBelowItems() {
         setUp(5, 4);
         model.startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
@@ -96,7 +90,6 @@
         assertEquals(GridModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
-    @Test
     public void testVerticalSelectionBetweenItems() {
         setUp(20, 4);
         model.startSelection(new Point(106, 0));
@@ -105,7 +98,6 @@
         assertEquals(GridModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
-    @Test
     public void testHorizontalSelectionBetweenItems() {
         setUp(20, 4);
         model.startSelection(new Point(0, 105));
@@ -114,7 +106,6 @@
         assertEquals(GridModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
-    @Test
     public void testGrowingAndShrinkingSelection() {
         setUp(20, 4);
         model.startSelection(new Point(0, 0));
@@ -145,7 +136,6 @@
         assertEquals(GridModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
-    @Test
     public void testSelectionMovingAroundOrigin() {
         setUp(16, 4);
         model.startSelection(new Point(210, 210));
@@ -160,7 +150,6 @@
         assertEquals(10, model.getPositionNearestOrigin());
     }
 
-    @Test
     public void testScrollingBandSelect() {
         setUp(40, 4);
         model.startSelection(new Point(0, 0));
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_SelectionTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_SelectionTest.java
index 51b542b..eddf4ef 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_SelectionTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_SelectionTest.java
@@ -18,16 +18,16 @@
 
 import static org.junit.Assert.*;
 
+import android.test.AndroidTestCase;
+
 import com.android.documentsui.MultiSelectManager.Selection;
 
-import org.junit.Before;
-import org.junit.Test;
 
-public class MultiSelectManager_SelectionTest {
+public class MultiSelectManager_SelectionTest extends AndroidTestCase{
 
     private Selection selection;
 
-    @Before
+    @Override
     public void setUp() throws Exception {
         selection = new Selection();
         selection.add(3);
@@ -35,8 +35,7 @@
         selection.add(9);
     }
 
-    @Test
-    public void add() {
+    public void testAdd() {
         // We added in setUp.
         assertEquals(3, selection.size());
         assertContains(3);
@@ -44,29 +43,25 @@
         assertContains(9);
     }
 
-    @Test
-    public void remove() {
+    public void testRemove() {
         selection.remove(3);
         selection.remove(5);
         assertEquals(1, selection.size());
         assertContains(9);
     }
 
-    @Test
-    public void clear() {
+    public void testClear() {
         selection.clear();
         assertEquals(0, selection.size());
     }
 
-    @Test
-    public void isEmpty() {
+    public void testIsEmpty() {
         assertTrue(new Selection().isEmpty());
         selection.clear();
         assertTrue(selection.isEmpty());
     }
 
-    @Test
-    public void sizeAndGet() {
+    public void testSizeAndGet() {
         Selection other = new Selection();
         for (int i = 0; i < selection.size(); i++) {
             other.add(selection.get(i));
@@ -74,13 +69,11 @@
         assertEquals(selection.size(), other.size());
     }
 
-    @Test
-    public void equalsSelf() {
+    public void testEqualsSelf() {
         assertEquals(selection, selection);
     }
 
-    @Test
-    public void equalsOther() {
+    public void testEqualsOther() {
         Selection other = new Selection();
         other.add(3);
         other.add(5);
@@ -89,23 +82,20 @@
         assertEquals(selection.hashCode(), other.hashCode());
     }
 
-    @Test
-    public void equalsCopy() {
+    public void testEqualsCopy() {
         Selection other = new Selection();
         other.copyFrom(selection);
         assertEquals(selection, other);
         assertEquals(selection.hashCode(), other.hashCode());
     }
 
-    @Test
-    public void notEquals() {
+    public void testNotEquals() {
         Selection other = new Selection();
         other.add(789);
         assertFalse(selection.equals(other));
     }
 
-    @Test
-    public void expandBefore() {
+    public void testExpandBefore() {
         selection.expand(2, 10);
         assertEquals(3, selection.size());
         assertContains(13);
@@ -113,8 +103,7 @@
         assertContains(19);
     }
 
-    @Test
-    public void expandAfter() {
+    public void testExpandAfter() {
         selection.expand(10, 10);
         assertEquals(3, selection.size());
         assertContains(3);
@@ -122,8 +111,7 @@
         assertContains(9);
     }
 
-    @Test
-    public void expandSplit() {
+    public void testExpandSplit() {
         selection.expand(5, 10);
         assertEquals(3, selection.size());
         assertContains(3);
@@ -131,8 +119,7 @@
         assertContains(19);
     }
 
-    @Test
-    public void expandEncompased() {
+    public void testExpandEncompased() {
         selection.expand(2, 10);
         assertEquals(3, selection.size());
         assertContains(13);
@@ -140,8 +127,7 @@
         assertContains(19);
     }
 
-    @Test
-    public void collapseBefore() {
+    public void testCollapseBefore() {
         selection.collapse(0, 2);
         assertEquals(3, selection.size());
         assertContains(1);
@@ -149,8 +135,7 @@
         assertContains(7);
     }
 
-    @Test
-    public void collapseAfter() {
+    public void testCollapseAfter() {
         selection.collapse(10, 10);
         assertEquals(3, selection.size());
         assertContains(3);
@@ -158,8 +143,7 @@
         assertContains(9);
     }
 
-    @Test
-    public void collapseAcross() {
+    public void testCollapseAcross() {
         selection.collapse(0, 10);
         assertEquals(0, selection.size());
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java b/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
deleted file mode 100644
index be3f251..0000000
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.documentsui;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-import org.junit.runners.Suite.SuiteClasses;
-
-@RunWith(Suite.class)
-@SuiteClasses({
-        MultiSelectManager_GridModelTest.class,
-        MultiSelectManager_SelectionTest.class,
-        MultiSelectManagerTest.class
-})
-
-/**
- * This test suite can be run using the "art" runtime (which can be built
- * via the `build-art-host` target.) You'll also need to "mma -j32" the
- * DocumentsUI package to ensure all deps are built.
- *
- * <p>Once the dependencies have been built, the tests can be executed as follows:
- *
- * <pre>
- *  CP=$OUT/system/framework/framework.jar:\
- *      $OUT/system/framework/core-junit.jar:\
- *      $OUT/system/app/DocumentsUI/DocumentsUI.apk:\
- *      $OUT/data/app/DocumentsUITests/DocumentsUITests.apk
- *
- *  art -cp $CP org.junit.runner.JUnitCore com.android.documentsui.UnitTests
- * </pre>
- */
-public class UnitTests {}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 393771a..18335b6 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -38,6 +38,7 @@
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsProvider;
+import android.provider.MediaStore;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.DebugUtils;
@@ -380,12 +381,31 @@
     @Override
     public void deleteDocument(String docId) throws FileNotFoundException {
         final File file = getFileForDocId(docId);
-        if (file.isDirectory()) {
+        final boolean isDirectory = file.isDirectory();
+        if (isDirectory) {
             FileUtils.deleteContents(file);
         }
         if (!file.delete()) {
             throw new IllegalStateException("Failed to delete " + file);
         }
+
+        final ContentResolver resolver = getContext().getContentResolver();
+        final Uri externalUri = MediaStore.Files.getContentUri("external");
+
+        // Remove media store entries for any files inside this directory, using
+        // path prefix match. Logic borrowed from MtpDatabase.
+        if (isDirectory) {
+            final String path = file.getAbsolutePath() + "/";
+            resolver.delete(externalUri,
+                    "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
+                    new String[] { path + "%", Integer.toString(path.length()), path });
+        }
+
+        // Remove media store entry for this exact file.
+        final String path = file.getAbsolutePath();
+        resolver.delete(externalUri,
+                "_data LIKE ?1 AND lower(_data)=lower(?2)",
+                new String[] { path, path });
     }
 
     @Override
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 1cd2908..c324abd 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -204,9 +204,6 @@
     <!-- Default for Settings.Secure.WAKE_GESTURE_ENABLED -->
     <bool name="def_wake_gesture_enabled">true</bool>
 
-    <!-- Default for Settings.Global.GUEST_USER_ENABLED -->
-    <bool name="def_guest_user_enabled">true</bool>
-
     <!-- Default state of tap to wake -->
     <bool name="def_double_tap_to_wake">true</bool>
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index ee296d9..d4e428e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1693,20 +1693,7 @@
         }
 
         if (upgradeVersion < 105) {
-            if (mUserHandle == UserHandle.USER_SYSTEM) {
-                db.beginTransaction();
-                SQLiteStatement stmt = null;
-                try {
-                    stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)"
-                            + " VALUES(?,?);");
-                    loadBooleanSetting(stmt, Settings.Global.GUEST_USER_ENABLED,
-                            R.bool.def_guest_user_enabled);
-                    db.setTransactionSuccessful();
-                } finally {
-                    db.endTransaction();
-                    if (stmt != null) stmt.close();
-                }
-            }
+            // No-op: GUEST_USER_ENABLED setting was removed
             upgradeVersion = 105;
         }
 
@@ -2705,8 +2692,6 @@
 
             loadSetting(stmt, Settings.Global.DEVICE_NAME, getDefaultDeviceName());
 
-            loadBooleanSetting(stmt, Settings.Global.GUEST_USER_ENABLED,
-                    R.bool.def_guest_user_enabled);
             loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED,
                     ImsConfig.FeatureValueConstants.ON);
 
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 472303e..b6d25f5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -697,14 +697,6 @@
             ActivityManager.StackInfo stackInfo = mIam.getStackInfo(ActivityManager.HOME_STACK_ID);
             if (stackInfo != null) {
                 windowRect.set(stackInfo.bounds);
-                // Temporary workaround, if we query this too early, occasionally, the home stack
-                // bounds are offset incorrectly
-                if (windowRect.left < 0) {
-                    windowRect.offset(-windowRect.left, 0);
-                }
-                if (windowRect.top < 0) {
-                    windowRect.offset(0, -windowRect.top);
-                }
             }
         } catch (RemoteException e) {
             e.printStackTrace();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index e70d146..71267cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -81,7 +81,7 @@
     }
 
     private void registerListener() {
-        if (UserSwitcherController.isUserSwitcherAvailable(mUserManager) && mUserListener == null) {
+        if (mUserManager.isUserSwitcherEnabled() && mUserListener == null) {
 
             final UserSwitcherController controller = mUserSwitcherController;
             if (controller != null) {
@@ -103,7 +103,7 @@
 
     @Override
     public void onClick(View v) {
-        if (UserSwitcherController.isUserSwitcherAvailable(mUserManager)) {
+        if (mUserManager.isUserSwitcherEnabled()) {
             if (mKeyguardMode) {
                 if (mKeyguardUserSwitcher != null) {
                     mKeyguardUserSwitcher.show(true /* animate */);
@@ -135,14 +135,14 @@
 
     private void refreshContentDescription() {
         String currentUser = null;
-        if (UserSwitcherController.isUserSwitcherAvailable(mUserManager)
+        if (mUserManager.isUserSwitcherEnabled()
                 && mUserSwitcherController != null) {
             currentUser = mUserSwitcherController.getCurrentUserName(mContext);
         }
 
         String text = null;
         if (isClickable()) {
-            if (UserSwitcherController.isUserSwitcherAvailable(mUserManager)) {
+            if (mUserManager.isUserSwitcherEnabled()) {
                 if (TextUtils.isEmpty(currentUser)) {
                     text = mContext.getString(R.string.accessibility_multi_user_switch_switcher);
                 } else {
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 876a934..37edc28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -882,7 +882,7 @@
         mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
         mNextAlarmController = new NextAlarmController(mContext);
         mKeyguardMonitor = new KeyguardMonitor(mContext);
-        if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) {
+        if (UserManager.get(mContext).isUserSwitcherEnabled()) {
             mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
                     mHandler);
             if (mUserSwitcherController.useFullscreenUserSwitcher()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 8165894..e00b890 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -752,9 +752,4 @@
             }
         }
     }
-
-    public static boolean isUserSwitcherAvailable(UserManager um) {
-        return UserManager.supportsMultipleUsers() && um.isUserSwitcherEnabled();
-    }
-
 }
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 8c830e8..3759c91 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -611,7 +611,7 @@
     in_allocs[2] = (RsAllocation)C;
 
     rsScriptForEachMulti((RsContext)con, (RsScript)id, 0,
-                         in_allocs, sizeof(in_allocs), nullptr,
+                         in_allocs, NELEM(in_allocs), nullptr,
                          &call, sizeof(call), nullptr, 0);
 }
 
@@ -646,7 +646,7 @@
     in_allocs[2] = (RsAllocation)C;
 
     rsScriptForEachMulti((RsContext)con, (RsScript)id, 0,
-                         in_allocs, sizeof(in_allocs), nullptr,
+                         in_allocs, NELEM(in_allocs), nullptr,
                          &call, sizeof(call), nullptr, 0);
 }
 
@@ -681,7 +681,7 @@
     in_allocs[2] = (RsAllocation)C;
 
     rsScriptForEachMulti((RsContext)con, (RsScript)id, 0,
-                         in_allocs, sizeof(in_allocs), nullptr,
+                         in_allocs, NELEM(in_allocs), nullptr,
                          &call, sizeof(call), nullptr, 0);
 }
 
@@ -707,7 +707,7 @@
     in_allocs[2] = (RsAllocation)C;
 
     rsScriptForEachMulti((RsContext)con, (RsScript)id, 0,
-                         in_allocs, sizeof(in_allocs), nullptr,
+                         in_allocs, NELEM(in_allocs), nullptr,
                          &call, sizeof(call), nullptr, 0);
 }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 87a0b80..b52687a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -45,28 +45,28 @@
     /**
      * Flag for enabling the screen magnification feature.
      *
-     * @see #setEnabledFeatures(int)
+     * @see #setUserAndEnabledFeatures(int, int)
      */
     static final int FLAG_FEATURE_SCREEN_MAGNIFIER = 0x00000001;
 
     /**
      * Flag for enabling the touch exploration feature.
      *
-     * @see #setEnabledFeatures(int)
+     * @see #setUserAndEnabledFeatures(int, int)
      */
     static final int FLAG_FEATURE_TOUCH_EXPLORATION = 0x00000002;
 
     /**
      * Flag for enabling the filtering key events feature.
      *
-     * @see #setEnabledFeatures(int)
+     * @see #setUserAndEnabledFeatures(int, int)
      */
     static final int FLAG_FEATURE_FILTER_KEY_EVENTS = 0x00000004;
 
     /**
      * Flag for enabling "Automatically click on mouse stop" feature.
      *
-     * @see #setEnabledFeatures(int)
+     * @see #setUserAndEnabledFeatures(int, int)
      */
     static final int FLAG_FEATURE_AUTOCLICK = 0x00000008;
 
@@ -97,6 +97,8 @@
 
     private boolean mInstalled;
 
+    private int mUserId;
+
     private int mEnabledFeatures;
 
     private TouchExplorer mTouchExplorer;
@@ -327,13 +329,14 @@
         /* do nothing */
     }
 
-    void setEnabledFeatures(int enabledFeatures) {
-        if (mEnabledFeatures == enabledFeatures) {
+    void setUserAndEnabledFeatures(int userId, int enabledFeatures) {
+        if (mEnabledFeatures == enabledFeatures && mUserId == userId) {
             return;
         }
         if (mInstalled) {
             disableFeatures();
         }
+        mUserId = userId;
         mEnabledFeatures = enabledFeatures;
         if (mInstalled) {
             enableFeatures();
@@ -350,7 +353,7 @@
         resetStreamState();
 
         if ((mEnabledFeatures & FLAG_FEATURE_AUTOCLICK) != 0) {
-            mAutoclickController = new AutoclickController(mContext);
+            mAutoclickController = new AutoclickController(mContext, mUserId);
             addFirstEventHandler(mAutoclickController);
         }
 
@@ -360,7 +363,7 @@
         }
 
         if ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0) {
-            mScreenMagnifier = new ScreenMagnifier(mContext,
+            mScreenMagnifier = new ScreenMagnifier(mContext, mUserId,
                     Display.DEFAULT_DISPLAY, mAms);
             addFirstEventHandler(mScreenMagnifier);
         }
@@ -386,7 +389,7 @@
         mEventHandler = handler;
     }
 
-    void disableFeatures() {
+    private void disableFeatures() {
         if (mAutoclickController != null) {
             mAutoclickController.onDestroy();
             mAutoclickController = null;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ff2a2ee..749a080 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1296,11 +1296,11 @@
                     inputFilter = mInputFilter;
                     setInputFilter = true;
                 }
-                mInputFilter.setEnabledFeatures(flags);
+                mInputFilter.setUserAndEnabledFeatures(userState.mUserId, flags);
             } else {
                 if (mHasInputFilter) {
                     mHasInputFilter = false;
-                    mInputFilter.disableFeatures();
+                    mInputFilter.setUserAndEnabledFeatures(userState.mUserId, 0);
                     inputFilter = null;
                     setInputFilter = true;
                 }
diff --git a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java
index 8989625..3283378 100644
--- a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java
+++ b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java
@@ -51,6 +51,8 @@
  *
  * It is expected that each instance will receive mouse events from a single mouse device. User of
  * the class should handle cases where multiple mouse devices are present.
+ *
+ * Each instance is associated to a single user (and it does not handle user switch itself).
  */
 public class AutoclickController implements EventStreamTransformation {
 
@@ -60,13 +62,15 @@
 
     private EventStreamTransformation mNext;
     private final Context mContext;
+    private final int mUserId;
 
     // Lazily created on the first mouse motion event.
     private ClickScheduler mClickScheduler;
     private ClickDelayObserver mClickDelayObserver;
 
-    public AutoclickController(Context context) {
+    public AutoclickController(Context context, int userId) {
         mContext = context;
+        mUserId = userId;
     }
 
     @Override
@@ -75,7 +79,7 @@
             if (mClickScheduler == null) {
                 Handler handler = new Handler(mContext.getMainLooper());
                 mClickScheduler = new ClickScheduler(handler, DEFAULT_CLICK_DELAY_MS);
-                mClickDelayObserver = new ClickDelayObserver(handler);
+                mClickDelayObserver = new ClickDelayObserver(mUserId, handler);
                 mClickDelayObserver.start(mContext.getContentResolver(), mClickScheduler);
             }
 
@@ -168,9 +172,11 @@
 
         private ContentResolver mContentResolver;
         private ClickScheduler mClickScheduler;
+        private final int mUserId;
 
-        public ClickDelayObserver(Handler handler) {
+        public ClickDelayObserver(int userId, Handler handler) {
             super(handler);
+            mUserId = userId;
         }
 
         /**
@@ -199,7 +205,7 @@
             mContentResolver = contentResolver;
             mClickScheduler = clickScheduler;
             mContentResolver.registerContentObserver(mAutoclickDelaySettingUri, false, this,
-                    UserHandle.USER_ALL);
+                    mUserId);
 
             // Initialize mClickScheduler's initial delay value.
             onChange(true, mAutoclickDelaySettingUri);
@@ -222,10 +228,9 @@
         @Override
         public void onChange(boolean selfChange, Uri uri) {
             if (mAutoclickDelaySettingUri.equals(uri)) {
-                // TODO: Plumb current user id down to here and use getIntForUser.
-                int delay = Settings.Secure.getInt(
+                int delay = Settings.Secure.getIntForUser(
                         mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
-                        DEFAULT_CLICK_DELAY_MS);
+                        DEFAULT_CLICK_DELAY_MS, mUserId);
                 mClickScheduler.updateDelay(delay);
             }
         }
diff --git a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
index 37276bd..8845bc0 100644
--- a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
+++ b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
@@ -29,7 +29,6 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.Message;
-import android.os.SystemClock;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Property;
@@ -137,6 +136,8 @@
 
     private final AccessibilityManagerService mAms;
 
+    private final int mUserId;
+
     private final int mTapTimeSlop = ViewConfiguration.getJumpTapTimeout();
     private final int mMultiTapTimeSlop;
     private final int mTapDistanceSlop;
@@ -188,8 +189,10 @@
         }
     };
 
-    public ScreenMagnifier(Context context, int displayId, AccessibilityManagerService service) {
+    public ScreenMagnifier(Context context, int userId, int displayId,
+            AccessibilityManagerService service) {
         mContext = context;
+        mUserId = userId;
         mWindowManager = LocalServices.getService(WindowManagerInternal.class);
         mAms = service;
 
@@ -813,33 +816,12 @@
             while (mDelayedEventQueue != null) {
                 MotionEventInfo info = mDelayedEventQueue;
                 mDelayedEventQueue = info.mNext;
-                final long offset = SystemClock.uptimeMillis() - info.mCachedTimeMillis;
-                MotionEvent event = obtainEventWithOffsetTimeAndDownTime(info.mEvent, offset);
-                MotionEvent rawEvent = obtainEventWithOffsetTimeAndDownTime(info.mRawEvent, offset);
-                ScreenMagnifier.this.onMotionEvent(event, rawEvent, info.mPolicyFlags);
-                event.recycle();
-                rawEvent.recycle();
+                ScreenMagnifier.this.onMotionEvent(info.mEvent, info.mRawEvent,
+                        info.mPolicyFlags);
                 info.recycle();
             }
         }
 
-        private MotionEvent obtainEventWithOffsetTimeAndDownTime(MotionEvent event, long offset) {
-            final int pointerCount = event.getPointerCount();
-            PointerCoords[] coords = getTempPointerCoordsWithMinSize(pointerCount);
-            PointerProperties[] properties = getTempPointerPropertiesWithMinSize(pointerCount);
-            for (int i = 0; i < pointerCount; i++) {
-                event.getPointerCoords(i, coords[i]);
-                event.getPointerProperties(i, properties[i]);
-            }
-            final long downTime = event.getDownTime() + offset;
-            final long eventTime = event.getEventTime() + offset;
-            return MotionEvent.obtain(downTime, eventTime,
-                    event.getAction(), pointerCount, properties, coords,
-                    event.getMetaState(), event.getButtonState(),
-                    1.0f, 1.0f, event.getDeviceId(), event.getEdgeFlags(),
-                    event.getSource(), event.getFlags());
-        }
-
         private void clearDelayedMotionEvents() {
             while (mDelayedEventQueue != null) {
                 MotionEventInfo info = mDelayedEventQueue;
@@ -882,17 +864,17 @@
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
-                Settings.Secure.putFloat(mContext.getContentResolver(),
-                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale);
+                Settings.Secure.putFloatForUser(mContext.getContentResolver(),
+                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale, mUserId);
                 return null;
             }
         }.execute();
     }
 
     private float getPersistedScale() {
-        return Settings.Secure.getFloat(mContext.getContentResolver(),
+        return Settings.Secure.getFloatForUser(mContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
-                DEFAULT_MAGNIFICATION_SCALE);
+                DEFAULT_MAGNIFICATION_SCALE, mUserId);
     }
 
     private static boolean isScreenMagnificationAutoUpdateEnabled(Context context) {
@@ -915,7 +897,6 @@
         public MotionEvent mEvent;
         public MotionEvent mRawEvent;
         public int mPolicyFlags;
-        public long mCachedTimeMillis;
 
         public static MotionEventInfo obtain(MotionEvent event, MotionEvent rawEvent,
                 int policyFlags) {
@@ -940,7 +921,6 @@
             mEvent = MotionEvent.obtain(event);
             mRawEvent = MotionEvent.obtain(rawEvent);
             mPolicyFlags = policyFlags;
-            mCachedTimeMillis = SystemClock.uptimeMillis();
         }
 
         public void recycle() {
@@ -964,7 +944,6 @@
             mRawEvent.recycle();
             mRawEvent = null;
             mPolicyFlags = 0;
-            mCachedTimeMillis = 0;
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bd10c63..9753331 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -11893,7 +11893,8 @@
             updateCurrentProfileIdsLocked();
 
             mRecentTasks.clear();
-            mRecentTasks.addAll(mTaskPersister.restoreTasksLocked());
+            mRecentTasks.addAll(mTaskPersister.restoreTasksLocked(
+                    getUserManagerLocked().getUserIds()));
             mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
             mTaskPersister.startPersisting();
 
@@ -20644,9 +20645,6 @@
                 // Kill all the processes for the user.
                 forceStopUserLocked(userId, "finish user");
             }
-
-            // Explicitly remove the old information in mRecentTasks.
-            mRecentTasks.removeTasksForUserLocked(userId);
         }
 
         for (int i=0; i<callbacks.size(); i++) {
@@ -20665,6 +20663,10 @@
         }
     }
 
+    void onUserRemovedLocked(int userId) {
+        mRecentTasks.removeTasksForUserLocked(userId);
+    }
+
     @Override
     public UserInfo getCurrentUser() {
         if ((checkCallingPermission(INTERACT_ACROSS_USERS)
@@ -20949,6 +20951,13 @@
                 return homeActivity == null ? null : homeActivity.realActivity;
             }
         }
+
+        @Override
+        public void onUserRemoved(int userId) {
+            synchronized (ActivityManagerService.this) {
+                ActivityManagerService.this.onUserRemovedLocked(userId);
+            }
+        }
     }
 
     private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index aa154a7..871331b 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -35,6 +35,7 @@
 import android.util.Xml;
 import android.os.Process;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 
@@ -330,7 +331,7 @@
         return null;
     }
 
-    ArrayList<TaskRecord> restoreTasksLocked() {
+    ArrayList<TaskRecord> restoreTasksLocked(final int [] validUserIds) {
         final ArrayList<TaskRecord> tasks = new ArrayList<TaskRecord>();
         ArraySet<Integer> recoveredTaskIds = new ArraySet<Integer>();
 
@@ -362,15 +363,18 @@
                             if (DEBUG) Slog.d(TAG, "restoreTasksLocked: restored task=" +
                                     task);
                             if (task != null) {
-                                task.isPersistable = true;
                                 // XXX Don't add to write queue... there is no reason to write
                                 // out the stuff we just read, if we don't write it we will
                                 // read the same thing again.
                                 //mWriteQueue.add(new TaskWriteQueueItem(task));
-                                tasks.add(task);
                                 final int taskId = task.taskId;
-                                recoveredTaskIds.add(taskId);
                                 mStackSupervisor.setNextTaskId(taskId);
+                                // Check if it's a valid user id. Don't add tasks for removed users.
+                                if (ArrayUtils.contains(validUserIds, task.userId)) {
+                                    task.isPersistable = true;
+                                    tasks.add(task);
+                                    recoveredTaskIds.add(taskId);
+                                }
                             } else {
                                 Slog.e(TAG, "Unable to restore taskFile=" + taskFile + ": " +
                                         fileToString(taskFile));
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 43f5baa..7e14b2b 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1193,7 +1193,7 @@
             mOverrideConfig = Configuration.EMPTY;
         } else {
             mBounds = new Rect(bounds);
-            if (stack.mStackId != DOCKED_STACK_ID) {
+            if (stack == null || stack.mStackId != DOCKED_STACK_ID) {
                 mLastNonFullscreenBounds = mBounds;
             }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f6c9374..7b15aad 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -27,6 +27,7 @@
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.AutomaticZenRule;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
 import android.app.ITransientNotification;
@@ -101,6 +102,7 @@
 import com.android.internal.R;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.Preconditions;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -1172,8 +1174,8 @@
             // Don't allow client applications to cancel foreground service notis.
             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);
+                            ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId,
+                    REASON_NOMAN_CANCEL, null);
         }
 
         @Override
@@ -1594,6 +1596,50 @@
         }
 
         @Override
+        public List<AutomaticZenRule> getAutomaticZenRules() throws RemoteException {
+            enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRules");
+            return mZenModeHelper.getAutomaticZenRules();
+        }
+
+        @Override
+        public AutomaticZenRule getAutomaticZenRule(String name) throws RemoteException {
+            enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRule");
+            return mZenModeHelper.getAutomaticZenRule(name);
+        }
+
+        @Override
+        public boolean addOrUpdateAutomaticZenRule(AutomaticZenRule automaticZenRule)
+                throws RemoteException {
+            Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
+            Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
+            Preconditions.checkNotNull(automaticZenRule.getOwner(), "Owner is null");
+            Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
+            enforcePolicyAccess(Binder.getCallingUid(), "addOrUpdateZenModeRule");
+
+            return mZenModeHelper.addOrUpdateAutomaticZenRule(automaticZenRule,
+                    "addOrUpdateAutomaticZenRule");
+        }
+
+        @Override
+        public boolean renameAutomaticZenRule(String oldName, String newName) {
+            Preconditions.checkNotNull(oldName, "oldName is null");
+            Preconditions.checkNotNull(newName, "newName is null");
+            enforcePolicyAccess(Binder.getCallingUid(), "renameAutomaticZenRule");
+
+            return mZenModeHelper.renameAutomaticZenRule(
+                    oldName, newName, "renameAutomaticZenRule");
+        }
+
+        @Override
+        public boolean removeAutomaticZenRule(String name) throws RemoteException {
+            Preconditions.checkNotNull(name, "Name is null");
+            // Verify that they can modify zen rules.
+            enforcePolicyAccess(Binder.getCallingUid(), "removeAutomaticZenRule");
+
+            return mZenModeHelper.removeAutomaticZenRule(name, "removeAutomaticZenRule");
+        }
+
+        @Override
         public void setInterruptionFilter(String pkg, int filter) throws RemoteException {
             enforcePolicyAccess(pkg, "setInterruptionFilter");
             final int zen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
@@ -1641,6 +1687,25 @@
                     message);
         }
 
+        private void enforcePolicyAccess(int uid, String method) {
+            if (PackageManager.PERMISSION_GRANTED == getContext().checkCallingPermission(
+                    android.Manifest.permission.MANAGE_NOTIFICATIONS)) {
+                return;
+            }
+            boolean accessAllowed = false;
+            String[] packages = getContext().getPackageManager().getPackagesForUid(uid);
+            final int packageCount = packages.length;
+            for (int i = 0; i < packageCount; i++) {
+                if (checkPolicyAccess(packages[i])) {
+                    accessAllowed = true;
+                }
+            }
+            if (!accessAllowed) {
+                Slog.w(TAG, "Notification policy access denied calling " + method);
+                throw new SecurityException("Notification policy access denied");
+            }
+        }
+
         private void enforcePolicyAccess(String pkg, String method) {
             if (PackageManager.PERMISSION_GRANTED == getContext().checkCallingPermission(
                     android.Manifest.permission.MANAGE_NOTIFICATIONS)) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 9131e5e..4d41e3a 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -21,11 +21,13 @@
 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
 
 import android.app.AppOpsManager;
+import android.app.AutomaticZenRule;
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
@@ -34,6 +36,7 @@
 import android.media.AudioSystem;
 import android.media.VolumePolicy;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -62,6 +65,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -196,6 +200,121 @@
         return mZenMode;
     }
 
+    public List<AutomaticZenRule> getAutomaticZenRules() {
+        List<AutomaticZenRule> rules = new ArrayList<>();
+        if (mConfig == null) return rules;
+        for(ZenRule rule : mConfig.automaticRules.values()) {
+            if (canManageAutomaticZenRule(rule)) {
+                rules.add(createAutomaticZenRule(rule));
+            }
+        }
+        return rules;
+    }
+
+    public AutomaticZenRule getAutomaticZenRule(String name) {
+        if (mConfig == null) return null;
+        for(ZenRule rule : mConfig.automaticRules.values()) {
+            if (canManageAutomaticZenRule(rule) && rule.name.equals(name)) {
+                return createAutomaticZenRule(rule);
+            }
+        }
+        return null;
+    }
+
+    public boolean addOrUpdateAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
+        if (mConfig == null) return false;
+        if (DEBUG) {
+            Log.d(TAG, "addOrUpdateAutomaticZenRule zenRule=" + automaticZenRule
+                    + " reason=" + reason);
+        }
+        final ZenModeConfig newConfig = mConfig.copy();
+        String ruleId = findMatchingRuleId(newConfig, automaticZenRule.getName());
+        ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+        if (ruleId == null) {
+            ruleId = newConfig.newRuleId();
+            rule.name = automaticZenRule.getName();
+            rule.component = automaticZenRule.getOwner();
+        } else {
+            rule = newConfig.automaticRules.get(ruleId);
+            if (!canManageAutomaticZenRule(rule)) {
+                throw new SecurityException(
+                        "Cannot update rules not owned by your condition provider");
+            }
+        }
+        if (rule.enabled != automaticZenRule.isEnabled()) {
+            rule.snoozing = false;
+        }
+        rule.condition = null;
+        rule.conditionId = automaticZenRule.getConditionId();
+        rule.enabled = automaticZenRule.isEnabled();
+        rule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
+                automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF);
+        newConfig.automaticRules.put(ruleId, rule);
+        return setConfig(newConfig, reason, true);
+    }
+
+    public boolean renameAutomaticZenRule(String oldName, String newName, String reason) {
+        if (mConfig == null) return false;
+        if (DEBUG) {
+            Log.d(TAG, "renameAutomaticZenRule oldName=" + oldName + "  newName=" + newName
+                    + " reason=" + reason);
+        }
+        final ZenModeConfig newConfig = mConfig.copy();
+        String ruleId = findMatchingRuleId(newConfig, oldName);
+        if (ruleId == null) {
+            return false;
+        } else {
+            ZenRule rule = newConfig.automaticRules.get(ruleId);
+            if (!canManageAutomaticZenRule(rule)) {
+                throw new SecurityException(
+                        "Cannot update rules not owned by your condition provider");
+            }
+            rule.name = newName;
+            return setConfig(newConfig, reason, true);
+        }
+    }
+
+    public boolean removeAutomaticZenRule(String name, String reason) {
+        if (mConfig == null) return false;
+        final ZenModeConfig newConfig = mConfig.copy();
+        String ruleId = findMatchingRuleId(newConfig, name);
+        if (ruleId != null) {
+            ZenRule rule = newConfig.automaticRules.get(ruleId);
+            if (canManageAutomaticZenRule(rule)) {
+                newConfig.automaticRules.remove(ruleId);
+                if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + name + " reason=" + reason);
+            } else {
+                throw new SecurityException(
+                        "Cannot delete rules not owned by your condition provider");
+            }
+        }
+        return setConfig(newConfig, reason, true);
+    }
+
+    public boolean canManageAutomaticZenRule(ZenRule rule) {
+        if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
+                == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        } else {
+            String[] packages = mContext.getPackageManager().getPackagesForUid(
+                    Binder.getCallingUid());
+            if (packages != null) {
+                final int packageCount = packages.length;
+                for (int i = 0; i < packageCount; i++) {
+                    if (packages[i].equals(rule.component.getPackageName())) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
+    private AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
+        return new AutomaticZenRule(rule.name, rule.component, rule.conditionId,
+                NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled);
+    }
+
     public void setManualZenMode(int zenMode, Uri conditionId, String reason) {
         setManualZenMode(zenMode, conditionId, reason, true /*setRingerMode*/);
     }
@@ -225,6 +344,15 @@
         setConfig(newConfig, reason, setRingerMode);
     }
 
+    private String findMatchingRuleId(ZenModeConfig config, String ruleName) {
+        for (String ruleId : config.automaticRules.keySet()) {
+            if (config.automaticRules.get(ruleId).name.equals(ruleName)) {
+                return ruleId;
+            }
+        }
+        return null;
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("mZenMode=");
         pw.println(Global.zenModeToString(mZenMode));
@@ -272,7 +400,7 @@
                 }
                 config.manualRule = null;  // don't restore the manual rule
                 if (config.automaticRules != null) {
-                    for (ZenModeConfig.ZenRule automaticRule : config.automaticRules.values()) {
+                    for (ZenRule automaticRule : config.automaticRules.values()) {
                         // don't restore transient state from restored automatic rules
                         automaticRule.snoozing = false;
                         automaticRule.condition = null;
@@ -319,36 +447,41 @@
     }
 
     private boolean setConfig(ZenModeConfig config, String reason, boolean setRingerMode) {
-        if (config == null || !config.isValid()) {
-            Log.w(TAG, "Invalid config in setConfig; " + config);
-            return false;
-        }
-        if (config.user != mUser) {
-            // simply store away for background users
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            if (config == null || !config.isValid()) {
+                Log.w(TAG, "Invalid config in setConfig; " + config);
+                return false;
+            }
+            if (config.user != mUser) {
+                // simply store away for background users
+                mConfigs.put(config.user, config);
+                if (DEBUG) Log.d(TAG, "setConfig: store config for user " + config.user);
+                return true;
+            }
+            mConditions.evaluateConfig(config, false /*processSubscriptions*/);  // may modify config
             mConfigs.put(config.user, config);
-            if (DEBUG) Log.d(TAG, "setConfig: store config for user " + config.user);
+            if (DEBUG) Log.d(TAG, "setConfig reason=" + reason, new Throwable());
+            ZenLog.traceConfig(reason, mConfig, config);
+            final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
+                    getNotificationPolicy(config));
+            mConfig = config;
+            if (config.equals(mConfig)) {
+                dispatchOnConfigChanged();
+            }
+            if (policyChanged){
+                dispatchOnPolicyChanged();
+            }
+            final String val = Integer.toString(mConfig.hashCode());
+            Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
+            if (!evaluateZenMode(reason, setRingerMode)) {
+                applyRestrictions();  // evaluateZenMode will also apply restrictions if changed
+            }
+            mConditions.evaluateConfig(config, true /*processSubscriptions*/);
             return true;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
-        mConditions.evaluateConfig(config, false /*processSubscriptions*/);  // may modify config
-        mConfigs.put(config.user, config);
-        if (DEBUG) Log.d(TAG, "setConfig reason=" + reason, new Throwable());
-        ZenLog.traceConfig(reason, mConfig, config);
-        final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
-                getNotificationPolicy(config));
-        mConfig = config;
-        if (config.equals(mConfig)) {
-            dispatchOnConfigChanged();
-        }
-        if (policyChanged){
-            dispatchOnPolicyChanged();
-        }
-        final String val = Integer.toString(mConfig.hashCode());
-        Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
-        if (!evaluateZenMode(reason, setRingerMode)) {
-            applyRestrictions();  // evaluateZenMode will also apply restrictions if changed
-        }
-        mConditions.evaluateConfig(config, true /*processSubscriptions*/);
-        return true;
     }
 
     private int getZenModeSetting() {
@@ -506,6 +639,7 @@
                 .getString(R.string.zen_mode_default_weeknights_name);
         rule1.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
         rule1.zenMode = Global.ZEN_MODE_ALARMS;
+        rule1.component = ScheduleConditionProvider.COMPONENT;
         config.automaticRules.put(config.newRuleId(), rule1);
 
         final ScheduleInfo weekends = new ScheduleInfo();
@@ -519,6 +653,7 @@
                 .getString(R.string.zen_mode_default_weekends_name);
         rule2.conditionId = ZenModeConfig.toScheduleConditionId(weekends);
         rule2.zenMode = Global.ZEN_MODE_ALARMS;
+        rule2.component = ScheduleConditionProvider.COMPONENT;
         config.automaticRules.put(config.newRuleId(), rule2);
     }
 
@@ -533,6 +668,7 @@
         rule.name = mContext.getResources().getString(R.string.zen_mode_default_events_name);
         rule.conditionId = ZenModeConfig.toEventConditionId(events);
         rule.zenMode = Global.ZEN_MODE_ALARMS;
+        rule.component = EventConditionProvider.COMPONENT;
         config.automaticRules.put(config.newRuleId(), rule);
     }
 
@@ -573,6 +709,7 @@
                 rule.conditionId = ZenModeConfig.toScheduleConditionId(schedule);
                 rule.zenMode = v1.sleepNone ? Global.ZEN_MODE_NO_INTERRUPTIONS
                         : Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+                rule.component = ScheduleConditionProvider.COMPONENT;
                 rt.automaticRules.put(rt.newRuleId(), rule);
             } else {
                 Log.i(TAG, "No existing V1 downtime found, generating default schedules");
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 0366fff..cf09b84 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -140,6 +140,7 @@
     private static final String ATTR_APP_ICON = "appIcon";
     private static final String ATTR_APP_LABEL = "appLabel";
     private static final String ATTR_ORIGINATING_URI = "originatingUri";
+    private static final String ATTR_ORIGINATING_UID = "originatingUid";
     private static final String ATTR_REFERRER_URI = "referrerUri";
     private static final String ATTR_ABI_OVERRIDE = "abiOverride";
     private static final String ATTR_VOLUME_UUID = "volumeUuid";
@@ -405,6 +406,8 @@
         params.appIcon = readBitmapAttribute(in, ATTR_APP_ICON);
         params.appLabel = readStringAttribute(in, ATTR_APP_LABEL);
         params.originatingUri = readUriAttribute(in, ATTR_ORIGINATING_URI);
+        params.originatingUid =
+                readIntAttribute(in, ATTR_ORIGINATING_UID, SessionParams.UID_UNKNOWN);
         params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI);
         params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE);
         params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
@@ -477,6 +480,7 @@
         writeStringAttribute(out, ATTR_APP_PACKAGE_NAME, params.appPackageName);
         writeStringAttribute(out, ATTR_APP_LABEL, params.appLabel);
         writeUriAttribute(out, ATTR_ORIGINATING_URI, params.originatingUri);
+        writeIntAttribute(out, ATTR_ORIGINATING_UID, params.originatingUid);
         writeUriAttribute(out, ATTR_REFERRER_URI, params.referrerUri);
         writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride);
         writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 4a473fd..a441cb2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -222,11 +222,17 @@
         // waived if the installer is the device owner.
         DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
+        final boolean isPermissionGranted =
+                (mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES, installerUid)
+                        == PackageManager.PERMISSION_GRANTED);
+        final boolean isInstallerRoot = (installerUid == Process.ROOT_UID);
+        final boolean forcePermissionPrompt =
+                (params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0;
         mIsInstallerDeviceOwner = (dpm != null) && dpm.isDeviceOwnerApp(installerPackageName);
-        if ((mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES, installerUid)
-                == PackageManager.PERMISSION_GRANTED)
-                || (installerUid == Process.ROOT_UID)
-                || mIsInstallerDeviceOwner) {
+        if ((isPermissionGranted
+                        || isInstallerRoot
+                        || mIsInstallerDeviceOwner)
+                && !forcePermissionPrompt) {
             mPermissionsAccepted = true;
         } else {
             mPermissionsAccepted = false;
@@ -955,7 +961,9 @@
 
         if (accepted) {
             // Mark and kick off another install pass
-            mPermissionsAccepted = true;
+            synchronized (mLock) {
+                mPermissionsAccepted = true;
+            }
             mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
         } else {
             destroyInternal();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c729e28..2009ccf 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9686,7 +9686,8 @@
             IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
             String installerPackageName, int installerUid, UserHandle user) {
         final VerificationParams verifParams = new VerificationParams(
-                null, sessionParams.originatingUri, sessionParams.referrerUri, installerUid, null);
+                null, sessionParams.originatingUri, sessionParams.referrerUri,
+                sessionParams.originatingUid, null);
         verifParams.setInstallerUid(installerUid);
 
         final OriginInfo origin;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index de106a1..6386a916 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerNative;
 import android.app.IStopUserCallback;
 import android.app.admin.DevicePolicyManager;
@@ -64,7 +65,7 @@
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
-import com.android.server.accounts.AccountManagerService;
+import com.android.server.LocalServices;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -242,13 +243,15 @@
             synchronized (mPackagesLock) {
                 // Prune out any partially created/partially removed users.
                 ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
-                for (int i = 0; i < mUsers.size(); i++) {
+                final int userSize = mUsers.size();
+                for (int i = 0; i < userSize; i++) {
                     UserInfo ui = mUsers.valueAt(i);
                     if ((ui.partial || ui.guestToRemove) && i != 0) {
                         partials.add(ui);
                     }
                 }
-                for (int i = 0; i < partials.size(); i++) {
+                final int partialsSize = partials.size();
+                for (int i = 0; i < partialsSize; i++) {
                     UserInfo ui = partials.get(i);
                     Slog.w(LOG_TAG, "Removing partially created user " + ui.id
                             + " (name=" + ui.name + ")");
@@ -272,7 +275,8 @@
     public UserInfo getPrimaryUser() {
         checkManageUsersPermission("query users");
         synchronized (mPackagesLock) {
-            for (int i = 0; i < mUsers.size(); i++) {
+            final int userSize = mUsers.size();
+            for (int i = 0; i < userSize; i++) {
                 UserInfo ui = mUsers.valueAt(i);
                 if (ui.isPrimary()) {
                     return ui;
@@ -287,7 +291,8 @@
         checkManageUsersPermission("query users");
         synchronized (mPackagesLock) {
             ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
-            for (int i = 0; i < mUsers.size(); i++) {
+            final int userSize = mUsers.size();
+            for (int i = 0; i < userSize; i++) {
                 UserInfo ui = mUsers.valueAt(i);
                 if (ui.partial) {
                     continue;
@@ -323,7 +328,8 @@
             // Probably a dying user
             return users;
         }
-        for (int i = 0; i < mUsers.size(); i++) {
+        final int userSize = mUsers.size();
+        for (int i = 0; i < userSize; i++) {
             UserInfo profile = mUsers.valueAt(i);
             if (!isProfileOf(user, profile)) {
                 continue;
@@ -1010,7 +1016,8 @@
             serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
             writeRestrictionsLocked(serializer, mGuestRestrictions);
             serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
-            for (int i = 0; i < mUsers.size(); i++) {
+            final int userSize = mUsers.size();
+            for (int i = 0; i < userSize; i++) {
                 UserInfo user = mUsers.valueAt(i);
                 serializer.startTag(null, TAG_USER);
                 serializer.attribute(null, ATTR_ID, Integer.toString(user.id));
@@ -1587,6 +1594,9 @@
                             }
                             new Thread() {
                                 public void run() {
+                                    // Clean up any ActivityManager state
+                                    LocalServices.getService(ActivityManagerInternal.class)
+                                            .onUserRemoved(userHandle);
                                     synchronized (mInstallLock) {
                                         synchronized (mPackagesLock) {
                                             removeUserStateLocked(userHandle);
@@ -1951,14 +1961,15 @@
      */
     private void updateUserIdsLocked() {
         int num = 0;
-        for (int i = 0; i < mUsers.size(); i++) {
+        final int userSize = mUsers.size();
+        for (int i = 0; i < userSize; i++) {
             if (!mUsers.valueAt(i).partial) {
                 num++;
             }
         }
         final int[] newUsers = new int[num];
         int n = 0;
-        for (int i = 0; i < mUsers.size(); i++) {
+        for (int i = 0; i < userSize; i++) {
             if (!mUsers.valueAt(i).partial) {
                 newUsers[n++] = mUsers.keyAt(i);
             }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index dbc3970..c265000 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2105,6 +2105,8 @@
         case TYPE_WALLPAPER:
             // wallpaper is at the bottom, though the window manager may move it.
             return 2;
+        case TYPE_DOCK_DIVIDER:
+            return 2;
         case TYPE_PHONE:
             return 3;
         case TYPE_SEARCH_BAR:
@@ -2135,56 +2137,54 @@
         case TYPE_INPUT_METHOD_DIALOG:
             // on-screen keyboards and other such input method user interfaces go here.
             return 13;
-        case TYPE_DOCK_DIVIDER:
-            return 14;
         case TYPE_KEYGUARD_SCRIM:
             // the safety window that shows behind keyguard while keyguard is starting
-            return 15;
+            return 14;
         case TYPE_STATUS_BAR_SUB_PANEL:
-            return 16;
+            return 15;
         case TYPE_STATUS_BAR:
-            return 17;
+            return 16;
         case TYPE_STATUS_BAR_PANEL:
-            return 18;
+            return 17;
         case TYPE_KEYGUARD_DIALOG:
-            return 19;
+            return 18;
         case TYPE_VOLUME_OVERLAY:
             // the on-screen volume indicator and controller shown when the user
             // changes the device volume
-            return 20;
+            return 19;
         case TYPE_SYSTEM_OVERLAY:
             // the on-screen volume indicator and controller shown when the user
             // changes the device volume
-            return 21;
+            return 20;
         case TYPE_NAVIGATION_BAR:
             // the navigation bar, if available, shows atop most things
-            return 22;
+            return 21;
         case TYPE_NAVIGATION_BAR_PANEL:
             // some panels (e.g. search) need to show on top of the navigation bar
-            return 23;
+            return 22;
         case TYPE_SYSTEM_ERROR:
             // system-level error dialogs
-            return 24;
+            return 23;
         case TYPE_MAGNIFICATION_OVERLAY:
             // used to highlight the magnified portion of a display
-            return 25;
+            return 24;
         case TYPE_DISPLAY_OVERLAY:
             // used to simulate secondary display devices
-            return 26;
+            return 25;
         case TYPE_DRAG:
             // the drag layer: input for drag-and-drop is associated with this window,
             // which sits above all other focusable windows
-            return 27;
+            return 26;
         case TYPE_ACCESSIBILITY_OVERLAY:
             // overlay put by accessibility services to intercept user interaction
-            return 28;
+            return 27;
         case TYPE_SECURE_SYSTEM_OVERLAY:
-            return 29;
+            return 28;
         case TYPE_BOOT_PROGRESS:
-            return 30;
+            return 29;
         case TYPE_POINTER:
             // the (mouse) pointer layer
-            return 31;
+            return 30;
         }
         Log.e(TAG, "Unknown window type: " + type);
         return 2;
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index a64cda6..cc51d20 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -1032,6 +1032,7 @@
                 0, top - containingFrame.top, 0);
         set.addAnimation(translate);
         set.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+        set.setZAdjustment(Animation.ZORDER_TOP);
         return set;
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d6d77e9..745874c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -126,6 +126,7 @@
         display.getMetrics(mDisplayMetrics);
         isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
         mService = service;
+        initializeDisplayBaseInfo();
         mDividerControllerLocked = new DockedStackDividerController(service.mContext, this);
     }
 
@@ -192,6 +193,21 @@
         }
     }
 
+    void initializeDisplayBaseInfo() {
+        synchronized(mDisplaySizeLock) {
+            // Bootstrap the default logical display from the display manager.
+            final DisplayInfo newDisplayInfo =
+                    mService.mDisplayManagerInternal.getDisplayInfo(mDisplayId);
+            if (newDisplayInfo != null) {
+                mDisplayInfo.copyFrom(newDisplayInfo);
+            }
+            mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
+            mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
+            mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
+            mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
+        }
+    }
+
     void getLogicalDisplayRect(Rect out) {
         // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
         final int orientation = mDisplayInfo.rotation;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 80bec3e6..74572cf 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -222,6 +222,7 @@
     static final boolean HIDE_STACK_CRAWLS = true;
     static final int LAYOUT_REPEAT_THRESHOLD = 4;
 
+
     static final boolean PROFILE_ORIENTATION = false;
     static final boolean localLOGV = DEBUG;
 
@@ -4399,7 +4400,6 @@
         mInputMonitor.setUpdateInputWindowsNeededLw();
         mWindowPlacerLocked.performSurfacePlacement();
         mInputMonitor.updateInputWindowsLw(false /*force*/);
-
         //dump();
     }
 
@@ -4484,10 +4484,6 @@
                     }
                     stack.attachDisplayContent(displayContent);
                     displayContent.attachStack(stack, onTop);
-                    if (stack.mStackId == DOCKED_STACK_ID) {
-                        mH.obtainMessage(H.UPDATE_DOCKED_STACK_DIVIDER,
-                                displayContent).sendToTarget();
-                    }
                     moveStackWindowsLocked(displayContent);
                     final WindowList windows = displayContent.getWindowList();
                     for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
@@ -4510,11 +4506,6 @@
     void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
         displayContent.detachStack(stack);
         stack.detachDisplay();
-        // We can't directly remove the divider, because only the WM thread can do these operations
-        // and we can be on AM thread.
-        if (stack.mStackId == DOCKED_STACK_ID) {
-            mH.obtainMessage(H.UPDATE_DOCKED_STACK_DIVIDER, displayContent).sendToTarget();
-        }
     }
 
     public void detachStack(int stackId) {
@@ -7107,22 +7098,7 @@
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
             if (displayContent != null) {
                 mAnimator.addDisplayLocked(displayId);
-                synchronized(displayContent.mDisplaySizeLock) {
-                    // Bootstrap the default logical display from the display manager.
-                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-                    DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
-                    if (newDisplayInfo != null) {
-                        displayInfo.copyFrom(newDisplayInfo);
-                    }
-                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
-                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
-                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
-                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
-                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
-                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
-                    displayContent.mBaseDisplayRect.set(0, 0,
-                            displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
-                }
+                displayContent.initializeDisplayBaseInfo();
             }
         }
     }
@@ -8361,6 +8337,13 @@
             } else if (wtoken != null) {
                 winAnimator.mAnimLayer =
                         w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
+                if (wtoken.mReplacingWindow && wtoken.mAnimateReplacingWindow) {
+                    // We know that we will be animating a relaunching window in the near future,
+                    // which will receive a z-order increase. We want the replaced window to
+                    // immediately receive the same treatment, e.g. to be above the dock divider.
+                    w.mLayer += TYPE_LAYER_OFFSET;
+                    winAnimator.mAnimLayer += TYPE_LAYER_OFFSET;
+                }
             } else {
                 winAnimator.mAnimLayer = w.mLayer;
             }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0b9f2c6..60bf571 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static com.android.server.wm.WindowManagerService.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerService.DEBUG_LAYERS;
@@ -868,14 +869,18 @@
                 mSurfaceW = width;
                 mSurfaceH = height;
 
-                final boolean isHwAccelerated = (attrs.flags &
-                        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
+                final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
                 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
                 if (!PixelFormat.formatHasAlpha(attrs.format)
+                        // Don't make surface with surfaceInsets opaque as they display a
+                        // translucent shadow.
                         && attrs.surfaceInsets.left == 0
                         && attrs.surfaceInsets.top == 0
                         && attrs.surfaceInsets.right == 0
-                        && attrs.surfaceInsets.bottom  == 0) {
+                        && attrs.surfaceInsets.bottom == 0
+                        // Don't make surface opaque when resizing to reduce the amount of
+                        // artifacts shown in areas the app isn't drawing content to.
+                        && !w.isDragResizing()) {
                     flags |= SurfaceControl.OPAQUE;
                 }
 
@@ -1400,7 +1405,11 @@
 
     private void adjustCropToStackBounds(WindowState w, Rect clipRect) {
         final AppWindowToken appToken = w.mAppToken;
-        if (appToken != null && appToken.mCropWindowsToStack) {
+        // We don't apply the the stack bounds to the window that is being replaced, because it was
+        // living in a different stack. If we suddenly crop it to the new stack bounds, it might
+        // get cut off. We don't want it to happen, so we let it ignore the stack bounds until it
+        // gets removed. The window that will replace it will abide them.
+        if (appToken != null && appToken.mCropWindowsToStack && !appToken.mReplacingWindow) {
             TaskStack stack = w.getTask().mStack;
             stack.getBounds(mTmpStackBounds);
             final int surfaceX = (int) mSurfaceX;
@@ -1713,8 +1722,7 @@
             return false;
         }
         final LayoutParams attrs = mWin.getAttrs();
-        final boolean isHwAccelerated = (attrs.flags &
-                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
+        final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
         final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
         if (format == mSurfaceFormat) {
             setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format));
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index d86a8af..df0a1c9 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -967,6 +967,7 @@
         }
 
         mService.mPolicy.finishLayoutLw();
+        mService.mH.obtainMessage(UPDATE_DOCKED_STACK_DIVIDER, displayContent).sendToTarget();
     }
 
     /**
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index 982bae0..53f55cd 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -423,7 +423,7 @@
                 try {
                     byteBuffer = recvKernelReply();
                 } catch (ErrnoException e) {
-                    Log.w(TAG, "ErrnoException: ", e);
+                    if (stillRunning()) { Log.w(TAG, "ErrnoException: ", e); }
                     break;
                 }
                 final long whenMs = SystemClock.elapsedRealtime();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java
index 3d2a238..71e7fd2 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java
@@ -176,8 +176,7 @@
         if (mPeeked) {
             if (mAttributes == null) {
                 if (mEventType != START_TAG) {
-                    throw new IndexOutOfBoundsException("getAttributeValue() called when not at " +
-                            "START_TAG.");
+                    throw new IndexOutOfBoundsException("getAttributeValue() called when not at START_TAG.");
                 } else {
                     return null;
                 }