Merge "System to track touch and sensor events before unlocking the phone"
diff --git a/Android.mk b/Android.mk
index 769a555..40da134 100644
--- a/Android.mk
+++ b/Android.mk
@@ -90,6 +90,7 @@
 	core/java/android/app/IWallpaperManager.aidl \
 	core/java/android/app/IWallpaperManagerCallback.aidl \
 	core/java/android/app/admin/IDevicePolicyManager.aidl \
+	core/java/android/app/trust/IStrongAuthTracker.aidl \
 	core/java/android/app/trust/ITrustManager.aidl \
 	core/java/android/app/trust/ITrustListener.aidl \
 	core/java/android/app/backup/IBackupManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 3e1f5a5..b1e80dd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8881,6 +8881,7 @@
     field public int configChanges;
     field public int documentLaunchMode;
     field public int flags;
+    field public android.content.pm.ActivityInfo.InitialLayout initialLayout;
     field public int launchMode;
     field public int maxRecents;
     field public java.lang.String parentActivityName;
@@ -8894,6 +8895,15 @@
     field public int uiOptions;
   }
 
+  public static final class ActivityInfo.InitialLayout {
+    ctor public ActivityInfo.InitialLayout(int, float, int, float, int);
+    field public final int gravity;
+    field public final int height;
+    field public final float heightFraction;
+    field public final int width;
+    field public final float widthFraction;
+  }
+
   public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
     ctor public ApplicationInfo();
     ctor public ApplicationInfo(android.content.pm.ApplicationInfo);
@@ -18136,7 +18146,7 @@
     method public final int getThumbPixWidth();
   }
 
-  public class MtpObjectInfo.Builder {
+  public static class MtpObjectInfo.Builder {
     ctor public MtpObjectInfo.Builder();
     ctor public MtpObjectInfo.Builder(android.mtp.MtpObjectInfo);
     method public android.mtp.MtpObjectInfo build();
@@ -32512,7 +32522,7 @@
     method public static int getLayoutDirectionFromLocale(java.util.Locale);
     method public static int getOffsetAfter(java.lang.CharSequence, int);
     method public static int getOffsetBefore(java.lang.CharSequence, int);
-    method public static java.lang.CharSequence getReverse(java.lang.CharSequence, int, int);
+    method public static deprecated java.lang.CharSequence getReverse(java.lang.CharSequence, int, int);
     method public static int getTrimmedLength(java.lang.CharSequence);
     method public static java.lang.String htmlEncode(java.lang.String);
     method public static int indexOf(java.lang.CharSequence, char);
@@ -34141,6 +34151,15 @@
     field public static final int RTL = 1; // 0x1
   }
 
+  public final class LocaleList {
+    ctor public LocaleList();
+    ctor public LocaleList(java.util.Locale[]);
+    method public java.util.Locale get(int);
+    method public java.util.Locale getPrimary();
+    method public boolean isEmpty();
+    method public int size();
+  }
+
   public final class Log {
     method public static int d(java.lang.String, java.lang.String);
     method public static int d(java.lang.String, java.lang.String, java.lang.Throwable);
diff --git a/api/system-current.txt b/api/system-current.txt
index 984d395..fe7c6da 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9139,6 +9139,7 @@
     field public int configChanges;
     field public int documentLaunchMode;
     field public int flags;
+    field public android.content.pm.ActivityInfo.InitialLayout initialLayout;
     field public int launchMode;
     field public int maxRecents;
     field public java.lang.String parentActivityName;
@@ -9152,6 +9153,15 @@
     field public int uiOptions;
   }
 
+  public static final class ActivityInfo.InitialLayout {
+    ctor public ActivityInfo.InitialLayout(int, float, int, float, int);
+    field public final int gravity;
+    field public final int height;
+    field public final float heightFraction;
+    field public final int width;
+    field public final float widthFraction;
+  }
+
   public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
     ctor public ApplicationInfo();
     ctor public ApplicationInfo(android.content.pm.ApplicationInfo);
@@ -19649,7 +19659,7 @@
     method public final int getThumbPixWidth();
   }
 
-  public class MtpObjectInfo.Builder {
+  public static class MtpObjectInfo.Builder {
     ctor public MtpObjectInfo.Builder();
     ctor public MtpObjectInfo.Builder(android.mtp.MtpObjectInfo);
     method public android.mtp.MtpObjectInfo build();
@@ -34845,7 +34855,7 @@
     method public static int getLayoutDirectionFromLocale(java.util.Locale);
     method public static int getOffsetAfter(java.lang.CharSequence, int);
     method public static int getOffsetBefore(java.lang.CharSequence, int);
-    method public static java.lang.CharSequence getReverse(java.lang.CharSequence, int, int);
+    method public static deprecated java.lang.CharSequence getReverse(java.lang.CharSequence, int, int);
     method public static int getTrimmedLength(java.lang.CharSequence);
     method public static java.lang.String htmlEncode(java.lang.String);
     method public static int indexOf(java.lang.CharSequence, char);
@@ -36474,6 +36484,15 @@
     field public static final int RTL = 1; // 0x1
   }
 
+  public final class LocaleList {
+    ctor public LocaleList();
+    ctor public LocaleList(java.util.Locale[]);
+    method public java.util.Locale get(int);
+    method public java.util.Locale getPrimary();
+    method public boolean isEmpty();
+    method public int size();
+  }
+
   public final class Log {
     method public static int d(java.lang.String, java.lang.String);
     method public static int d(java.lang.String, java.lang.String, java.lang.Throwable);
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 2ee586f..7c8842c 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -27,6 +27,8 @@
 
 LOCAL_MODULE:= bootanimation
 
+LOCAL_INIT_RC := bootanim.rc
+
 ifdef TARGET_32_BIT_SURFACEFLINGER
 LOCAL_32_BIT_ONLY := true
 endif
diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc
new file mode 100644
index 0000000..ee0d0b8
--- /dev/null
+++ b/cmds/bootanimation/bootanim.rc
@@ -0,0 +1,6 @@
+service bootanim /system/bin/bootanimation
+    class core
+    user graphics
+    group graphics audio
+    disabled
+    oneshot
diff --git a/core/java/android/app/trust/IStrongAuthTracker.aidl b/core/java/android/app/trust/IStrongAuthTracker.aidl
new file mode 100644
index 0000000..36c71bf
--- /dev/null
+++ b/core/java/android/app/trust/IStrongAuthTracker.aidl
@@ -0,0 +1,26 @@
+/*
+**
+** Copyright 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.trust;
+
+/**
+ * Private API to be notified about strong auth changes
+ *
+ * {@hide}
+ */
+oneway interface IStrongAuthTracker {
+    void onStrongAuthRequiredChanged(int strongAuthRequired, int userId);
+}
\ No newline at end of file
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index 32951d9..2dea545 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -26,11 +26,9 @@
 interface ITrustManager {
     void reportUnlockAttempt(boolean successful, int userId);
     void reportEnabledTrustAgentsChanged(int userId);
-    void reportRequireCredentialEntry(int userId);
     void registerTrustListener(in ITrustListener trustListener);
     void unregisterTrustListener(in ITrustListener trustListener);
     void reportKeyguardShowingChanged();
     boolean isDeviceLocked(int userId);
     boolean isDeviceSecure(int userId);
-    boolean hasUserAuthenticatedSinceBoot(int userId);
 }
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 8cab565..aff69f0 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -16,13 +16,19 @@
 
 package android.app.trust;
 
+import android.annotation.IntDef;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.SparseIntArray;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * See {@link com.android.server.trust.TrustManagerService}
@@ -73,21 +79,6 @@
     }
 
     /**
-     * Reports that trust is disabled until credentials have been entered for user {@param userId}.
-     *
-     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
-     *
-     * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
-     */
-    public void reportRequireCredentialEntry(int userId) {
-        try {
-            mService.reportRequireCredentialEntry(userId);
-        } catch (RemoteException e) {
-            onError(e);
-        }
-    }
-
-    /**
      * Reports that the visibility of the keyguard has changed.
      *
      * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
@@ -147,23 +138,6 @@
         }
     }
 
-    /**
-     * Checks whether the specified user has been authenticated since the last boot.
-     *
-     * @param userId the user id of the user to check for
-     * @return true if the user has authenticated since boot, false otherwise
-     *
-     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
-     */
-    public boolean hasUserAuthenticatedSinceBoot(int userId) {
-        try {
-            return mService.hasUserAuthenticatedSinceBoot(userId);
-        } catch (RemoteException e) {
-            onError(e);
-            return false;
-        }
-    }
-
     private void onError(Exception e) {
         Log.e(TAG, "Error while calling TrustManagerService", e);
     }
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 1f3ff51..2d825fa 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -64,9 +64,7 @@
  * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
  * adapter, when running on JELLY_BEAN_MR1 and below, call the
  * static {@link #getDefaultAdapter} method; when running on JELLY_BEAN_MR2 and
- * higher, retrieve it through
- * {@link android.content.Context#getSystemService} with
- * {@link android.content.Context#BLUETOOTH_SERVICE}.
+ * higher, call {@link BluetoothManager#getAdapter}.
  * Fundamentally, this is your starting point for all
  * Bluetooth actions. Once you have the local adapter, you can get a set of
  * {@link BluetoothDevice} objects representing all paired devices with
diff --git a/core/java/android/content/RestrictionEntry.java b/core/java/android/content/RestrictionEntry.java
index ab049ec..0473475 100644
--- a/core/java/android/content/RestrictionEntry.java
+++ b/core/java/android/content/RestrictionEntry.java
@@ -456,7 +456,7 @@
         if (o == this) return true;
         if (!(o instanceof RestrictionEntry)) return false;
         final RestrictionEntry other = (RestrictionEntry) o;
-        if (mType != other.mType || mKey.equals(other.mKey)) {
+        if (mType != other.mType || !mKey.equals(other.mKey)) {
             return false;
         }
         if (mCurrentValues == null && other.mCurrentValues == null
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index 1fac06e..a7744e7 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -677,7 +677,8 @@
      * <table>
      *     <tr><th>RestrictionEntry</th><th>Bundle</th></tr>
      *     <tr><td>{@link RestrictionEntry#TYPE_BOOLEAN}</td><td>{@link Bundle#putBoolean}</td></tr>
-     *     <tr><td>{@link RestrictionEntry#TYPE_CHOICE}, {@link RestrictionEntry#TYPE_CHOICE}</td>
+     *     <tr><td>{@link RestrictionEntry#TYPE_CHOICE},
+     *     {@link RestrictionEntry#TYPE_MULTI_SELECT}</td>
      *     <td>{@link Bundle#putStringArray}</td></tr>
      *     <tr><td>{@link RestrictionEntry#TYPE_INTEGER}</td><td>{@link Bundle#putInt}</td></tr>
      *     <tr><td>{@link RestrictionEntry#TYPE_STRING}</td><td>{@link Bundle#putString}</td></tr>
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 43cc63b..876fbf5 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -698,6 +698,8 @@
      */
     public int lockTaskLaunchMode;
 
+    public InitialLayout initialLayout;
+
     public ActivityInfo() {
     }
 
@@ -763,9 +765,14 @@
         }
         pw.println(prefix + "resizeable=" + resizeable + " lockTaskLaunchMode="
                 + lockTaskLaunchModeToString(lockTaskLaunchMode));
+        if (initialLayout != null) {
+            pw.println(prefix + "initialLayout=" + initialLayout.width + "|"
+                    + initialLayout.widthFraction + ", " + initialLayout.height + "|"
+                    + initialLayout.heightFraction + ", " + initialLayout.gravity);
+        }
         super.dumpBack(pw, prefix);
     }
-    
+
     public String toString() {
         return "ActivityInfo{"
             + Integer.toHexString(System.identityHashCode(this))
@@ -793,6 +800,16 @@
         dest.writeInt(maxRecents);
         dest.writeInt(resizeable ? 1 : 0);
         dest.writeInt(lockTaskLaunchMode);
+        if (initialLayout != null) {
+            dest.writeInt(1);
+            dest.writeInt(initialLayout.width);
+            dest.writeFloat(initialLayout.widthFraction);
+            dest.writeInt(initialLayout.height);
+            dest.writeFloat(initialLayout.heightFraction);
+            dest.writeInt(initialLayout.gravity);
+        } else {
+            dest.writeInt(0);
+        }
     }
 
     public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -822,5 +839,33 @@
         maxRecents = source.readInt();
         resizeable = (source.readInt() == 1);
         lockTaskLaunchMode = source.readInt();
+        if (source.readInt() == 1) {
+            initialLayout = new InitialLayout(source);
+        }
+    }
+
+    public static final class InitialLayout {
+        public InitialLayout(int width, float widthFraction, int height, float heightFraction,
+                int gravity) {
+            this.width = width;
+            this.widthFraction = widthFraction;
+            this.height = height;
+            this.heightFraction = heightFraction;
+            this.gravity = gravity;
+        }
+
+        InitialLayout(Parcel source) {
+            width = source.readInt();
+            widthFraction = source.readFloat();
+            height = source.readInt();
+            heightFraction = source.readFloat();
+            gravity = source.readInt();
+        }
+
+        public final int width;
+        public final float widthFraction;
+        public final int height;
+        public final float heightFraction;
+        public final int gravity;
     }
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 924df1b..6443667 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -50,6 +50,7 @@
 import android.util.Pair;
 import android.util.Slog;
 import android.util.TypedValue;
+import android.view.Gravity;
 
 import com.android.internal.R;
 import com.android.internal.util.ArrayUtils;
@@ -3260,10 +3261,12 @@
                     owner.preferredActivityFilters.add(intent);
                 }
             } else if (parser.getName().equals("meta-data")) {
-                if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
+                if ((a.metaData = parseMetaData(res, parser, attrs, a.metaData,
                         outError)) == null) {
                     return null;
                 }
+            } else if (!receiver && parser.getName().equals("initial-layout")) {
+                parseInitialLayout(res, attrs, a);
             } else {
                 if (!RIGID_PARSER) {
                     Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
@@ -3296,6 +3299,43 @@
         return a;
     }
 
+    private void parseInitialLayout(Resources res, AttributeSet attrs, Activity a) {
+        TypedArray sw = res.obtainAttributes(attrs,
+                com.android.internal.R.styleable.AndroidManifestInitialLayout);
+        int width = -1;
+        float widthFraction = -1f;
+        int height = -1;
+        float heightFraction = -1f;
+        final int widthType = sw.getType(
+                com.android.internal.R.styleable.AndroidManifestInitialLayout_activity_width);
+        if (widthType == TypedValue.TYPE_FRACTION) {
+            widthFraction = sw.getFraction(
+                    com.android.internal.R.styleable.AndroidManifestInitialLayout_activity_width,
+                    1, 1, -1);
+        } else if (widthType == TypedValue.TYPE_DIMENSION) {
+            width = sw.getDimensionPixelSize(
+                    com.android.internal.R.styleable.AndroidManifestInitialLayout_activity_width,
+                    -1);
+        }
+        final int heightType = sw.getType(
+                com.android.internal.R.styleable.AndroidManifestInitialLayout_activity_height);
+        if (heightType == TypedValue.TYPE_FRACTION) {
+            heightFraction = sw.getFraction(
+                    com.android.internal.R.styleable.AndroidManifestInitialLayout_activity_height,
+                    1, 1, -1);
+        } else if (heightType == TypedValue.TYPE_DIMENSION) {
+            height = sw.getDimensionPixelSize(
+                    com.android.internal.R.styleable.AndroidManifestInitialLayout_activity_height,
+                    -1);
+        }
+        int gravity = sw.getInt(
+                com.android.internal.R.styleable.AndroidManifestInitialLayout_gravity,
+                Gravity.CENTER);
+        sw.recycle();
+        a.info.initialLayout = new ActivityInfo.InitialLayout(width, widthFraction,
+                height, heightFraction, gravity);
+    }
+
     private Activity parseActivityAlias(Package owner, Resources res,
             XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
             throws XmlPullParserException, IOException {
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index cbd2f78..dfd0f7d 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -145,6 +145,17 @@
         return (!hideSystemUser || id != UserHandle.USER_SYSTEM) && supportsSwitchTo();
     }
 
+    /* @hide */
+    public boolean canHaveProfile() {
+        if (isManagedProfile() || isGuest() || isRestricted()) {
+            return false;
+        }
+        if (UserManager.isSplitSystemUser()) {
+            return id != UserHandle.USER_SYSTEM;
+        }
+        return id == UserHandle.USER_OWNER;
+    }
+
     public UserInfo() {
     }
 
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 7aa9787..a04cdce 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -19,7 +19,9 @@
 
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.utils.HashCodeHelpers;
+import android.hardware.camera2.utils.SurfaceUtils;
 import android.util.Log;
+import android.util.Size;
 import android.view.Surface;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -66,9 +68,7 @@
      *
      */
     public OutputConfiguration(Surface surface) {
-        checkNotNull(surface, "Surface must not be null");
-        mSurface = surface;
-        mRotation = ROTATION_0;
+        this(surface, ROTATION_0);
     }
 
     /**
@@ -94,6 +94,9 @@
         checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
         mSurface = surface;
         mRotation = rotation;
+        mConfiguredSize = SurfaceUtils.getSurfaceSize(surface);
+        mConfiguredFormat = SurfaceUtils.getSurfaceFormat(surface);
+        mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(surface);
     }
 
     /**
@@ -106,6 +109,9 @@
         checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
         mSurface = surface;
         mRotation = rotation;
+        mConfiguredSize = SurfaceUtils.getSurfaceSize(mSurface);
+        mConfiguredFormat = SurfaceUtils.getSurfaceFormat(mSurface);
+        mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(mSurface);
     }
 
     /**
@@ -163,8 +169,9 @@
     /**
      * Check if this {@link OutputConfiguration} is equal to another {@link OutputConfiguration}.
      *
-     * <p>Two output configurations are only equal if and only if the underlying surface and
-     * all other configuration parameters are equal. </p>
+     * <p>Two output configurations are only equal if and only if the underlying surfaces, surface
+     * properties (width, height, format, dataspace) when the output configurations are created,
+     * and all other configuration parameters are equal. </p>
      *
      * @return {@code true} if the objects were equal, {@code false} otherwise
      */
@@ -176,7 +183,11 @@
             return true;
         } else if (obj instanceof OutputConfiguration) {
             final OutputConfiguration other = (OutputConfiguration) obj;
-            return (mSurface == other.mSurface && mRotation == other.mRotation);
+            return mSurface == other.mSurface &&
+                   mRotation == other.mRotation &&
+                   mConfiguredSize.equals(other.mConfiguredSize) &&
+                   mConfiguredFormat == other.mConfiguredFormat &&
+                   mConfiguredDataspace == other.mConfiguredDataspace;
         }
         return false;
     }
@@ -192,4 +203,9 @@
     private static final String TAG = "OutputConfiguration";
     private final Surface mSurface;
     private final int mRotation;
+
+    // The size, format, and dataspace of the surface when OutputConfiguration is created.
+    private final Size mConfiguredSize;
+    private final int mConfiguredFormat;
+    private final int mConfiguredDataspace;
 }
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 061fad9..7cff11b 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -395,7 +395,7 @@
      * Request authentication of a crypto object. This call warms up the fingerprint hardware
      * and starts scanning for a fingerprint. It terminates when
      * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
-     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at
+     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
      * which point the object is no longer valid. The operation can be canceled by using the
      * provided cancel object.
      *
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index a6d477f..3bd12c0 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -351,8 +351,12 @@
     public void maybeMarkCapabilitiesRestricted() {
         // If all the capabilities are typically provided by restricted networks, conclude that this
         // network is restricted.
-        if ((mNetworkCapabilities & ~(DEFAULT_CAPABILITIES | RESTRICTED_CAPABILITIES)) == 0)
+        if ((mNetworkCapabilities & ~(DEFAULT_CAPABILITIES | RESTRICTED_CAPABILITIES)) == 0 &&
+                // Must have at least some restricted capabilities, otherwise a request for an
+                // internet-less network will get marked restricted.
+                (mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0) {
             removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        }
     }
 
     /**
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 364c0eb..aeb5d45 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -43,7 +43,7 @@
     UserInfo getPrimaryUser();
     List<UserInfo> getUsers(boolean excludeDying);
     List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
-    boolean canAddMoreManagedProfiles();
+    boolean canAddMoreManagedProfiles(int userId);
     UserInfo getProfileParent(int userHandle);
     UserInfo getUserInfo(int userHandle);
     long getUserCreationTime(int userHandle);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index aea5123..849f5de 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1024,9 +1024,9 @@
      * @return true if more managed profiles can be added, false if limit has been reached.
      * @hide
      */
-    public boolean canAddMoreManagedProfiles() {
+    public boolean canAddMoreManagedProfiles(int userId) {
         try {
-            return mService.canAddMoreManagedProfiles();
+            return mService.canAddMoreManagedProfiles(userId);
         } catch (RemoteException re) {
             Log.w(TAG, "Could not check if we can add more managed profiles", re);
             return false;
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index ef54d84..6888594 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -341,6 +341,7 @@
         }
 
         String description = null;
+        String derivedFsUuid = fsUuid;
         long mtpReserveSize = 0;
         long maxFileSize = 0;
         int mtpStorageId = StorageVolume.STORAGE_ID_INVALID;
@@ -351,6 +352,7 @@
             final VolumeInfo privateVol = storage.findPrivateForEmulated(this);
             if (privateVol != null) {
                 description = storage.getBestVolumeDescription(privateVol);
+                derivedFsUuid = privateVol.fsUuid;
             }
 
             if (isPrimary()) {
@@ -393,7 +395,7 @@
 
         return new StorageVolume(id, mtpStorageId, userPath, description, isPrimary(), removable,
                 emulated, mtpReserveSize, allowMassStorage, maxFileSize, new UserHandle(userId),
-                fsUuid, envState);
+                derivedFsUuid, envState);
     }
 
     public static int buildStableMtpStorageId(String fsUuid) {
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index db19f7a..6310570 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -118,7 +118,7 @@
     public boolean allowEvents = DEFAULT_ALLOW_EVENTS;
     public int allowCallsFrom = DEFAULT_SOURCE;
     public int allowMessagesFrom = DEFAULT_SOURCE;
-    public int user = UserHandle.USER_OWNER;
+    public int user = UserHandle.USER_SYSTEM;
 
     public ZenRule manualRule;
     public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>();
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 4d8a7d0..49cb8e2 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -462,7 +462,7 @@
 
     /**
      * Returns the length that the specified CharSequence would have if
-     * spaces and control characters were trimmed from the start and end,
+     * spaces and ASCII control characters were trimmed from the start and end,
      * as by {@link String#trim}.
      */
     public static int getTrimmedLength(CharSequence s) {
@@ -505,7 +505,13 @@
         return false;
     }
 
-    // XXX currently this only reverses chars, not spans
+    /*
+     * @deprecated
+     * Do not use. This function only reverses individual {@code char}s and not their associated
+     * spans. It doesn't support surrogate pairs (that correspond to non-BMP code points),
+     * combining sequences or conjuncts either.
+     */
+    @Deprecated
     public static CharSequence getReverse(CharSequence source,
                                           int start, int end) {
         return new Reverser(source, start, end);
@@ -1470,8 +1476,9 @@
      */
     public static boolean isDigitsOnly(CharSequence str) {
         final int len = str.length();
-        for (int i = 0; i < len; i++) {
-            if (!Character.isDigit(str.charAt(i))) {
+        for (int cp, i = 0; i < len; i += Character.charCount(cp)) {
+            cp = Character.codePointAt(str, i);
+            if (!Character.isDigit(cp)) {
                 return false;
             }
         }
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index a53da09..9f5dfa6 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -98,7 +98,8 @@
 
     /** {@hide} */
     public static BytesResult formatBytes(Resources res, long sizeBytes, int flags) {
-        float result = sizeBytes;
+        final boolean isNegative = (sizeBytes < 0);
+        float result = isNegative ? -sizeBytes : sizeBytes;
         int suffix = com.android.internal.R.string.byteShort;
         long mult = 1;
         if (result > 900) {
@@ -154,9 +155,13 @@
                 roundFormat = "%.2f";
             }
         }
+
+        if (isNegative) {
+            result = -result;
+        }
         final String roundedString = String.format(roundFormat, result);
 
-        // Note this might overflow if result >= Long.MAX_VALUE / 100, but that's like 80PB so
+        // Note this might overflow if abs(result) >= Long.MAX_VALUE / 100, but that's like 80PB so
         // it's okay (for now)...
         final long roundedBytes =
                 (flags & FLAG_CALCULATE_ROUNDED) == 0 ? 0
diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java
new file mode 100644
index 0000000..017735a
--- /dev/null
+++ b/core/java/android/util/LocaleList.java
@@ -0,0 +1,82 @@
+/*
+ * 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.util;
+
+import android.annotation.Nullable;
+
+import java.util.HashSet;
+import java.util.Locale;
+
+// TODO: We don't except too many LocaleLists to exist at the same time, and
+// we need access to the data at native level, so we should pass the data
+// down to the native level, create a mapt of every list seen there, take a
+// pointer back, and just keep that pointed in the Java-level object, so
+// things could be copied very quickly.
+
+/**
+ * LocaleList is an immutable list of Locales, typically used to keep an
+ * ordered user preferences for locales.
+ */
+public final class LocaleList {
+    private final Locale[] mList;
+    private static final Locale[] sEmptyList = new Locale[0];
+
+    public Locale get(int location) {
+        return location < mList.length ? mList[location] : null;
+    }
+
+    public Locale getPrimary() {
+        return mList.length == 0 ? null : get(0);
+    }
+
+    public boolean isEmpty() {
+        return mList.length == 0;
+    }
+
+    public int size() {
+        return mList.length;
+    }
+
+    public LocaleList() {
+        mList = sEmptyList;
+    }
+
+    /**
+     * @throws NullPointerException if any of the input locales is <code>null</code>.
+     * @throws IllegalArgumentException if any of the input locales repeat.
+     */
+    public LocaleList(@Nullable Locale[] list) {
+        if (list == null || list.length == 0) {
+            mList = sEmptyList;
+        } else {
+            final Locale[] localeList = new Locale[list.length];
+            final HashSet<Locale> seenLocales = new HashSet<Locale>();
+            for (int i = 0; i < list.length; ++i) {
+                final Locale l = list[i];
+                if (l == null) {
+                    throw new NullPointerException();
+                } else if (seenLocales.contains(l)) {
+                    throw new IllegalArgumentException();
+                } else {
+                    seenLocales.add(l);
+                    localeList[i] = (Locale) l.clone();
+                }
+            }
+            mList = localeList;
+        }
+    }
+}
diff --git a/core/java/android/view/AppTransitionAnimationSpec.aidl b/core/java/android/view/AppTransitionAnimationSpec.aidl
new file mode 100644
index 0000000..8388347
--- /dev/null
+++ b/core/java/android/view/AppTransitionAnimationSpec.aidl
@@ -0,0 +1,20 @@
+/*
+** Copyright 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.view;
+
+/** @hide */
+parcelable AppTransitionAnimationSpec;
diff --git a/core/java/android/view/AppTransitionAnimationSpec.java b/core/java/android/view/AppTransitionAnimationSpec.java
new file mode 100644
index 0000000..c6e1989
--- /dev/null
+++ b/core/java/android/view/AppTransitionAnimationSpec.java
@@ -0,0 +1,61 @@
+package android.view;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Holds information about how the next app transition animation should be executed.
+ *
+ * This class is intended to be used with IWindowManager.overridePendingAppTransition* methods when
+ * simple arguments are not enough to describe the animation.
+ *
+ * @hide
+ */
+public class AppTransitionAnimationSpec implements Parcelable {
+    public final int taskId;
+    public final Bitmap bitmap;
+    public final Rect rect;
+
+    public AppTransitionAnimationSpec(int taskId, Bitmap bitmap, Rect rect) {
+        this.taskId = taskId;
+        this.bitmap = bitmap;
+        this.rect = rect;
+    }
+
+    public AppTransitionAnimationSpec(Parcel in) {
+        taskId = in.readInt();
+        bitmap = in.readParcelable(null);
+        rect = in.readParcelable(null);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(taskId);
+        dest.writeParcelable(bitmap, 0 /* flags */);
+        dest.writeParcelable(rect, 0 /* flags */);
+
+    }
+
+    public static final Parcelable.Creator<AppTransitionAnimationSpec> CREATOR
+            = new Parcelable.Creator<AppTransitionAnimationSpec>() {
+        public AppTransitionAnimationSpec createFromParcel(Parcel in) {
+            return new AppTransitionAnimationSpec(in);
+        }
+
+        public AppTransitionAnimationSpec[] newArray(int size) {
+            return new AppTransitionAnimationSpec[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return "{taskId: " + taskId + ", bitmap: " + bitmap + ", rect: " + rect + "}";
+    }
+}
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 948cec7..080ed9a 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -20,12 +20,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.CanvasProperty;
-import android.graphics.NinePatch;
 import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Picture;
-import android.graphics.Rect;
-import android.graphics.RectF;
 import android.util.Pools.SynchronizedPool;
 
 /**
@@ -206,16 +201,12 @@
      * Draws the specified layer onto this canvas.
      *
      * @param layer The layer to composite on this canvas
-     * @param x The left coordinate of the layer
-     * @param y The top coordinate of the layer
-     * @param paint The paint used to draw the layer
      */
-    void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
-        layer.setLayerPaint(paint);
-        nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle(), x, y);
+    void drawHardwareLayer(HardwareLayer layer) {
+        nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle());
     }
 
-    private static native void nDrawLayer(long renderer, long layer, float x, float y);
+    private static native void nDrawLayer(long renderer, long layer);
 
     ///////////////////////////////////////////////////////////////////////////
     // Drawing
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 65ae8a6..692ca7b 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -150,8 +150,4 @@
     private static native void nSetSurfaceTexture(long layerUpdater,
             SurfaceTexture surface, boolean isAlreadyAttached);
     private static native void nUpdateSurfaceTexture(long layerUpdater);
-    private static native void nUpdateRenderLayer(long layerUpdater, long displayList,
-            int left, int top, int right, int bottom);
-
-    private static native int nGetTexName(long layerUpdater);
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0a4b982..f86adfe 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -39,6 +39,7 @@
 import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.IInputFilter;
+import android.view.AppTransitionAnimationSpec;
 import android.view.WindowContentFrameStats;
 
 /**
@@ -127,6 +128,16 @@
     void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
             int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
             boolean scaleUp);
+    /**
+     * Overrides animation for app transition that exits from an application to a multi-window
+     * environment and allows specifying transition animation parameters for each window.
+     *
+     * @param specs Array of transition animation descriptions for entering windows.
+     *
+     * @hide
+     */
+    void overridePendingAppTransitionMultiThumb(in AppTransitionAnimationSpec[] specs,
+            IRemoteCallback startedCallback, boolean scaleUp);
     void overridePendingAppTransitionInPlace(String packageName, int anim);
     void executeAppTransition();
     void setAppStartingWindow(IBinder token, String pkg, int theme,
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index cdc196e..6b60be9 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -23,6 +23,7 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
 
@@ -294,6 +295,22 @@
     public void buildLayer() {
     }
 
+    @Override
+    public void setForeground(Drawable foreground) {
+        if (foreground != null) {
+            throw new UnsupportedOperationException(
+                    "TextureView doesn't support displaying a foreground drawable");
+        }
+    }
+
+    @Override
+    public void setBackgroundDrawable(Drawable background) {
+        if (background != null) {
+            throw new UnsupportedOperationException(
+                    "TextureView doesn't support displaying a background drawable");
+        }
+    }
+
     /**
      * Subclasses of TextureView cannot do their own rendering
      * with the {@link Canvas} object.
@@ -302,11 +319,25 @@
      */
     @Override
     public final void draw(Canvas canvas) {
-        // NOTE: Maintain this carefully (see View.java)
+        // NOTE: Maintain this carefully (see View#draw)
         mPrivateFlags = (mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
 
-        applyUpdate();
-        applyTransformMatrix();
+        /* Simplify drawing to guarantee the layer is the only thing drawn - so e.g. no background,
+        scrolling, or fading edges. This guarantees all drawing is in the layer, so drawing
+        properties (alpha, layer paint) affect all of the content of a TextureView. */
+
+        if (canvas.isHardwareAccelerated()) {
+            DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
+
+            HardwareLayer layer = getHardwareLayer();
+            if (layer != null) {
+                applyUpdate();
+                applyTransformMatrix();
+
+                mLayer.setLayerPaint(mLayerPaint); // ensure layer paint is up to date
+                displayListCanvas.drawHardwareLayer(layer);
+            }
+        }
     }
 
     /**
@@ -342,12 +373,7 @@
         invalidate(true);
     }
 
-    @Override
     HardwareLayer getHardwareLayer() {
-        // NOTE: Maintain these two lines very carefully (see View.java)
-        mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
-        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
-
         if (mLayer == null) {
             if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
                 return null;
@@ -385,9 +411,6 @@
             mSurface.setDefaultBufferSize(getWidth(), getHeight());
         }
 
-        applyUpdate();
-        applyTransformMatrix();
-
         return mLayer;
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a492518..b17f88f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -15002,16 +15002,6 @@
     }
 
     /**
-     * If this View draws with a HardwareLayer, returns it.
-     * Otherwise returns null
-     *
-     * TODO: Only TextureView uses this, can we eliminate it?
-     */
-    HardwareLayer getHardwareLayer() {
-        return null;
-    }
-
-    /**
      * Destroys all hardware rendering resources. This method is invoked
      * when the system needs to reclaim resources. Upon execution of this
      * method, you should free any OpenGL resources created by the view.
@@ -15161,10 +15151,7 @@
             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
 
             try {
-                final HardwareLayer layer = getHardwareLayer();
-                if (layer != null && layer.isValid()) {
-                    canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
-                } else if (layerType == LAYER_TYPE_SOFTWARE) {
+                if (layerType == LAYER_TYPE_SOFTWARE) {
                     buildDrawingCache(true);
                     Bitmap cache = getDrawingCache(true);
                     if (cache != null) {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index d9faece..5fc8c7a 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -220,7 +220,7 @@
                 result.putExtras(replExtras);
             }
         }
-        if (aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER)
+        if (aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_PARENT)
                 || aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE)) {
             result = Intent.createChooser(result,
                     getIntent().getCharSequenceExtra(Intent.EXTRA_TITLE));
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 39b66aa..dbec740 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -45,8 +45,8 @@
 
     public static String TAG = "IntentForwarderActivity";
 
-    public static String FORWARD_INTENT_TO_USER_OWNER
-            = "com.android.internal.app.ForwardIntentToUserOwner";
+    public static String FORWARD_INTENT_TO_PARENT
+            = "com.android.internal.app.ForwardIntentToParent";
 
     public static String FORWARD_INTENT_TO_MANAGED_PROFILE
             = "com.android.internal.app.ForwardIntentToManagedProfile";
@@ -60,9 +60,9 @@
         final int targetUserId;
         final int userMessageId;
 
-        if (className.equals(FORWARD_INTENT_TO_USER_OWNER)) {
+        if (className.equals(FORWARD_INTENT_TO_PARENT)) {
             userMessageId = com.android.internal.R.string.forward_intent_to_owner;
-            targetUserId = UserHandle.USER_OWNER;
+            targetUserId = getProfileParent();
         } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
             userMessageId = com.android.internal.R.string.forward_intent_to_work;
             targetUserId = getManagedProfile();
@@ -72,7 +72,7 @@
             targetUserId = UserHandle.USER_NULL;
         }
         if (targetUserId == UserHandle.USER_NULL) {
-            // This covers the case where there is no managed profile.
+            // This covers the case where there is no parent / managed profile.
             finish();
             return;
         }
@@ -168,7 +168,7 @@
      */
     private int getManagedProfile() {
         UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
-        List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.USER_OWNER);
+        List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.myUserId());
         for (UserInfo userInfo : relatedUsers) {
             if (userInfo.isManagedProfile()) return userInfo.id;
         }
@@ -176,4 +176,19 @@
                 + " has been called, but there is no managed profile");
         return UserHandle.USER_NULL;
     }
+
+    /**
+     * Returns the userId of the profile parent or UserHandle.USER_NULL if there is
+     * no parent.
+     */
+    private int getProfileParent() {
+        UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
+        UserInfo parent = userManager.getProfileParent(UserHandle.myUserId());
+        if (parent == null) {
+            Slog.wtf(TAG, FORWARD_INTENT_TO_PARENT
+                    + " has been called, but there is no parent");
+            return UserHandle.USER_NULL;
+        }
+        return parent.id;
+    }
 }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index be26c24..55e23b1 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -20,6 +20,7 @@
 import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.HOME_STACK_ID;
+import static android.app.ActivityManager.INVALID_STACK_ID;
 import static android.view.View.MeasureSpec.AT_MOST;
 import static android.view.View.MeasureSpec.EXACTLY;
 import static android.view.View.MeasureSpec.getMode;
@@ -5250,7 +5251,7 @@
      * @return Returns the workspace stack id which contains this window.
      **/
     private int getWorkspaceId() {
-        int workspaceId = FULLSCREEN_WORKSPACE_STACK_ID;
+        int workspaceId = INVALID_STACK_ID;
         WindowControllerCallback callback = getWindowControllerCallback();
         if (callback != null) {
             try {
@@ -5259,6 +5260,9 @@
                 Log.e(TAG, "Failed to get the workspace ID of a PhoneWindow.");
             }
         }
+        if (workspaceId == INVALID_STACK_ID) {
+            return FULLSCREEN_WORKSPACE_STACK_ID;
+        }
         return workspaceId;
     }
 
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index c1645c3..1e41e63 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -46,6 +46,8 @@
     void cancelPreloadRecentApps();
     void showScreenPinningRequest();
 
+    void showKeyboardShortcutsMenu();
+
     /**
      * Notifies the status bar that an app transition is pending to delay applying some flags with
      * visual impact until {@link #appTransitionReady} is called.
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 7db2cc9..6c957be 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -68,6 +68,8 @@
     void preloadRecentApps();
     void cancelPreloadRecentApps();
 
+    void showKeyboardShortcutsMenu();
+
     /**
      * Notifies the status bar that an app transition is pending to delay applying some flags with
      * visual impact until {@link #appTransitionReady} is called.
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index dfb7c50..4e4552d 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.widget;
 
+import android.app.trust.IStrongAuthTracker;
 import com.android.internal.widget.VerifyCredentialResponse;
 
 /** {@hide} */
@@ -35,4 +36,7 @@
     boolean checkVoldPassword(int userId);
     boolean havePattern(int userId);
     boolean havePassword(int userId);
+    void registerStrongAuthTracker(in IStrongAuthTracker tracker);
+    void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
+    void requireStrongAuth(int strongAuthReason, int userId);
 }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index ca184d1..1995694 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -16,19 +16,19 @@
 
 package com.android.internal.widget;
 
-import android.Manifest;
+import android.annotation.IntDef;
 import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
 import android.app.admin.DevicePolicyManager;
+import android.app.trust.IStrongAuthTracker;
 import android.app.trust.TrustManager;
-import android.bluetooth.BluetoothClass;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.os.AsyncTask;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
@@ -39,9 +39,12 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.SparseIntArray;
 
 import com.google.android.collect.Lists;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -229,7 +232,7 @@
     public void reportFailedPasswordAttempt(int userId) {
         getDevicePolicyManager().reportFailedPasswordAttempt(userId);
         getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
-        getTrustManager().reportRequireCredentialEntry(userId);
+        requireCredentialEntry(userId);
     }
 
     public void reportSuccessfulPasswordAttempt(int userId) {
@@ -1168,10 +1171,32 @@
     }
 
     /**
-     * @see android.app.trust.TrustManager#reportRequireCredentialEntry(int)
+     * Disable trust until credentials have been entered for user {@param userId}.
+     *
+     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+     *
+     * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
      */
     public void requireCredentialEntry(int userId) {
-        getTrustManager().reportRequireCredentialEntry(userId);
+        requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
+    }
+
+    /**
+     * Requests strong authentication for user {@param userId}.
+     *
+     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+     *
+     * @param strongAuthReason a combination of {@link StrongAuthTracker.StrongAuthFlags} indicating
+     *                         the reason for and the strength of the requested authentication.
+     * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
+     */
+    public void requireStrongAuth(@StrongAuthTracker.StrongAuthFlags int strongAuthReason,
+            int userId) {
+        try {
+            getLockSettings().requireStrongAuth(strongAuthReason, userId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error while requesting strong auth: " + e);
+        }
     }
 
     private void onAfterChangingPassword(int userHandle) {
@@ -1209,4 +1234,147 @@
             throw new IllegalStateException("should not be called from the main thread.");
         }
     }
+
+    public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
+        try {
+            getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Could not register StrongAuthTracker");
+        }
+    }
+
+    public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
+        try {
+            getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.mStub);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not unregister StrongAuthTracker", e);
+        }
+    }
+
+    /**
+     * Tracks the global strong authentication state.
+     */
+    public static class StrongAuthTracker {
+
+        @IntDef(flag = true,
+                value = { STRONG_AUTH_NOT_REQUIRED,
+                        STRONG_AUTH_REQUIRED_AFTER_BOOT,
+                        STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
+                        SOME_AUTH_REQUIRED_AFTER_USER_REQUEST})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface StrongAuthFlags {}
+
+        /**
+         * Strong authentication is not required.
+         */
+        public static final int STRONG_AUTH_NOT_REQUIRED = 0x0;
+
+        /**
+         * Strong authentication is required because the user has not authenticated since boot.
+         */
+        public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;
+
+        /**
+         * Strong authentication is required because a device admin has requested it.
+         */
+        public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;
+
+        /**
+         * Some authentication is required because the user has temporarily disabled trust.
+         */
+        public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
+
+        public static final int DEFAULT = STRONG_AUTH_REQUIRED_AFTER_BOOT;
+        private static final int ALLOWING_FINGERPRINT = SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
+
+        final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
+
+        private final H mHandler;
+
+        public StrongAuthTracker() {
+            this(Looper.myLooper());
+        }
+
+        /**
+         * @param looper the looper on whose thread calls to {@link #onStrongAuthRequiredChanged}
+         *               will be scheduled.
+         */
+        public StrongAuthTracker(Looper looper) {
+            mHandler = new H(looper);
+        }
+
+        /**
+         * Returns {@link #STRONG_AUTH_NOT_REQUIRED} if strong authentication is not required,
+         * otherwise returns a combination of {@link StrongAuthFlags} indicating why strong
+         * authentication is required.
+         *
+         * @param userId the user for whom the state is queried.
+         */
+        public @StrongAuthFlags int getStrongAuthForUser(int userId) {
+            return mStrongAuthRequiredForUser.get(userId, DEFAULT);
+        }
+
+        /**
+         * @return true if unlocking with trust alone is allowed for {@param userId} by the current
+         * strong authentication requirements.
+         */
+        public boolean isTrustAllowedForUser(int userId) {
+            return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
+        }
+
+        /**
+         * @return true if unlocking with fingerprint alone is allowed for {@param userId} by the
+         * current strong authentication requirements.
+         */
+        public boolean isFingerprintAllowedForUser(int userId) {
+            return (getStrongAuthForUser(userId) & ~ALLOWING_FINGERPRINT) == 0;
+        }
+
+        /**
+         * Called when the strong authentication requirements for {@param userId} changed.
+         */
+        public void onStrongAuthRequiredChanged(int userId) {
+        }
+
+        void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
+                int userId) {
+
+            int oldValue = getStrongAuthForUser(userId);
+            if (strongAuthFlags != oldValue) {
+                if (strongAuthFlags == DEFAULT) {
+                    mStrongAuthRequiredForUser.delete(userId);
+                } else {
+                    mStrongAuthRequiredForUser.put(userId, strongAuthFlags);
+                }
+                onStrongAuthRequiredChanged(userId);
+            }
+        }
+
+
+        final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
+            @Override
+            public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
+                    int userId) {
+                mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED,
+                        strongAuthFlags, userId).sendToTarget();
+            }
+        };
+
+        private class H extends Handler {
+            static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1;
+
+            public H(Looper looper) {
+                super(looper);
+            }
+
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED:
+                        handleStrongAuthRequiredChanged(msg.arg1, msg.arg2);
+                        break;
+                }
+            }
+        };
+    }
 }
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
index 05711b5..92812f8 100644
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -20,6 +20,7 @@
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.view.ViewGroup;
@@ -63,18 +64,31 @@
     private final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20;
     // The height of a window which has not in DIP.
     private final int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
-
     private PhoneWindow mOwner = null;
-    boolean mWindowHasShadow = false;
-    boolean mShowDecor = false;
+    private boolean mWindowHasShadow = false;
+    private boolean mShowDecor = false;
+
+    // True if the window is being dragged.
+    private boolean mDragging = false;
+
+    // The bounds of the window and the absolute mouse pointer coordinates from before we started to
+    // drag the window. They will be used to determine the next window position.
+    private final Rect mWindowOriginalBounds = new Rect();
+    private float mStartDragX;
+    private float mStartDragY;
+    // True when the left mouse button got released while dragging.
+    private boolean mLeftMouseButtonReleased;
+
+    // Avoiding re-creation of Rect's by keeping a temporary window drag bound.
+    private final Rect mWindowDragBounds = new Rect();
 
     // The current focus state of the window for updating the window elevation.
-    boolean mWindowHasFocus = true;
+    private boolean mWindowHasFocus = true;
 
     // Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
     // size calculation takes the shadow size into account. We set the elevation currently
     // to max until the first layout command has been executed.
-    boolean mAllowUpdateElevation = false;
+    private boolean mAllowUpdateElevation = false;
 
     public NonClientDecorView(Context context) {
         super(context);
@@ -103,6 +117,62 @@
         findViewById(R.id.close_window).setOnClickListener(this);
     }
 
+    @Override
+    public boolean onTouchEvent(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.
+        switch (e.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                // A drag action is started if we aren't dragging already and the starting event is
+                // either a left mouse button or any other input device.
+                if (!mDragging &&
+                        (e.getToolType(e.getActionIndex()) != MotionEvent.TOOL_TYPE_MOUSE ||
+                                (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0)) {
+                    mDragging = true;
+                    mWindowOriginalBounds.set(getActivityBounds());
+                    mLeftMouseButtonReleased = false;
+                    mStartDragX = e.getRawX();
+                    mStartDragY = e.getRawY();
+                }
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                if (mDragging && !mLeftMouseButtonReleased) {
+                    if (e.getToolType(e.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE &&
+                            (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) == 0) {
+                        // There is no separate mouse button up call and if the user mixes mouse
+                        // button drag actions, we stop dragging once he releases the button.
+                        mLeftMouseButtonReleased = true;
+                        break;
+                    }
+                    mWindowDragBounds.set(mWindowOriginalBounds);
+                    mWindowDragBounds.offset(Math.round(e.getRawX() - mStartDragX),
+                            Math.round(e.getRawY() - mStartDragY));
+                    setActivityBounds(mWindowDragBounds);
+                }
+                break;
+
+            case MotionEvent.ACTION_UP:
+                if (mDragging) {
+                    // Since the window is already where it should be we don't have to do anything
+                    // special at this time.
+                    mDragging = false;
+                    return true;
+                }
+                break;
+
+            case MotionEvent.ACTION_CANCEL:
+                if (mDragging) {
+                    mDragging = false;
+                    setActivityBounds(mWindowOriginalBounds);
+                    return true;
+                }
+                break;
+        }
+        return mDragging;
+    }
+
     /**
      * The phone window configuration has changed and the decor needs to be updated.
      * @param showDecor True if the decor should be shown.
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index c66cdfe..988d13a 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -112,15 +112,15 @@
     }
 
     static jlong init(JNIEnv* env, jobject clazz) {
-        SK_COMPILE_ASSERT(1 <<  0 == SkPaint::kAntiAlias_Flag,          paint_flags_mismatch);
-        SK_COMPILE_ASSERT(1 <<  2 == SkPaint::kDither_Flag,             paint_flags_mismatch);
-        SK_COMPILE_ASSERT(1 <<  3 == SkPaint::kUnderlineText_Flag,      paint_flags_mismatch);
-        SK_COMPILE_ASSERT(1 <<  4 == SkPaint::kStrikeThruText_Flag,     paint_flags_mismatch);
-        SK_COMPILE_ASSERT(1 <<  5 == SkPaint::kFakeBoldText_Flag,       paint_flags_mismatch);
-        SK_COMPILE_ASSERT(1 <<  6 == SkPaint::kLinearText_Flag,         paint_flags_mismatch);
-        SK_COMPILE_ASSERT(1 <<  7 == SkPaint::kSubpixelText_Flag,       paint_flags_mismatch);
-        SK_COMPILE_ASSERT(1 <<  8 == SkPaint::kDevKernText_Flag,        paint_flags_mismatch);
-        SK_COMPILE_ASSERT(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, paint_flags_mismatch);
+        static_assert(1 <<  0 == SkPaint::kAntiAlias_Flag,          "paint_flags_mismatch");
+        static_assert(1 <<  2 == SkPaint::kDither_Flag,             "paint_flags_mismatch");
+        static_assert(1 <<  3 == SkPaint::kUnderlineText_Flag,      "paint_flags_mismatch");
+        static_assert(1 <<  4 == SkPaint::kStrikeThruText_Flag,     "paint_flags_mismatch");
+        static_assert(1 <<  5 == SkPaint::kFakeBoldText_Flag,       "paint_flags_mismatch");
+        static_assert(1 <<  6 == SkPaint::kLinearText_Flag,         "paint_flags_mismatch");
+        static_assert(1 <<  7 == SkPaint::kSubpixelText_Flag,       "paint_flags_mismatch");
+        static_assert(1 <<  8 == SkPaint::kDevKernText_Flag,        "paint_flags_mismatch");
+        static_assert(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, "paint_flags_mismatch");
 
         Paint* obj = new Paint();
         defaultSettingsForAndroid(obj);
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index f7b5dc2..dbd7c89 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -519,6 +519,9 @@
 
 int register_android_graphics_Path(JNIEnv* env) {
     return RegisterMethodsOrDie(env, "android/graphics/Path", methods, NELEM(methods));
+
+    static_assert(0  == SkPath::kCW_Direction,  "direction_mismatch");
+    static_assert(1  == SkPath::kCCW_Direction, "direction_mismatch");
 }
 
 }
diff --git a/core/jni/android/graphics/PorterDuff.cpp b/core/jni/android/graphics/PorterDuff.cpp
index d65864d..fed90a5 100644
--- a/core/jni/android/graphics/PorterDuff.cpp
+++ b/core/jni/android/graphics/PorterDuff.cpp
@@ -33,29 +33,29 @@
 
     static jlong CreateXfermode(JNIEnv* env, jobject, jint modeHandle) {
         // validate that the Java enum values match our expectations
-        SK_COMPILE_ASSERT(0  == SkXfermode::kClear_Mode,    xfermode_mismatch);
-        SK_COMPILE_ASSERT(1  == SkXfermode::kSrc_Mode,      xfermode_mismatch);
-        SK_COMPILE_ASSERT(2  == SkXfermode::kDst_Mode,      xfermode_mismatch);
-        SK_COMPILE_ASSERT(3  == SkXfermode::kSrcOver_Mode,  xfermode_mismatch);
-        SK_COMPILE_ASSERT(4  == SkXfermode::kDstOver_Mode,  xfermode_mismatch);
-        SK_COMPILE_ASSERT(5  == SkXfermode::kSrcIn_Mode,    xfermode_mismatch);
-        SK_COMPILE_ASSERT(6  == SkXfermode::kDstIn_Mode,    xfermode_mismatch);
-        SK_COMPILE_ASSERT(7  == SkXfermode::kSrcOut_Mode,   xfermode_mismatch);
-        SK_COMPILE_ASSERT(8  == SkXfermode::kDstOut_Mode,   xfermode_mismatch);
-        SK_COMPILE_ASSERT(9  == SkXfermode::kSrcATop_Mode,  xfermode_mismatch);
-        SK_COMPILE_ASSERT(10 == SkXfermode::kDstATop_Mode,  xfermode_mismatch);
-        SK_COMPILE_ASSERT(11 == SkXfermode::kXor_Mode,      xfermode_mismatch);
-        SK_COMPILE_ASSERT(16 == SkXfermode::kDarken_Mode,   xfermode_mismatch);
-        SK_COMPILE_ASSERT(17 == SkXfermode::kLighten_Mode,  xfermode_mismatch);
-        SK_COMPILE_ASSERT(13 == SkXfermode::kModulate_Mode, xfermode_mismatch);
-        SK_COMPILE_ASSERT(14 == SkXfermode::kScreen_Mode,   xfermode_mismatch);
-        SK_COMPILE_ASSERT(12 == SkXfermode::kPlus_Mode,     xfermode_mismatch);
-        SK_COMPILE_ASSERT(15 == SkXfermode::kOverlay_Mode,  xfermode_mismatch);
-        
+        static_assert(0  == SkXfermode::kClear_Mode,    "xfermode_mismatch");
+        static_assert(1  == SkXfermode::kSrc_Mode,      "xfermode_mismatch");
+        static_assert(2  == SkXfermode::kDst_Mode,      "xfermode_mismatch");
+        static_assert(3  == SkXfermode::kSrcOver_Mode,  "xfermode_mismatch");
+        static_assert(4  == SkXfermode::kDstOver_Mode,  "xfermode_mismatch");
+        static_assert(5  == SkXfermode::kSrcIn_Mode,    "xfermode_mismatch");
+        static_assert(6  == SkXfermode::kDstIn_Mode,    "xfermode_mismatch");
+        static_assert(7  == SkXfermode::kSrcOut_Mode,   "xfermode_mismatch");
+        static_assert(8  == SkXfermode::kDstOut_Mode,   "xfermode_mismatch");
+        static_assert(9  == SkXfermode::kSrcATop_Mode,  "xfermode_mismatch");
+        static_assert(10 == SkXfermode::kDstATop_Mode,  "xfermode_mismatch");
+        static_assert(11 == SkXfermode::kXor_Mode,      "xfermode_mismatch");
+        static_assert(16 == SkXfermode::kDarken_Mode,   "xfermode_mismatch");
+        static_assert(17 == SkXfermode::kLighten_Mode,  "xfermode_mismatch");
+        static_assert(13 == SkXfermode::kModulate_Mode, "xfermode_mismatch");
+        static_assert(14 == SkXfermode::kScreen_Mode,   "xfermode_mismatch");
+        static_assert(12 == SkXfermode::kPlus_Mode,     "xfermode_mismatch");
+        static_assert(15 == SkXfermode::kOverlay_Mode,  "xfermode_mismatch");
+
         SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
         return reinterpret_cast<jlong>(SkXfermode::Create(mode));
     }
- 
+
 };
 
 static JNINativeMethod methods[] = {
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index 3833325..460c1a1 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -40,18 +40,14 @@
 
 using namespace uirenderer;
 
-static struct {
-    jmethodID set;
-} gRectClassInfo;
-
 // ----------------------------------------------------------------------------
 // Setup
 // ----------------------------------------------------------------------------
 
 static void android_view_DisplayListCanvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jboolean reorderEnable) {
-    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
-    renderer->insertReorderBarrier(reorderEnable);
+        jlong canvasPtr, jboolean reorderEnable) {
+    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    canvas->insertReorderBarrier(reorderEnable);
 }
 
 // ----------------------------------------------------------------------------
@@ -59,10 +55,10 @@
 // ----------------------------------------------------------------------------
 
 static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong functorPtr) {
-    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
+        jlong canvasPtr, jlong functorPtr) {
+    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
-    renderer->callDrawGLFunction(functor);
+    canvas->callDrawGLFunction(functor);
 }
 
 // ----------------------------------------------------------------------------
@@ -82,9 +78,9 @@
 // ----------------------------------------------------------------------------
 
 static void android_view_DisplayListCanvas_drawRoundRectProps(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
+        jlong canvasPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
         jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) {
-    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
+    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
     CanvasPropertyPrimitive* leftProp = reinterpret_cast<CanvasPropertyPrimitive*>(leftPropPtr);
     CanvasPropertyPrimitive* topProp = reinterpret_cast<CanvasPropertyPrimitive*>(topPropPtr);
     CanvasPropertyPrimitive* rightProp = reinterpret_cast<CanvasPropertyPrimitive*>(rightPropPtr);
@@ -92,17 +88,17 @@
     CanvasPropertyPrimitive* rxProp = reinterpret_cast<CanvasPropertyPrimitive*>(rxPropPtr);
     CanvasPropertyPrimitive* ryProp = reinterpret_cast<CanvasPropertyPrimitive*>(ryPropPtr);
     CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
-    renderer->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp);
+    canvas->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp);
 }
 
 static void android_view_DisplayListCanvas_drawCircleProps(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
-    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
+        jlong canvasPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
+    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
     CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
     CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
     CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
     CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
-    renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
+    canvas->drawCircle(xProp, yProp, radiusProp, paintProp);
 }
 
 // ----------------------------------------------------------------------------
@@ -110,9 +106,9 @@
 // ----------------------------------------------------------------------------
 
 static jlong android_view_DisplayListCanvas_finishRecording(JNIEnv* env,
-        jobject clazz, jlong rendererPtr) {
-    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
-    return reinterpret_cast<jlong>(renderer->finishRecording());
+        jobject clazz, jlong canvasPtr) {
+    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    return reinterpret_cast<jlong>(canvas->finishRecording());
 }
 
 static jlong android_view_DisplayListCanvas_createDisplayListCanvas(JNIEnv* env, jobject clazz,
@@ -121,17 +117,17 @@
 }
 
 static void android_view_DisplayListCanvas_resetDisplayListCanvas(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jint width, jint height) {
-    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
-    renderer->reset(width, height);
+        jlong canvasPtr, jint width, jint height) {
+    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    canvas->reset(width, height);
 }
 
 
 static void android_view_DisplayListCanvas_drawRenderNode(JNIEnv* env,
-        jobject clazz, jlong rendererPtr, jlong renderNodePtr) {
-    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
+        jobject clazz, jlong canvasPtr, jlong renderNodePtr) {
+    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
-    renderer->drawRenderNode(renderNode);
+    canvas->drawRenderNode(renderNode);
 }
 
 // ----------------------------------------------------------------------------
@@ -139,10 +135,10 @@
 // ----------------------------------------------------------------------------
 
 static void android_view_DisplayListCanvas_drawLayer(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
-    DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
+        jlong canvasPtr, jlong layerPtr) {
+    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
-    renderer->drawLayer(layer, x, y);
+    canvas->drawLayer(layer);
 }
 
 // ----------------------------------------------------------------------------
@@ -192,7 +188,7 @@
     { "nCreateDisplayListCanvas", "(II)J",     (void*) android_view_DisplayListCanvas_createDisplayListCanvas },
     { "nResetDisplayListCanvas", "(JII)V",     (void*) android_view_DisplayListCanvas_resetDisplayListCanvas },
 
-    { "nDrawLayer",               "(JJFF)V",   (void*) android_view_DisplayListCanvas_drawLayer },
+    { "nDrawLayer",               "(JJ)V",     (void*) android_view_DisplayListCanvas_drawLayer },
 
     { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_DisplayListCanvas_getMaxTextureWidth },
     { "nGetMaximumTextureHeight", "()I",       (void*) android_view_DisplayListCanvas_getMaxTextureHeight },
@@ -204,9 +200,6 @@
 };
 
 int register_android_view_DisplayListCanvas(JNIEnv* env) {
-    jclass clazz = FindClassOrDie(env, "android/graphics/Rect");
-    gRectClassInfo.set = GetMethodIDOrDie(env, clazz, "set", "(IIII)V");
-
     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
 }
 
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 9e49afb..36ba892 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -79,12 +79,6 @@
     layer->updateTexImage();
 }
 
-static jint android_view_HardwareLayer_getTexName(JNIEnv* env, jobject clazz,
-        jlong layerUpdaterPtr) {
-    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
-    return layer->backingLayer()->getTextureId();
-}
-
 // ----------------------------------------------------------------------------
 // JNI Glue
 // ----------------------------------------------------------------------------
@@ -98,8 +92,6 @@
     { "nSetSurfaceTexture",      "(JLandroid/graphics/SurfaceTexture;Z)V",
             (void*) android_view_HardwareLayer_setSurfaceTexture },
     { "nUpdateSurfaceTexture",   "(J)V",       (void*) android_view_HardwareLayer_updateSurfaceTexture },
-
-    { "nGetTexName",             "(J)I",       (void*) android_view_HardwareLayer_getTexName },
 };
 
 int register_android_view_HardwareLayer(JNIEnv* env) {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 4c920dc..414cbb4 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -358,8 +358,8 @@
     return;
   }
   jsize count = env->GetArrayLength(fdsToClose);
-  jint *ar = env->GetIntArrayElements(fdsToClose, 0);
-  if (!ar) {
+  ScopedIntArrayRO ar(env, fdsToClose);
+  if (ar.get() == NULL) {
       ALOGE("Bad fd array");
       RuntimeAbort(env);
   }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d591f8b..fefd5a7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -786,6 +786,46 @@
         android:protectionLevel="normal"
         android:permissionFlags="hidden"/>
 
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.WRITE_SMS"
+        android:protectionLevel="normal"
+        android:permissionFlags="hidden"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
+        android:protectionLevel="normal"
+        android:permissionFlags="hidden"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
+        android:protectionLevel="normal"
+        android:permissionFlags="hidden"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
+        android:protectionLevel="normal"
+        android:permissionFlags="hidden"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.MANAGE_ACCOUNTS"
+        android:protectionLevel="normal"
+        android:permissionFlags="hidden"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.USE_CREDENTIALS"
+        android:protectionLevel="normal"
+        android:permissionFlags="hidden"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.SUBSCRIBED_FEEDS_READ"
+        android:protectionLevel="normal"
+        android:permissionFlags="hidden"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE"
+        android:protectionLevel="normal"
+        android:permissionFlags="hidden"/>
+
     <!-- ====================================================================== -->
     <!-- INSTALL PERMISSIONS                                                    -->
     <!-- ====================================================================== -->
@@ -2658,7 +2698,7 @@
                 android:exported="true"
                 >
         </activity>
-        <activity-alias android:name="com.android.internal.app.ForwardIntentToUserOwner"
+        <activity-alias android:name="com.android.internal.app.ForwardIntentToParent"
                 android:targetActivity="com.android.internal.app.IntentForwarderActivity"
                 android:exported="true"
                 android:label="@string/user_owner_label">
diff --git a/core/res/res/drawable/scrollbar_handle_material.xml b/core/res/res/drawable/scrollbar_handle_material.xml
index 56fecec..33efbba 100644
--- a/core/res/res/drawable/scrollbar_handle_material.xml
+++ b/core/res/res/drawable/scrollbar_handle_material.xml
@@ -17,6 +17,9 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:tint="?attr/colorControlNormal"
        android:shape="rectangle">
-    <solid android:color="#84ffffff" />
-    <size android:width="4dp" />
+    <solid
+        android:color="#84ffffff" />
+    <size
+        android:width="4dp"
+        android:height="4dp" />
 </shape>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 1a45b3a..74fd1ec 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2195,4 +2195,18 @@
       <attr name="name" />
     </declare-styleable>
 
+    <!-- <code>initial-layout</code> tag allows configuring the initial layout for the activity
+         within multi-window environment. -->
+    <declare-styleable name="AndroidManifestInitialLayout" parent="AndroidManifestActivity">
+        <!-- Initial width of the activity. Can be either a fixed value or fraction, in which case
+             the width will be constructed as a fraction of the total available width. -->
+        <attr name="activity_width" format="dimension|fraction" />
+        <!-- Initial height of the activity. Can be either a fixed value or fraction, in which case
+             the height will be constructed as a fraction of the total available height. -->
+        <attr name="activity_height" format="dimension|fraction" />
+        <!-- Where to initially position the activity inside the available space. Uses constants
+             defined in {@link android.view.Gravity}. -->
+        <attr name="gravity" />
+    </declare-styleable>
+
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7acc25d..2c940ae 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -619,6 +619,17 @@
         <!-- rotation: 270 (rotate CW)  --> <item>-25</item> <item>65</item>
     </integer-array>
 
+    <!-- Indicate the name of the window orientation sensor type if present. A
+         window orientation sensor produces values to be used in lieu of the
+         typical, accelerometer based sensor. It must only produce integral
+         values between 0 and 3, inclusive, with each one corresponding to a
+         given rotation:
+            0: 0 degrees of rotation (natural)
+            1: 90 degrees of rotation (rotate CCW)
+            2: 180 degrees of rotation (reverse)
+            3: 270 degrees of rotation (rotate CW) -->
+    <string name="config_orientationSensorType" translatable="false">@null</string>
+
     <!-- Lid switch behavior -->
 
     <!-- The number of degrees to rotate the display when the keyboard is open.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 004407f..a55258c 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1545,6 +1545,7 @@
   <java-symbol type="string" name="bugreport_title" />
   <java-symbol type="string" name="bugreport_message" />
   <java-symbol type="string" name="bugreport_status" />
+  <java-symbol type="string" name="config_orientationSensorType" />
   <java-symbol type="string" name="faceunlock_multiple_failures" />
   <java-symbol type="string" name="global_action_power_off" />
   <java-symbol type="string" name="global_actions_airplane_mode_off_status" />
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
new file mode 100644
index 0000000..03ae9dc
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -0,0 +1,494 @@
+/*
+* 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.animation;
+
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import static android.test.MoreAsserts.assertNotEqual;
+
+public class ValueAnimatorTests extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> {
+    private ValueAnimator a1;
+    private ValueAnimator a2;
+
+    // Tolerance of error in calculations related to duration, frame time, etc. due to frame delay.
+    private final static long TOLERANCE = 100; // ms
+    private final static long POLL_INTERVAL = 100; // ms
+
+    private final static float A1_START_VALUE = 0f;
+    private final static float A1_END_VALUE = 1f;
+    private final static int A2_START_VALUE = 100;
+    private final static int A2_END_VALUE = 200;
+
+    public ValueAnimatorTests() {
+        super(BasicAnimatorActivity.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        a1 = ValueAnimator.ofFloat(A1_START_VALUE, A1_END_VALUE).setDuration(300);
+        a2 = ValueAnimator.ofInt(A2_START_VALUE, A2_END_VALUE).setDuration(500);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        a1 = null;
+        a2 = null;
+    }
+
+    @SmallTest
+    public void testStartDelay() throws Throwable {
+        final ValueAnimator a = ValueAnimator.ofFloat(5f, 20f);
+        assertEquals(a.getStartDelay(), 0);
+        final long delay = 200;
+        a.setStartDelay(delay);
+        assertEquals(a.getStartDelay(), delay);
+
+        final MyUpdateListener listener = new MyUpdateListener();
+        a.addUpdateListener(listener);
+        final long[] startTime = new long[1];
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Test the time between isRunning() and isStarted()
+                assertFalse(a.isStarted());
+                assertFalse(a.isRunning());
+                a.start();
+                startTime[0] = SystemClock.uptimeMillis();
+                assertTrue(a.isStarted());
+                assertFalse(a.isRunning());
+            }
+        });
+
+        Thread.sleep(a.getTotalDuration());
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(listener.wasRunning);
+                assertTrue(listener.firstRunningFrameTime - startTime[0] >= delay);
+            }
+        });
+
+        Thread.sleep(a.getTotalDuration());
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(a.isStarted());
+            }
+        });
+    }
+
+    @SmallTest
+    public void testListenerCallbacks() throws Throwable {
+        final MyListener l1 = new MyListener();
+        final MyListener l2 = new MyListener();
+        a1.addListener(l1);
+        a2.addListener(l2);
+        a2.setStartDelay(400);
+
+        assertFalse(l1.startCalled);
+        assertFalse(l1.cancelCalled);
+        assertFalse(l1.endCalled);
+        assertFalse(l2.startCalled);
+        assertFalse(l2.cancelCalled);
+        assertFalse(l2.endCalled);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                a1.start();
+                a2.start();
+            }
+        });
+
+        long wait = 0;
+        Thread.sleep(POLL_INTERVAL);
+        wait += POLL_INTERVAL;
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(l1.cancelCalled);
+                a1.cancel();
+                assertTrue(l1.cancelCalled);
+                assertTrue(l1.endCalled);
+            }
+        });
+
+        while (wait < a2.getStartDelay()) {
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    // Make sure a2's start listener isn't called during start delay.
+                    assertTrue(l1.startCalled);
+                    assertFalse(l2.startCalled);
+                }
+            });
+            Thread.sleep(POLL_INTERVAL);
+            wait += POLL_INTERVAL;
+        }
+
+        long delay = Math.max(a1.getTotalDuration(), a2.getTotalDuration()) + TOLERANCE;
+        Thread.sleep(delay);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // a1 is canceled.
+                assertTrue(l1.startCalled);
+                assertTrue(l1.cancelCalled);
+                assertTrue(l1.endCalled);
+
+                // a2 is supposed to finish normally
+                assertTrue(l2.startCalled);
+                assertFalse(l2.cancelCalled);
+                assertTrue(l2.endCalled);
+            }
+        });
+    }
+
+    @SmallTest
+    public void testIsStarted() throws Throwable {
+        assertFalse(a1.isStarted());
+        assertFalse(a2.isStarted());
+        assertFalse(a1.isRunning());
+        assertFalse(a2.isRunning());
+        final long startDelay = 150;
+        a1.setStartDelay(startDelay);
+        final long[] startTime = new long[1];
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                a1.start();
+                a2.start();
+                startTime[0] = SystemClock.uptimeMillis();
+                assertTrue(a1.isStarted());
+                assertTrue(a2.isStarted());
+            }
+        });
+        long delayMs = 0;
+        while (delayMs < startDelay) {
+            Thread.sleep(POLL_INTERVAL);
+            delayMs += POLL_INTERVAL;
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    if (SystemClock.uptimeMillis() - startTime[0] < startDelay) {
+                        assertFalse(a1.isRunning());
+                    }
+                }
+            });
+        }
+
+        Thread.sleep(startDelay);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(a1.isRunning());
+                assertTrue(a2.isRunning());
+            }
+        });
+
+        long delay = Math.max(a1.getTotalDuration(), a2.getTotalDuration()) * 2;
+        Thread.sleep(delay);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(a1.isStarted());
+                assertFalse(a1.isRunning());
+                assertFalse(a2.isStarted());
+                assertFalse(a2.isRunning());
+            }
+        });
+    }
+
+    @SmallTest
+    public void testPause() throws Throwable {
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(a1.isPaused());
+                assertFalse(a2.isPaused());
+
+                a1.start();
+                a2.start();
+
+                assertFalse(a1.isPaused());
+                assertFalse(a2.isPaused());
+                assertTrue(a1.isStarted());
+                assertTrue(a2.isStarted());
+            }
+        });
+
+        Thread.sleep(POLL_INTERVAL);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(a1.isRunning());
+                assertTrue(a2.isRunning());
+                a1.pause();
+                assertTrue(a1.isPaused());
+                assertFalse(a2.isPaused());
+                assertTrue(a1.isRunning());
+            }
+        });
+
+        Thread.sleep(a2.getTotalDuration());
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // By this time, a2 should have finished, and a1 is still paused
+                assertFalse(a2.isStarted());
+                assertFalse(a2.isRunning());
+                assertTrue(a1.isStarted());
+                assertTrue(a1.isRunning());
+                assertTrue(a1.isPaused());
+
+                a1.resume();
+            }
+        });
+
+        Thread.sleep(POLL_INTERVAL);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(a1.isRunning());
+                assertTrue(a1.isStarted());
+                assertFalse(a1.isPaused());
+            }
+        });
+
+        Thread.sleep(a1.getTotalDuration());
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // a1 should finish by now.
+                assertFalse(a1.isRunning());
+                assertFalse(a1.isStarted());
+                assertFalse(a1.isPaused());
+            }
+        });
+
+    }
+
+    @SmallTest
+    public void testPauseListener() throws Throwable {
+        MyPauseListener l1 = new MyPauseListener();
+        MyPauseListener l2 = new MyPauseListener();
+        a1.addPauseListener(l1);
+        a2.addPauseListener(l2);
+
+        assertFalse(l1.pauseCalled);
+        assertFalse(l1.resumeCalled);
+        assertFalse(l2.pauseCalled);
+        assertFalse(l2.resumeCalled);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                a1.start();
+                a2.start();
+            }
+        });
+
+        Thread.sleep(a1.getTotalDuration() / 2);
+        a1.pause();
+
+        Thread.sleep(a2.getTotalDuration());
+
+        // Only a1's pause listener should be called.
+        assertTrue(l1.pauseCalled);
+        assertFalse(l1.resumeCalled);
+        a1.resume();
+
+        Thread.sleep(a1.getTotalDuration());
+
+        assertTrue(l1.pauseCalled);
+        assertTrue(l1.resumeCalled);
+        assertFalse(l2.pauseCalled);
+        assertFalse(l2.resumeCalled);
+    }
+
+    @SmallTest
+    public void testResume() throws Throwable {
+        final MyUpdateListener l1 = new MyUpdateListener();
+        final long totalDuration = a1.getTotalDuration();
+        a1.addUpdateListener(l1);
+        // Set a longer duration on a1 for this test
+        a1.setDuration(1000);
+        assertTrue(l1.firstRunningFrameTime < 0);
+        assertTrue(l1.lastUpdateTime < 0);
+
+        final long[] lastUpdate = new long[1];
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                a1.start();
+            }
+        });
+
+        Thread.sleep(totalDuration / 2);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(l1.firstRunningFrameTime > 0);
+                assertTrue(l1.lastUpdateTime > l1.firstRunningFrameTime);
+                lastUpdate[0] = l1.lastUpdateTime;
+                a1.pause();
+            }
+        });
+
+        Thread.sleep(totalDuration);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // There should be no update after pause()
+                assertEquals(lastUpdate[0], l1.lastUpdateTime);
+                a1.resume();
+            }
+        });
+
+        do {
+            Thread.sleep(POLL_INTERVAL);
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    assertTrue(l1.lastUpdateTime > lastUpdate[0]);
+                    lastUpdate[0] = l1.lastUpdateTime;
+                }
+            });
+        } while (!a1.isStarted());
+
+        // Time between pause and resume: totalDuration
+        long entireSpan = totalDuration * 2;
+        long frameDelta = l1.lastUpdateTime - l1.firstRunningFrameTime;
+        assertTrue(Math.abs(entireSpan - frameDelta) < TOLERANCE);
+    }
+
+    @SmallTest
+    public void testEndValue() throws Throwable {
+        final MyListener l1 = new MyListener();
+        a1.addListener(l1);
+
+        final MyListener l2 = new MyListener();
+        a2.addListener(l2);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                a1.start();
+                a2.start();
+            }
+        });
+
+        Thread.sleep(POLL_INTERVAL);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Animation has started but not finished, check animated values against end values
+                assertFalse(l1.endCalled);
+                assertFalse(l2.endCalled);
+                assertNotEqual(A1_END_VALUE, a1.getAnimatedValue());
+                assertNotEqual(A1_END_VALUE, a2.getAnimatedValue());
+
+                // Force a2 to end.
+                a2.end();
+            }
+        });
+
+        Thread.sleep(a1.getTotalDuration());
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(l1.cancelCalled);
+                assertTrue(l1.endCalled);
+                assertFalse(l2.cancelCalled);
+                assertTrue(l2.endCalled);
+
+                // By now a1 should have finished normally and a2 has skipped to the end, check
+                // their end values.
+                assertEquals(A1_END_VALUE, ((Float) (a1.getAnimatedValue())).floatValue());
+                assertEquals(A2_END_VALUE, ((Integer) (a2.getAnimatedValue())).intValue());
+            }
+        });
+    }
+
+    class MyUpdateListener implements ValueAnimator.AnimatorUpdateListener {
+        boolean wasRunning = false;
+        long firstRunningFrameTime = -1;
+        long lastUpdateTime = -1;
+
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            lastUpdateTime = SystemClock.uptimeMillis();
+            if (animation.isRunning() && !wasRunning) {
+                // Delay has passed
+                firstRunningFrameTime = lastUpdateTime;
+                wasRunning = animation.isRunning();
+            }
+        }
+    }
+
+    class MyListener implements Animator.AnimatorListener {
+        boolean startCalled = false;
+        boolean cancelCalled = false;
+        boolean endCalled = false;
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+            startCalled = true;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            endCalled = true;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            cancelCalled = true;
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+
+        }
+    }
+
+    class MyPauseListener implements Animator.AnimatorPauseListener {
+        boolean pauseCalled = false;
+        boolean resumeCalled = false;
+
+        @Override
+        public void onAnimationPause(Animator animation) {
+            pauseCalled = true;
+        }
+
+        @Override
+        public void onAnimationResume(Animator animation) {
+            resumeCalled = true;
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java
index d2e2131..be6e7ea 100644
--- a/core/tests/coretests/src/android/text/format/FormatterTest.java
+++ b/core/tests/coretests/src/android/text/format/FormatterTest.java
@@ -56,14 +56,14 @@
     public void testFormatBytes() {
         setLocale(Locale.ENGLISH);
 
-        checkFormatBytes(0, true, "0.00", 0);
-        checkFormatBytes(0, false, "0.00", 0);
+        checkFormatBytes(0, true, "0", 0);
+        checkFormatBytes(0, false, "0", 0);
 
-        checkFormatBytes(1, true, "1.0", 1);
-        checkFormatBytes(1, false, "1.00", 1);
+        checkFormatBytes(1, true, "1", 1);
+        checkFormatBytes(1, false, "1", 1);
 
         checkFormatBytes(12, true, "12", 12);
-        checkFormatBytes(12, false, "12.00", 12);
+        checkFormatBytes(12, false, "12", 12);
 
         checkFormatBytes(123, true, "123", 123);
         checkFormatBytes(123, false, "123", 123);
@@ -80,13 +80,15 @@
         checkFormatBytes(9123000, true, "8.7", 9122611);
         checkFormatBytes(9123000, false, "8.70", 9122611);
 
-        // The method doesn't really support negative values, but apparently people pass -1...
-        checkFormatBytes(-1, true, "-1.00", -1);
-        checkFormatBytes(-1, false, "-1.00", -1);
+        checkFormatBytes(-1, true, "-1", -1);
+        checkFormatBytes(-1, false, "-1", -1);
+
+        checkFormatBytes(-912, true, "-0.89", -911);
+        checkFormatBytes(-912, false, "-0.89", -911);
 
         // Missing FLAG_CALCULATE_ROUNDED case.
         BytesResult r = Formatter.formatBytes(getContext().getResources(), 1, 0);
-        assertEquals("1.00", r.value);
+        assertEquals("1", r.value);
         assertEquals(0, r.roundedBytes); // Didn't pass FLAG_CALCULATE_ROUNDED
 
         // Make sure it works on different locales.
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 0b94f8b..49d9115 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -18,7 +18,7 @@
 
 import android.app.Activity;
 import android.content.Intent;
-import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.GetChars;
 import android.text.Selection;
@@ -27,11 +27,15 @@
 /**
  * TextViewTest tests {@link TextView}.
  */
-public class TextViewTest extends AndroidTestCase {
+public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActivity> {
+
+    public TextViewTest() {
+        super(TextViewActivity.class);
+    }
 
     @SmallTest
     public void testArray() throws Exception {
-        TextView tv = new TextView(mContext);
+        TextView tv = new TextView(getActivity());
 
         char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ',
                                 'W', 'o', 'r', 'l', 'd', '!' };
@@ -59,25 +63,34 @@
         assertEquals('\0', c2[5]);
     }
 
+    @SmallTest
     public void testProcessTextActivityResultNonEditable() {
-        TextView tv = new TextView(mContext);
+        final TextView tv = new TextView(getActivity());
         CharSequence originalText = "This is some text.";
         tv.setText(originalText, TextView.BufferType.SPANNABLE);
         assertEquals(originalText, tv.getText().toString());
         tv.setTextIsSelectable(true);
         Selection.setSelection((Spannable) tv.getText(), 0, tv.getText().length());
 
-        CharSequence newText = "Text is replaced.";
-        Intent data = new Intent();
-        data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
-        tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
+        // We need to run this in the UI thread, as it will create a Toast.
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                CharSequence newText = "Text is replaced.";
+                Intent data = new Intent();
+                data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
+                tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
 
         // This is a TextView, which can't be modified. Hence no change should have been made.
         assertEquals(originalText, tv.getText().toString());
     }
 
+    @SmallTest
     public void testProcessTextActivityResultEditable() {
-        EditText tv = new EditText(mContext);
+        EditText tv = new EditText(getActivity());
         CharSequence originalText = "This is some text.";
         tv.setText(originalText, TextView.BufferType.SPANNABLE);
         assertEquals(originalText, tv.getText().toString());
@@ -92,8 +105,9 @@
         assertEquals(newText, tv.getText().toString());
     }
 
+    @SmallTest
     public void testProcessTextActivityResultCancel() {
-        EditText tv = new EditText(mContext);
+        EditText tv = new EditText(getActivity());
         CharSequence originalText = "This is some text.";
         tv.setText(originalText, TextView.BufferType.SPANNABLE);
         assertEquals(originalText, tv.getText().toString());
@@ -108,8 +122,9 @@
         assertEquals(originalText, tv.getText().toString());
     }
 
+    @SmallTest
     public void testProcessTextActivityNoData() {
-        EditText tv = new EditText(mContext);
+        EditText tv = new EditText(getActivity());
         CharSequence originalText = "This is some text.";
         tv.setText(originalText, TextView.BufferType.SPANNABLE);
         assertEquals(originalText, tv.getText().toString());
diff --git a/docs/html/design/media/wear/1-tap-launch.png b/docs/html/design/media/wear/1-tap-launch.png
new file mode 100644
index 0000000..c0c9aca
--- /dev/null
+++ b/docs/html/design/media/wear/1-tap-launch.png
Binary files differ
diff --git a/docs/html/design/media/wear/2-tap-launch.png b/docs/html/design/media/wear/2-tap-launch.png
new file mode 100644
index 0000000..395a3ce
--- /dev/null
+++ b/docs/html/design/media/wear/2-tap-launch.png
Binary files differ
diff --git a/docs/html/design/media/wear/aesthetic.png b/docs/html/design/media/wear/aesthetic.png
new file mode 100644
index 0000000..f6e5f3e
--- /dev/null
+++ b/docs/html/design/media/wear/aesthetic.png
Binary files differ
diff --git a/docs/html/design/media/wear/available_gestures.png b/docs/html/design/media/wear/available_gestures.png
new file mode 100644
index 0000000..677076b
--- /dev/null
+++ b/docs/html/design/media/wear/available_gestures.png
Binary files differ
diff --git a/docs/html/design/media/wear/available_gestures_2x.png b/docs/html/design/media/wear/available_gestures_2x.png
new file mode 100644
index 0000000..eced0c7
--- /dev/null
+++ b/docs/html/design/media/wear/available_gestures_2x.png
Binary files differ
diff --git a/docs/html/design/media/wear/changing-target.png b/docs/html/design/media/wear/changing-target.png
new file mode 100644
index 0000000..427531f
--- /dev/null
+++ b/docs/html/design/media/wear/changing-target.png
Binary files differ
diff --git a/docs/html/design/media/wear/revealing-info.png b/docs/html/design/media/wear/revealing-info.png
new file mode 100644
index 0000000..e419e9f
--- /dev/null
+++ b/docs/html/design/media/wear/revealing-info.png
Binary files differ
diff --git a/docs/html/design/media/wear/toggling-states.png b/docs/html/design/media/wear/toggling-states.png
new file mode 100644
index 0000000..93398e6
--- /dev/null
+++ b/docs/html/design/media/wear/toggling-states.png
Binary files differ
diff --git a/docs/html/design/media/wear/visual_feedback.gif b/docs/html/design/media/wear/visual_feedback.gif
new file mode 100644
index 0000000..e07000a
--- /dev/null
+++ b/docs/html/design/media/wear/visual_feedback.gif
Binary files differ
diff --git a/docs/html/design/wear/watchfaces.jd b/docs/html/design/wear/watchfaces.jd
index e018523..c8c6d5a 100644
--- a/docs/html/design/wear/watchfaces.jd
+++ b/docs/html/design/wear/watchfaces.jd
@@ -288,6 +288,107 @@
 with an actual watch screen before you start coding.</p>
 
 
+<h2 id="interactive">Design Interactive Watch Faces</h2>
+
+<p>Your watch face can respond to a single-tap gesture from the user, as long as
+there’s not another UI element that also responds to that gesture. Some possible use cases for
+interacting with the watch face include:</p>
+
+<ul>
+   <li><strong>Causing an aesthetic change</strong> on the watch face, for example inverting
+         the color scheme.</li>
+   <li><strong>Showing more information</strong> inline on the watch face, for example displaying a
+         detailed step count.</li>
+   <li><strong>Completing an action</strong> inline or in the background, for example starting a
+         timer.</li>
+   <li><strong>Launching a specific activity,</strong> for example a starting a conversation in a
+   messaging application.</li>
+</ul>
+
+<h3 id="ag">Available gestures</h3>
+<p>Only single taps are available. This restriction is important for maintaining clear and
+consistent system interactions, and for making watch face interactions as simple as
+possible: Neither you nor the user should think of watch faces as full-fledged apps. Figure 1
+summarizes the categories of gestures, and their uses.</p>
+
+<img src="{@docRoot}design/media/wear/available_gestures.png"
+srcset="{@docRoot}design/media/wear/available_gestures.png 1x,
+{@docRoot}design/media/wear/available_gestures_2x.png 2x"
+alt="Single tap is the only available gesture." width="740" height="" id="available-gestures" />
+<p class="img-caption">
+  <strong>Figure 1.</strong> Available, reserved, and blocked gestures.
+</p>
+
+As a rule, watch-face interaction should be lightweight, with the user completing their desired
+action within one or two touches.
+
+<h3>Tap targets</h3>
+
+<p>If you want to cause a simple state change on the watch face, such as a purely aesthetic
+change, you can use the entire canvas of the watch face as the tap target.</p>
+
+<p>For a more significant change or action, such as launching an activity or sending a message to a
+friend, it’s important to keep targets smaller, between 48-90 dpi, to avoid false-positive taps.
+There should be a gap between targets of at least 8-16 dpi. For an optimized tappable experience,
+display a maximum of 7 to 9 targets at once.</p>
+
+<h3 id=”areas”>Tap regions</h3>
+
+<p>You can also use different regions of the screen to trigger different changes to the watch face.
+For example, tapping on the entire canvas could toggle states for the entire face. Tapping a specific target
+could produce an inline display of information related to the target. Last, tapping outside the
+target could restore the watch face to its default state.</p>
+
+<div style="float:right;margin-bottom:20px;margin-left:20px">
+  <img src="/design/media/wear/visual_feedback.gif" width="200"
+       height="196" alt="The watch face should show where the user’s finger has made contact." style="margin-top:-10px;margin-left:13px">
+</div>
+
+
+<h3>Visual feedback</h3>
+
+<p>Provide visual feedback when the user’s finger touches down on the watch face. The tap
+event does not trigger until the user lifts their finger, but visual feedback on touchdown helps
+indicate that the system has received the touch, and also helps the user know where the touch
+landed.</p>
+
+<p class=”warning”><strong>Warning:</strong> Do not immediately launch a UI on touchdown. A UI that
+you launch on touchdown conflicts with gestures for interacting with system UI elements including
+the watch face picker, notification stream, settings shade, and app launcher.</p>
+
+<h3>Design examples</h3>
+
+Here are some examples of approaches for interactive watch faces:
+
+<h4>Applying an aesthetic change</h4>
+
+<img src="{@docRoot}design/media/wear/aesthetic.png"
+alt="" width="686" height="" id="descriptive-id" />
+
+<h4>Toggling states</h4>
+
+<img src="{@docRoot}design/media/wear/toggling-states.png"
+alt="" width="686" height="" id="descriptive-id" />
+
+<h4>Changing a targeted UI element</h4>
+
+<img src="{@docRoot}design/media/wear/changing-target.png"
+alt="" width="686" height="" id="descriptive-id" />
+
+<h4>Revealing information inline</h4>
+
+<img src="{@docRoot}design/media/wear/revealing-info.png"
+alt="" width="686" height="" id="descriptive-id" />
+
+<h4>Launching an activity with a single tap</h4>
+
+<img src="{@docRoot}design/media/wear/1-tap-launch.png"
+alt="" width="751" height="" id="descriptive-id" />
+
+<h4>Launching an activity with two taps</h4>
+
+<img src="{@docRoot}design/media/wear/2-tap-launch.png"
+alt="" width="751" height="" id="descriptive-id" />
 
 <h2 id="CompanionApp">Support the Android Wear Companion App</h2>
 
diff --git a/docs/html/reference/android/support/wearable/R.anim.html b/docs/html/reference/android/support/wearable/R.anim.html
index 11d766d..8976afe 100644
--- a/docs/html/reference/android/support/wearable/R.anim.html
+++ b/docs/html/reference/android/support/wearable/R.anim.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1322,6 +1323,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.animator.html b/docs/html/reference/android/support/wearable/R.animator.html
index 9fa6445..7ab63f2 100644
--- a/docs/html/reference/android/support/wearable/R.animator.html
+++ b/docs/html/reference/android/support/wearable/R.animator.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1134,6 +1135,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.attr.html b/docs/html/reference/android/support/wearable/R.attr.html
index 1f043a2..099c981 100644
--- a/docs/html/reference/android/support/wearable/R.attr.html
+++ b/docs/html/reference/android/support/wearable/R.attr.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -697,6 +698,23 @@
           static
           
           int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#buttonRippleColor">buttonRippleColor</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+            
+    
+
+          </td>
+      </tr>
+      
+    
+      <tr class=" api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          
+          int</nobr></td>
           <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#circle_border_color">circle_border_color</a></td>
           <td class="jd-descrcol" width="100%">
             <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
@@ -708,7 +726,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -724,7 +742,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -741,7 +759,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -757,7 +775,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -773,7 +791,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -789,7 +807,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -805,7 +823,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -821,6 +839,23 @@
       </tr>
       
     
+      <tr class=" api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          
+          int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#color_sequence">color_sequence</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+            
+    
+
+          </td>
+      </tr>
+      
+    
       <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
@@ -1054,6 +1089,55 @@
           static
           
           int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#image_circle_percentage">image_circle_percentage</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+            
+    
+
+          </td>
+      </tr>
+      
+    
+      <tr class=" api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          
+          int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#image_horizontal_offcenter_percentage">image_horizontal_offcenter_percentage</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+            
+    
+
+          </td>
+      </tr>
+      
+    
+      <tr class="alt-color api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          
+          int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#image_tint">image_tint</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+            
+    
+
+          </td>
+      </tr>
+      
+    
+      <tr class=" api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          
+          int</nobr></td>
           <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#layout_box">layout_box</a></td>
           <td class="jd-descrcol" width="100%">
             <p>Must be one or more (separated by '|') of the following constant values.
@@ -1064,7 +1148,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1080,7 +1164,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1096,7 +1180,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1112,7 +1196,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1128,7 +1212,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1144,7 +1228,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1160,7 +1244,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1176,7 +1260,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1192,7 +1276,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1208,7 +1292,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1224,13 +1308,13 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
           
           int</nobr></td>
-          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#pressedTranslationZ">pressedTranslationZ</a></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#pressedButtonTranslationZ">pressedButtonTranslationZ</a></td>
           <td class="jd-descrcol" width="100%">
             <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
             
@@ -1240,7 +1324,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1257,23 +1341,6 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
-          <td class="jd-typecol"><nobr>
-          public
-          static
-          
-          int</nobr></td>
-          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html#rippleColor">rippleColor</a></td>
-          <td class="jd-descrcol" width="100%">
-            <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
-or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
-            
-    
-
-          </td>
-      </tr>
-      
-    
       <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
@@ -1605,6 +1672,41 @@
 
 
 
+<A NAME="buttonRippleColor"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        buttonRippleColor
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+</p></div>
+
+    
+    </div>
+</div>
+
+
+
 <A NAME="circle_border_color"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -1921,6 +2023,41 @@
 
 
 
+<A NAME="color_sequence"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        color_sequence
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+</p></div>
+
+    
+    </div>
+</div>
+
+
+
 <A NAME="dotColor"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -2457,6 +2594,122 @@
 
 
 
+<A NAME="image_circle_percentage"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        image_circle_percentage
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+</p></div>
+
+    
+    </div>
+</div>
+
+
+
+<A NAME="image_horizontal_offcenter_percentage"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        image_horizontal_offcenter_percentage
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+</p></div>
+
+    
+    </div>
+</div>
+
+
+
+<A NAME="image_tint"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        image_tint
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+</p></div>
+
+    
+    </div>
+</div>
+
+
+
 <A NAME="layout_box"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -2903,7 +3156,7 @@
 
 
 
-<A NAME="pressedTranslationZ"></A>
+<A NAME="pressedButtonTranslationZ"></A>
 
 <div class="jd-details api apilevel-"> 
     <h4 class="jd-details-title">
@@ -2913,7 +3166,7 @@
          
         int
       </span>
-        pressedTranslationZ
+        pressedButtonTranslationZ
     </h4>
       <div class="api-level">
         
@@ -2975,41 +3228,6 @@
 
 
 
-<A NAME="rippleColor"></A>
-
-<div class="jd-details api apilevel-"> 
-    <h4 class="jd-details-title">
-      <span class="normal">
-        public 
-        static 
-         
-        int
-      </span>
-        rippleColor
-    </h4>
-      <div class="api-level">
-        
-        
-  
-
-      </div>
-    <div class="jd-details-descr">
-      
-    
-
-      
-  <div class="jd-tagdata jd-tagdescr"><p><p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
-or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
-<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
-"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
-</p></div>
-
-    
-    </div>
-</div>
-
-
-
 <A NAME="roundLayout"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -3233,6 +3451,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.color.html b/docs/html/reference/android/support/wearable/R.color.html
index cdfd0a8..07b5e0c 100644
--- a/docs/html/reference/android/support/wearable/R.color.html
+++ b/docs/html/reference/android/support/wearable/R.color.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -2450,6 +2451,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.dimen.html b/docs/html/reference/android/support/wearable/R.dimen.html
index c24ef8d..215b2b3 100644
--- a/docs/html/reference/android/support/wearable/R.dimen.html
+++ b/docs/html/reference/android/support/wearable/R.dimen.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1839,6 +1840,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.drawable.html b/docs/html/reference/android/support/wearable/R.drawable.html
index 167c8ab..c83cd2e 100644
--- a/docs/html/reference/android/support/wearable/R.drawable.html
+++ b/docs/html/reference/android/support/wearable/R.drawable.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1557,6 +1558,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.html b/docs/html/reference/android/support/wearable/R.html
index fd87f79..714f287 100644
--- a/docs/html/reference/android/support/wearable/R.html
+++ b/docs/html/reference/android/support/wearable/R.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="selected api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -717,7 +718,7 @@
          
         
         class</nobr></td>
-      <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></td>
+      <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></td>
       <td class="jd-descrcol" width="100%">
         &nbsp;
         
@@ -734,6 +735,23 @@
          
         
         class</nobr></td>
+      <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></td>
+      <td class="jd-descrcol" width="100%">
+        &nbsp;
+        
+    
+
+      </td>
+    </tr>
+    
+    
+    <tr class="alt-color api apilevel-" >
+      <td class="jd-typecol"><nobr>
+        
+         
+         
+        
+        class</nobr></td>
       <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></td>
       <td class="jd-descrcol" width="100%">
         &nbsp;
@@ -744,7 +762,7 @@
     </tr>
     
     
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
       <td class="jd-typecol"><nobr>
         
          
@@ -761,7 +779,7 @@
     </tr>
     
     
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
       <td class="jd-typecol"><nobr>
         
          
@@ -778,7 +796,7 @@
     </tr>
     
     
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
       <td class="jd-typecol"><nobr>
         
          
@@ -795,7 +813,7 @@
     </tr>
     
     
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
       <td class="jd-typecol"><nobr>
         
          
@@ -812,7 +830,7 @@
     </tr>
     
     
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
       <td class="jd-typecol"><nobr>
         
          
@@ -829,7 +847,7 @@
     </tr>
     
     
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
       <td class="jd-typecol"><nobr>
         
          
@@ -846,7 +864,7 @@
     </tr>
     
     
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
       <td class="jd-typecol"><nobr>
         
          
@@ -863,7 +881,7 @@
     </tr>
     
     
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
       <td class="jd-typecol"><nobr>
         
          
@@ -1283,6 +1301,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.id.html b/docs/html/reference/android/support/wearable/R.id.html
index 2b3db85..c6bad3b 100644
--- a/docs/html/reference/android/support/wearable/R.id.html
+++ b/docs/html/reference/android/support/wearable/R.id.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -2262,6 +2263,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.interpolator.html b/docs/html/reference/android/support/wearable/R.interpolator.html
index ae6cac1..01391a8 100644
--- a/docs/html/reference/android/support/wearable/R.interpolator.html
+++ b/docs/html/reference/android/support/wearable/R.interpolator.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1369,6 +1370,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.layout.html b/docs/html/reference/android/support/wearable/R.layout.html
index 7a87cf2..4987ba7 100644
--- a/docs/html/reference/android/support/wearable/R.layout.html
+++ b/docs/html/reference/android/support/wearable/R.layout.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1275,6 +1276,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.string.html b/docs/html/reference/android/support/wearable/R.string.html
index 3d13614..c8707ef 100644
--- a/docs/html/reference/android/support/wearable/R.string.html
+++ b/docs/html/reference/android/support/wearable/R.string.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1134,6 +1135,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.style.html b/docs/html/reference/android/support/wearable/R.style.html
index 48837d0..38ce308 100644
--- a/docs/html/reference/android/support/wearable/R.style.html
+++ b/docs/html/reference/android/support/wearable/R.style.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -2262,6 +2263,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/R.styleable.html b/docs/html/reference/android/support/wearable/R.styleable.html
index d1e4ca3..e43e070 100644
--- a/docs/html/reference/android/support/wearable/R.styleable.html
+++ b/docs/html/reference/android/support/wearable/R.styleable.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -473,6 +473,7 @@
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+          <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
           <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -614,7 +615,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1137,6 +1138,23 @@
           static
           
           int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_buttonRippleColor">ActionPage_buttonRippleColor</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#buttonRippleColor">buttonRippleColor</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
+            
+    
+
+          </td>
+      </tr>
+      
+    
+      <tr class=" api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          
+          int</nobr></td>
           <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_imageScaleMode">ActionPage_imageScaleMode</a></td>
           <td class="jd-descrcol" width="100%">
             <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#imageScaleMode">imageScaleMode</a></code>
@@ -1148,7 +1166,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1165,7 +1183,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1182,32 +1200,15 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
-          <td class="jd-typecol"><nobr>
-          public
-          static
-          
-          int</nobr></td>
-          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedTranslationZ">ActionPage_pressedTranslationZ</a></td>
-          <td class="jd-descrcol" width="100%">
-            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedTranslationZ">pressedTranslationZ</a></code>
-          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
-            
-    
-
-          </td>
-      </tr>
-      
-    
       <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
           
           int</nobr></td>
-          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_rippleColor">ActionPage_rippleColor</a></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedButtonTranslationZ">ActionPage_pressedButtonTranslationZ</a></td>
           <td class="jd-descrcol" width="100%">
-            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#rippleColor">rippleColor</a></code>
+            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedButtonTranslationZ">pressedButtonTranslationZ</a></code>
           attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
             
     
@@ -1390,6 +1391,57 @@
           static
           
           int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_circle_percentage">CircledImageView_image_circle_percentage</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_circle_percentage">image_circle_percentage</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+            
+    
+
+          </td>
+      </tr>
+      
+    
+      <tr class="alt-color api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          
+          int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_horizontal_offcenter_percentage">CircledImageView_image_horizontal_offcenter_percentage</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_horizontal_offcenter_percentage">image_horizontal_offcenter_percentage</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+            
+    
+
+          </td>
+      </tr>
+      
+    
+      <tr class=" api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          
+          int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_tint">CircledImageView_image_tint</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_tint">image_tint</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+            
+    
+
+          </td>
+      </tr>
+      
+    
+      <tr class="alt-color api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          
+          int</nobr></td>
           <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_shadow_width">CircledImageView_shadow_width</a></td>
           <td class="jd-descrcol" width="100%">
             <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#shadow_width">shadow_width</a></code>
@@ -1401,7 +1453,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1417,7 +1469,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1434,7 +1486,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1451,7 +1503,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1468,7 +1520,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1485,6 +1537,23 @@
       </tr>
       
     
+      <tr class="alt-color api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          
+          int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_buttonRippleColor">CircularButton_buttonRippleColor</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#buttonRippleColor">buttonRippleColor</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
+            
+    
+
+          </td>
+      </tr>
+      
+    
       <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
@@ -1508,9 +1577,9 @@
           static
           
           int</nobr></td>
-          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedTranslationZ">CircularButton_pressedTranslationZ</a></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedButtonTranslationZ">CircularButton_pressedButtonTranslationZ</a></td>
           <td class="jd-descrcol" width="100%">
-            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedTranslationZ">pressedTranslationZ</a></code>
+            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedButtonTranslationZ">pressedButtonTranslationZ</a></code>
           attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
             
     
@@ -1523,23 +1592,6 @@
           <td class="jd-typecol"><nobr>
           public
           static
-          
-          int</nobr></td>
-          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_rippleColor">CircularButton_rippleColor</a></td>
-          <td class="jd-descrcol" width="100%">
-            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#rippleColor">rippleColor</a></code>
-          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
-            
-    
-
-          </td>
-      </tr>
-      
-    
-      <tr class="alt-color api apilevel-" >
-          <td class="jd-typecol"><nobr>
-          public
-          static
           final
           int[]</nobr></td>
           <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#DelayedConfirmationView">DelayedConfirmationView</a></td>
@@ -1552,7 +1604,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1569,7 +1621,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1585,7 +1637,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1602,7 +1654,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1619,7 +1671,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1636,7 +1688,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1653,7 +1705,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1670,7 +1722,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1687,7 +1739,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1704,7 +1756,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1721,7 +1773,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1738,7 +1790,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1755,7 +1807,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1772,7 +1824,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1789,7 +1841,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1806,10 +1858,43 @@
       </tr>
       
     
+      <tr class=" api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
+          final
+          int[]</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner">ProgressSpinner</a></td>
+          <td class="jd-descrcol" width="100%">
+            Attributes that can be used with a ProgressSpinner.
+            
+    
+
+          </td>
+      </tr>
+      
+    
       <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
+          
+          int</nobr></td>
+          <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner_color_sequence">ProgressSpinner_color_sequence</a></td>
+          <td class="jd-descrcol" width="100%">
+            <p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#color_sequence">color_sequence</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner">ProgressSpinner</a></code> array.
+            
+    
+
+          </td>
+      </tr>
+      
+    
+      <tr class=" api apilevel-" >
+          <td class="jd-typecol"><nobr>
+          public
+          static
           final
           int[]</nobr></td>
           <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html#WatchViewStub">WatchViewStub</a></td>
@@ -1822,7 +1907,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1839,7 +1924,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1856,7 +1941,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1872,7 +1957,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1889,7 +1974,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1906,7 +1991,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1923,7 +2008,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1940,7 +2025,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1957,7 +2042,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1974,7 +2059,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -1991,7 +2076,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -2008,7 +2093,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -2025,7 +2110,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -2042,7 +2127,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -2059,7 +2144,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -2076,7 +2161,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -2092,7 +2177,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -2109,7 +2194,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
           <td class="jd-typecol"><nobr>
           public
           static
@@ -2875,15 +2960,15 @@
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textColor">android:textColor</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textStyle">android:textStyle</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_typeface">android:typeface</a></code></code></td><td></td></tr>
+           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_buttonRippleColor">android.support.wearable:buttonRippleColor</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_imageScaleMode">android.support.wearable:imageScaleMode</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_maxTextSize">android.support.wearable:maxTextSize</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_minTextSize">android.support.wearable:minTextSize</a></code></code></td><td></td></tr>
-           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedTranslationZ">android.support.wearable:pressedTranslationZ</a></code></code></td><td></td></tr>
-           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_rippleColor">android.support.wearable:rippleColor</a></code></code></td><td></td></tr>
+           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedButtonTranslationZ">android.support.wearable:pressedButtonTranslationZ</a></code></code></td><td></td></tr>
            </table></p></div>
   <div class="jd-tagdata">
       <h5 class="jd-tagtitle">See Also</h5>
-      <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_color">ActionPage_android_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_elevation">ActionPage_android_elevation</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_fontFamily">ActionPage_android_fontFamily</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_gravity">ActionPage_android_gravity</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_lineSpacingExtra">ActionPage_android_lineSpacingExtra</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_lineSpacingMultiplier">ActionPage_android_lineSpacingMultiplier</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_maxLines">ActionPage_android_maxLines</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_src">ActionPage_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_stateListAnimator">ActionPage_android_stateListAnimator</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_text">ActionPage_android_text</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textColor">ActionPage_android_textColor</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textStyle">ActionPage_android_textStyle</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_typeface">ActionPage_android_typeface</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_imageScaleMode">ActionPage_imageScaleMode</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_maxTextSize">ActionPage_maxTextSize</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_minTextSize">ActionPage_minTextSize</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedTranslationZ">ActionPage_pressedTranslationZ</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_rippleColor">ActionPage_rippleColor</a></code></li>
+      <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_color">ActionPage_android_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_elevation">ActionPage_android_elevation</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_fontFamily">ActionPage_android_fontFamily</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_gravity">ActionPage_android_gravity</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_lineSpacingExtra">ActionPage_android_lineSpacingExtra</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_lineSpacingMultiplier">ActionPage_android_lineSpacingMultiplier</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_maxLines">ActionPage_android_maxLines</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_src">ActionPage_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_stateListAnimator">ActionPage_android_stateListAnimator</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_text">ActionPage_android_text</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textColor">ActionPage_android_textColor</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_textStyle">ActionPage_android_textStyle</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_android_typeface">ActionPage_android_typeface</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_buttonRippleColor">ActionPage_buttonRippleColor</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_imageScaleMode">ActionPage_imageScaleMode</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_maxTextSize">ActionPage_maxTextSize</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_minTextSize">ActionPage_minTextSize</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage_pressedButtonTranslationZ">ActionPage_pressedButtonTranslationZ</a></code></li>
       </ul>
   </div>
 
@@ -3309,6 +3394,44 @@
 
 
 
+<A NAME="ActionPage_buttonRippleColor"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        ActionPage_buttonRippleColor
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#buttonRippleColor">buttonRippleColor</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
+
+
+          <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".</p></div>
+
+    
+    </div>
+</div>
+
+
+
 <A NAME="ActionPage_imageScaleMode"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -3436,7 +3559,7 @@
 
 
 
-<A NAME="ActionPage_pressedTranslationZ"></A>
+<A NAME="ActionPage_pressedButtonTranslationZ"></A>
 
 <div class="jd-details api apilevel-"> 
     <h4 class="jd-details-title">
@@ -3446,7 +3569,7 @@
          
         int
       </span>
-        ActionPage_pressedTranslationZ
+        ActionPage_pressedButtonTranslationZ
     </h4>
       <div class="api-level">
         
@@ -3459,7 +3582,7 @@
     
 
       
-  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedTranslationZ">pressedTranslationZ</a></code>
+  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedButtonTranslationZ">pressedButtonTranslationZ</a></code>
           attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
 
 
@@ -3478,44 +3601,6 @@
 
 
 
-<A NAME="ActionPage_rippleColor"></A>
-
-<div class="jd-details api apilevel-"> 
-    <h4 class="jd-details-title">
-      <span class="normal">
-        public 
-        static 
-         
-        int
-      </span>
-        ActionPage_rippleColor
-    </h4>
-      <div class="api-level">
-        
-        
-  
-
-      </div>
-    <div class="jd-details-descr">
-      
-    
-
-      
-  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#rippleColor">rippleColor</a></code>
-          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ActionPage">ActionPage</a></code> array.
-
-
-          <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
-or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
-<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
-"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".</p></div>
-
-    
-    </div>
-</div>
-
-
-
 <A NAME="BoxInsetLayout_Layout"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -3641,11 +3726,14 @@
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_padding">android.support.wearable:circle_padding</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius">android.support.wearable:circle_radius</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius_pressed">android.support.wearable:circle_radius_pressed</a></code></code></td><td></td></tr>
+           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_circle_percentage">android.support.wearable:image_circle_percentage</a></code></code></td><td></td></tr>
+           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_horizontal_offcenter_percentage">android.support.wearable:image_horizontal_offcenter_percentage</a></code></code></td><td></td></tr>
+           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_tint">android.support.wearable:image_tint</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_shadow_width">android.support.wearable:shadow_width</a></code></code></td><td></td></tr>
            </table></p></div>
   <div class="jd-tagdata">
       <h5 class="jd-tagtitle">See Also</h5>
-      <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_android_src">CircledImageView_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_border_color">CircledImageView_circle_border_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_border_width">CircledImageView_circle_border_width</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_color">CircledImageView_circle_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_padding">CircledImageView_circle_padding</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius">CircledImageView_circle_radius</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius_pressed">CircledImageView_circle_radius_pressed</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_shadow_width">CircledImageView_shadow_width</a></code></li>
+      <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_android_src">CircledImageView_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_border_color">CircledImageView_circle_border_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_border_width">CircledImageView_circle_border_width</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_color">CircledImageView_circle_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_padding">CircledImageView_circle_padding</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius">CircledImageView_circle_radius</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_circle_radius_pressed">CircledImageView_circle_radius_pressed</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_circle_percentage">CircledImageView_image_circle_percentage</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_horizontal_offcenter_percentage">CircledImageView_image_horizontal_offcenter_percentage</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_image_tint">CircledImageView_image_tint</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView_shadow_width">CircledImageView_shadow_width</a></code></li>
       </ul>
   </div>
 
@@ -3937,6 +4025,131 @@
 
 
 
+<A NAME="CircledImageView_image_circle_percentage"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        CircledImageView_image_circle_percentage
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_circle_percentage">image_circle_percentage</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.</p></div>
+
+    
+    </div>
+</div>
+
+
+
+<A NAME="CircledImageView_image_horizontal_offcenter_percentage"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        CircledImageView_image_horizontal_offcenter_percentage
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_horizontal_offcenter_percentage">image_horizontal_offcenter_percentage</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.</p></div>
+
+    
+    </div>
+</div>
+
+
+
+<A NAME="CircledImageView_image_tint"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        CircledImageView_image_tint
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#image_tint">image_tint</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircledImageView">CircledImageView</a></code> array.
+
+
+          <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.</p></div>
+
+    
+    </div>
+</div>
+
+
+
 <A NAME="CircledImageView_shadow_width"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -4012,13 +4225,13 @@
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_elevation">android:elevation</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_src">android:src</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_stateListAnimator">android:stateListAnimator</a></code></code></td><td></td></tr>
+           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_buttonRippleColor">android.support.wearable:buttonRippleColor</a></code></code></td><td></td></tr>
            <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_imageScaleMode">android.support.wearable:imageScaleMode</a></code></code></td><td></td></tr>
-           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedTranslationZ">android.support.wearable:pressedTranslationZ</a></code></code></td><td></td></tr>
-           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_rippleColor">android.support.wearable:rippleColor</a></code></code></td><td></td></tr>
+           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedButtonTranslationZ">android.support.wearable:pressedButtonTranslationZ</a></code></code></td><td></td></tr>
            </table></p></div>
   <div class="jd-tagdata">
       <h5 class="jd-tagtitle">See Also</h5>
-      <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_color">CircularButton_android_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_elevation">CircularButton_android_elevation</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_src">CircularButton_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_stateListAnimator">CircularButton_android_stateListAnimator</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_imageScaleMode">CircularButton_imageScaleMode</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedTranslationZ">CircularButton_pressedTranslationZ</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_rippleColor">CircularButton_rippleColor</a></code></li>
+      <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_color">CircularButton_android_color</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_elevation">CircularButton_android_elevation</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_src">CircularButton_android_src</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_android_stateListAnimator">CircularButton_android_stateListAnimator</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_buttonRippleColor">CircularButton_buttonRippleColor</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_imageScaleMode">CircularButton_imageScaleMode</a></code></li><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton_pressedButtonTranslationZ">CircularButton_pressedButtonTranslationZ</a></code></li>
       </ul>
   </div>
 
@@ -4156,6 +4369,44 @@
 
 
 
+<A NAME="CircularButton_buttonRippleColor"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        CircularButton_buttonRippleColor
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#buttonRippleColor">buttonRippleColor</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
+
+
+          <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".</p></div>
+
+    
+    </div>
+</div>
+
+
+
 <A NAME="CircularButton_imageScaleMode"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -4199,7 +4450,7 @@
 
 
 
-<A NAME="CircularButton_pressedTranslationZ"></A>
+<A NAME="CircularButton_pressedButtonTranslationZ"></A>
 
 <div class="jd-details api apilevel-"> 
     <h4 class="jd-details-title">
@@ -4209,7 +4460,7 @@
          
         int
       </span>
-        CircularButton_pressedTranslationZ
+        CircularButton_pressedButtonTranslationZ
     </h4>
       <div class="api-level">
         
@@ -4222,7 +4473,7 @@
     
 
       
-  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedTranslationZ">pressedTranslationZ</a></code>
+  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#pressedButtonTranslationZ">pressedButtonTranslationZ</a></code>
           attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
 
 
@@ -4241,44 +4492,6 @@
 
 
 
-<A NAME="CircularButton_rippleColor"></A>
-
-<div class="jd-details api apilevel-"> 
-    <h4 class="jd-details-title">
-      <span class="normal">
-        public 
-        static 
-         
-        int
-      </span>
-        CircularButton_rippleColor
-    </h4>
-      <div class="api-level">
-        
-        
-  
-
-      </div>
-    <div class="jd-details-descr">
-      
-    
-
-      
-  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#rippleColor">rippleColor</a></code>
-          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#CircularButton">CircularButton</a></code> array.
-
-
-          <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
-or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
-<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
-"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".</p></div>
-
-    
-    </div>
-</div>
-
-
-
 <A NAME="DelayedConfirmationView"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -4952,6 +5165,87 @@
 
 
 
+<A NAME="ProgressSpinner"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+        final 
+        int[]
+      </span>
+        ProgressSpinner
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Attributes that can be used with a ProgressSpinner.
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner_color_sequence">android.support.wearable:color_sequence</a></code></code></td><td></td></tr>
+           </table></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">See Also</h5>
+      <ul class="nolist"><li><code><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner_color_sequence">ProgressSpinner_color_sequence</a></code></li>
+      </ul>
+  </div>
+
+    
+    </div>
+</div>
+
+
+
+<A NAME="ProgressSpinner_color_sequence"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+         
+        int
+      </span>
+        ProgressSpinner_color_sequence
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p><p>This symbol is the offset where the <code><a href="../../../../reference/android/support/wearable/R.attr.html#color_sequence">color_sequence</a></code>
+          attribute's value can be found in the <code><a href="../../../../reference/android/support/wearable/R.styleable.html#ProgressSpinner">ProgressSpinner</a></code> array.
+
+
+          <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".</p></div>
+
+    
+    </div>
+</div>
+
+
+
 <A NAME="WatchViewStub"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -5847,6 +6141,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/activity/ConfirmationActivity.html b/docs/html/reference/android/support/wearable/activity/ConfirmationActivity.html
index f7cd613..92bfeca 100644
--- a/docs/html/reference/android/support/wearable/activity/ConfirmationActivity.html
+++ b/docs/html/reference/android/support/wearable/activity/ConfirmationActivity.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -713,7 +713,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -10110,6 +10110,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/activity/WearableActivity.html b/docs/html/reference/android/support/wearable/activity/WearableActivity.html
index 2698dca..6f70f74 100644
--- a/docs/html/reference/android/support/wearable/activity/WearableActivity.html
+++ b/docs/html/reference/android/support/wearable/activity/WearableActivity.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -716,7 +716,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -10513,6 +10513,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/activity/package-summary.html b/docs/html/reference/android/support/wearable/activity/package-summary.html
index 4dd01b7..e3a691a 100644
--- a/docs/html/reference/android/support/wearable/activity/package-summary.html
+++ b/docs/html/reference/android/support/wearable/activity/package-summary.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -542,7 +542,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 
 
 
@@ -654,6 +654,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/companion/WatchFaceCompanion.html b/docs/html/reference/android/support/wearable/companion/WatchFaceCompanion.html
index ce369f2..8174777 100644
--- a/docs/html/reference/android/support/wearable/companion/WatchFaceCompanion.html
+++ b/docs/html/reference/android/support/wearable/companion/WatchFaceCompanion.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -599,7 +599,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1158,6 +1158,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/companion/package-summary.html b/docs/html/reference/android/support/wearable/companion/package-summary.html
index 0447708..7404dcd 100644
--- a/docs/html/reference/android/support/wearable/companion/package-summary.html
+++ b/docs/html/reference/android/support/wearable/companion/package-summary.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -541,7 +541,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 
 
 
@@ -641,6 +641,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/input/RemoteInputConstants.html b/docs/html/reference/android/support/wearable/input/RemoteInputConstants.html
index f3cb90c..35fe2d5 100644
--- a/docs/html/reference/android/support/wearable/input/RemoteInputConstants.html
+++ b/docs/html/reference/android/support/wearable/input/RemoteInputConstants.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -603,7 +603,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1151,6 +1151,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/input/RemoteInputIntent.html b/docs/html/reference/android/support/wearable/input/RemoteInputIntent.html
index 92d90bc..34ae2d5 100644
--- a/docs/html/reference/android/support/wearable/input/RemoteInputIntent.html
+++ b/docs/html/reference/android/support/wearable/input/RemoteInputIntent.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -603,7 +603,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -644,7 +644,7 @@
      new RemoteInput.Builder(KEY_QUICK_REPLY_TEXT).setLabel("Quick reply").build()
  };
  Intent intent = new Intent(ACTION_REMOTE_INPUT);
- intent.putExtra(EXTRA_REMOTE_INPUT, remoteInputs);
+ intent.putExtra(EXTRA_REMOTE_INPUTS, remoteInputs);
  startActivity(intent);
  </pre>
 
@@ -1496,6 +1496,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/input/package-summary.html b/docs/html/reference/android/support/wearable/input/package-summary.html
index 2071e28..314838d 100644
--- a/docs/html/reference/android/support/wearable/input/package-summary.html
+++ b/docs/html/reference/android/support/wearable/input/package-summary.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -542,7 +542,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 
 
 
@@ -653,6 +653,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/media/MediaControlConstants.html b/docs/html/reference/android/support/wearable/media/MediaControlConstants.html
index 42c141b..30ddc45 100644
--- a/docs/html/reference/android/support/wearable/media/MediaControlConstants.html
+++ b/docs/html/reference/android/support/wearable/media/MediaControlConstants.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -602,7 +602,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1370,6 +1370,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/media/package-summary.html b/docs/html/reference/android/support/wearable/media/package-summary.html
index 3310b5a..72dce84 100644
--- a/docs/html/reference/android/support/wearable/media/package-summary.html
+++ b/docs/html/reference/android/support/wearable/media/package-summary.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -541,7 +541,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 
 
 
@@ -641,6 +641,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/package-summary.html b/docs/html/reference/android/support/wearable/package-summary.html
index a8e3db057..a4ef376 100644
--- a/docs/html/reference/android/support/wearable/package-summary.html
+++ b/docs/html/reference/android/support/wearable/package-summary.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -474,6 +474,7 @@
         <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.html">R</a></li>
         <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.anim.html">R.anim</a></li>
         <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.animator.html">R.animator</a></li>
+        <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></li>
         <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></li>
         <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></li>
         <li class="api apilevel-"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></li>
@@ -553,7 +554,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 
 
 
@@ -607,6 +608,17 @@
       
     
       <tr class=" api apilevel-" >
+        <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.array.html">R.array</a></td>
+        <td class="jd-descrcol" width="100%">
+          &nbsp;
+          
+    
+
+        </td>
+      </tr>
+      
+    
+      <tr class="alt-color api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.attr.html">R.attr</a></td>
         <td class="jd-descrcol" width="100%">
           &nbsp;
@@ -617,7 +629,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.color.html">R.color</a></td>
         <td class="jd-descrcol" width="100%">
           &nbsp;
@@ -628,7 +640,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.dimen.html">R.dimen</a></td>
         <td class="jd-descrcol" width="100%">
           &nbsp;
@@ -639,7 +651,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.drawable.html">R.drawable</a></td>
         <td class="jd-descrcol" width="100%">
           &nbsp;
@@ -650,7 +662,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.id.html">R.id</a></td>
         <td class="jd-descrcol" width="100%">
           &nbsp;
@@ -661,7 +673,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.interpolator.html">R.interpolator</a></td>
         <td class="jd-descrcol" width="100%">
           &nbsp;
@@ -672,7 +684,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.layout.html">R.layout</a></td>
         <td class="jd-descrcol" width="100%">
           &nbsp;
@@ -683,7 +695,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.string.html">R.string</a></td>
         <td class="jd-descrcol" width="100%">
           &nbsp;
@@ -694,7 +706,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.style.html">R.style</a></td>
         <td class="jd-descrcol" width="100%">
           &nbsp;
@@ -705,7 +717,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../reference/android/support/wearable/R.styleable.html">R.styleable</a></td>
         <td class="jd-descrcol" width="100%">
           &nbsp;
@@ -785,6 +797,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Attendees.html b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Attendees.html
index ba439b3..794973f 100644
--- a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Attendees.html
+++ b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Attendees.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -602,7 +602,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1063,6 +1063,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Instances.html b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Instances.html
index 70ad4d9..77c3c67 100644
--- a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Instances.html
+++ b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Instances.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -602,7 +602,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1063,6 +1063,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Reminders.html b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Reminders.html
index 752da5e..9dfd7f7 100644
--- a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Reminders.html
+++ b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.Reminders.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -602,7 +602,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1063,6 +1063,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.html b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.html
index 919306b..588ae71 100644
--- a/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.html
+++ b/docs/html/reference/android/support/wearable/provider/WearableCalendarContract.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -611,7 +611,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1265,6 +1265,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/provider/package-summary.html b/docs/html/reference/android/support/wearable/provider/package-summary.html
index f82ce5c..bb4c581 100644
--- a/docs/html/reference/android/support/wearable/provider/package-summary.html
+++ b/docs/html/reference/android/support/wearable/provider/package-summary.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -544,7 +544,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 
 
 
@@ -677,6 +677,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/ActionLabel.html b/docs/html/reference/android/support/wearable/view/ActionLabel.html
index 3716018..f8cb733 100644
--- a/docs/html/reference/android/support/wearable/view/ActionLabel.html
+++ b/docs/html/reference/android/support/wearable/view/ActionLabel.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -684,7 +685,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -12362,6 +12363,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/ActionPage.html b/docs/html/reference/android/support/wearable/view/ActionPage.html
index 268bba1..69c4dfb 100644
--- a/docs/html/reference/android/support/wearable/view/ActionPage.html
+++ b/docs/html/reference/android/support/wearable/view/ActionPage.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -714,7 +715,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -15449,6 +15450,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/BoxInsetLayout.LayoutParams.html b/docs/html/reference/android/support/wearable/view/BoxInsetLayout.LayoutParams.html
index 43097b4..d716836 100644
--- a/docs/html/reference/android/support/wearable/view/BoxInsetLayout.LayoutParams.html
+++ b/docs/html/reference/android/support/wearable/view/BoxInsetLayout.LayoutParams.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -687,7 +688,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -2431,6 +2432,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/BoxInsetLayout.html b/docs/html/reference/android/support/wearable/view/BoxInsetLayout.html
index 5619e75..d315135 100644
--- a/docs/html/reference/android/support/wearable/view/BoxInsetLayout.html
+++ b/docs/html/reference/android/support/wearable/view/BoxInsetLayout.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -725,7 +726,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -15573,6 +15574,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CardFragment.html b/docs/html/reference/android/support/wearable/view/CardFragment.html
index 9437e93..b73c6ca 100644
--- a/docs/html/reference/android/support/wearable/view/CardFragment.html
+++ b/docs/html/reference/android/support/wearable/view/CardFragment.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -679,7 +680,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -4875,6 +4876,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CardFrame.html b/docs/html/reference/android/support/wearable/view/CardFrame.html
index 1beeda2..32224d5 100644
--- a/docs/html/reference/android/support/wearable/view/CardFrame.html
+++ b/docs/html/reference/android/support/wearable/view/CardFrame.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -714,7 +715,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -15930,6 +15931,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CardScrollView.html b/docs/html/reference/android/support/wearable/view/CardScrollView.html
index 0364eb9..a361847 100644
--- a/docs/html/reference/android/support/wearable/view/CardScrollView.html
+++ b/docs/html/reference/android/support/wearable/view/CardScrollView.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -722,7 +723,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -15898,6 +15899,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CircledImageView.html b/docs/html/reference/android/support/wearable/view/CircledImageView.html
index 1c9451b..a2ba3f7 100644
--- a/docs/html/reference/android/support/wearable/view/CircledImageView.html
+++ b/docs/html/reference/android/support/wearable/view/CircledImageView.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -684,7 +685,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -2857,12 +2858,44 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageCirclePercentage(float)">setImageCirclePercentage</a></span>(float percentage)</nobr>
+        
+  </td></tr>
+
+
+	 
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
         <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageDrawable(android.graphics.drawable.Drawable)">setImageDrawable</a></span>(Drawable drawable)</nobr>
         
   </td></tr>
 
 
 	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageHorizontalOffcenterPercentage(float)">setImageHorizontalOffcenterPercentage</a></span>(float percentage)</nobr>
+        
+  </td></tr>
+
+
+	 
     <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
@@ -2889,7 +2922,7 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
-        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setPressed(boolean)">setPressed</a></span>(boolean pressed)</nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageTint(int)">setImageTint</a></span>(int tint)</nobr>
         
   </td></tr>
 
@@ -2905,7 +2938,7 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
-        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setProgress(float)">setProgress</a></span>(float progress)</nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setPressed(boolean)">setPressed</a></span>(boolean pressed)</nobr>
         
   </td></tr>
 
@@ -2921,6 +2954,22 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setProgress(float)">setProgress</a></span>(float progress)</nobr>
+        
+  </td></tr>
+
+
+	 
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
         <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setShadowVisibility(float)">setShadowVisibility</a></span>(float shadowVisibility)</nobr>
         
         <div class="jd-descrdiv">
@@ -2934,7 +2983,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -11857,6 +11906,38 @@
 </div>
 
 
+<A NAME="setImageCirclePercentage(float)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">setImageCirclePercentage</span>
+      <span class="normal">(float percentage)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
 <A NAME="setImageDrawable(android.graphics.drawable.Drawable)"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -11889,6 +11970,38 @@
 </div>
 
 
+<A NAME="setImageHorizontalOffcenterPercentage(float)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">setImageHorizontalOffcenterPercentage</span>
+      <span class="normal">(float percentage)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
 <A NAME="setImageResource(int)"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -11921,6 +12034,38 @@
 </div>
 
 
+<A NAME="setImageTint(int)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">setImageTint</span>
+      <span class="normal">(int tint)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
 <A NAME="setPressed(boolean)"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -12330,6 +12475,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CircularButton.html b/docs/html/reference/android/support/wearable/view/CircularButton.html
index edcb3f2..ff626ce 100644
--- a/docs/html/reference/android/support/wearable/view/CircularButton.html
+++ b/docs/html/reference/android/support/wearable/view/CircularButton.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -687,7 +688,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -11986,6 +11987,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/CrossfadeDrawable.html b/docs/html/reference/android/support/wearable/view/CrossfadeDrawable.html
index f346b82..176e532 100644
--- a/docs/html/reference/android/support/wearable/view/CrossfadeDrawable.html
+++ b/docs/html/reference/android/support/wearable/view/CrossfadeDrawable.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -665,7 +666,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -3562,6 +3563,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.DelayedConfirmationListener.html b/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.DelayedConfirmationListener.html
index 6159875..459b683 100644
--- a/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.DelayedConfirmationListener.html
+++ b/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.DelayedConfirmationListener.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -908,6 +909,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.html b/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.html
index 3b61bf0..10e10b9 100644
--- a/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.html
+++ b/docs/html/reference/android/support/wearable/view/DelayedConfirmationView.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -698,7 +699,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -3164,12 +3165,44 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageCirclePercentage(float)">setImageCirclePercentage</a></span>(float percentage)</nobr>
+        
+  </td></tr>
+
+
+	 
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
         <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageDrawable(android.graphics.drawable.Drawable)">setImageDrawable</a></span>(Drawable drawable)</nobr>
         
   </td></tr>
 
 
 	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageHorizontalOffcenterPercentage(float)">setImageHorizontalOffcenterPercentage</a></span>(float percentage)</nobr>
+        
+  </td></tr>
+
+
+	 
     <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
@@ -3196,7 +3229,7 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
-        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setPressed(boolean)">setPressed</a></span>(boolean pressed)</nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setImageTint(int)">setImageTint</a></span>(int tint)</nobr>
         
   </td></tr>
 
@@ -3212,7 +3245,7 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
-        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setProgress(float)">setProgress</a></span>(float progress)</nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setPressed(boolean)">setPressed</a></span>(boolean pressed)</nobr>
         
   </td></tr>
 
@@ -3228,6 +3261,22 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setProgress(float)">setProgress</a></span>(float progress)</nobr>
+        
+  </td></tr>
+
+
+	 
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
         <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/CircledImageView.html#setShadowVisibility(float)">setShadowVisibility</a></span>(float shadowVisibility)</nobr>
         
         <div class="jd-descrdiv">
@@ -3241,7 +3290,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -11914,6 +11963,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/DismissOverlayView.html b/docs/html/reference/android/support/wearable/view/DismissOverlayView.html
index f455403..f146daf 100644
--- a/docs/html/reference/android/support/wearable/view/DismissOverlayView.html
+++ b/docs/html/reference/android/support/wearable/view/DismissOverlayView.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -719,7 +720,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -15317,6 +15318,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/DotsPageIndicator.html b/docs/html/reference/android/support/wearable/view/DotsPageIndicator.html
index 006a270..634cf95 100644
--- a/docs/html/reference/android/support/wearable/view/DotsPageIndicator.html
+++ b/docs/html/reference/android/support/wearable/view/DotsPageIndicator.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -705,7 +706,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -13437,6 +13438,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/FragmentGridPagerAdapter.html b/docs/html/reference/android/support/wearable/view/FragmentGridPagerAdapter.html
index 9df4ae7..ed7fecd 100644
--- a/docs/html/reference/android/support/wearable/view/FragmentGridPagerAdapter.html
+++ b/docs/html/reference/android/support/wearable/view/FragmentGridPagerAdapter.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -611,6 +612,9 @@
   
 
 
+  &#124; <a href="#promethods">Protected Methods</a>
+  
+
 
   &#124; <a href="#inhmethods">Inherited Methods</a>
 
@@ -660,7 +664,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -965,6 +969,22 @@
             
             
             
+            Fragment</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/FragmentGridPagerAdapter.html#findExistingFragment(int, int)">findExistingFragment</a></span>(int row, int column)</nobr>
+        
+  </td></tr>
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
@@ -981,7 +1001,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1004,7 +1024,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             abstract
             
@@ -1027,7 +1047,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1050,7 +1070,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1074,7 +1094,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1097,7 +1117,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1126,6 +1146,71 @@
 
 
 
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="promethods" class="jd-sumtable"><tr><th colspan="12">Protected Methods</th></tr>
+
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/FragmentGridPagerAdapter.html#applyItemPosition(java.lang.Object, android.graphics.Point)">applyItemPosition</a></span>(Object object, Point position)</nobr>
+        
+        <div class="jd-descrdiv">
+          Called after <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code> to allow superclasses to update their
+ internal bookkeeping if a subclass has overridden <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/FragmentGridPagerAdapter.html#removeFragment(android.app.Fragment, android.app.FragmentTransaction)">removeFragment</a></span>(Fragment fragment, FragmentTransaction transaction)</nobr>
+        
+  </td></tr>
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/FragmentGridPagerAdapter.html#restoreFragment(android.app.Fragment, android.app.FragmentTransaction)">restoreFragment</a></span>(Fragment fragment, FragmentTransaction transaction)</nobr>
+        
+  </td></tr>
+
+
+
+</table>
+
+
 
 
 
@@ -1157,6 +1242,30 @@
 	 
     <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#applyItemPosition(java.lang.Object, android.graphics.Point)">applyItemPosition</a></span>(Object object, Point position)</nobr>
+        
+        <div class="jd-descrdiv">
+          Called after <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code> to allow superclasses to update their
+ internal bookkeeping if a subclass has overridden <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol"><nobr>
             abstract
             
             
@@ -1178,7 +1287,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1201,7 +1310,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1224,7 +1333,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1247,7 +1356,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             abstract
             
@@ -1270,7 +1379,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1293,7 +1402,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1316,7 +1425,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1339,7 +1448,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             abstract
             
@@ -1362,7 +1471,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             abstract
             
@@ -1385,7 +1494,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             abstract
             
@@ -1409,7 +1518,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1433,7 +1542,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1457,7 +1566,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1481,7 +1590,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1504,7 +1613,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1527,7 +1636,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1550,7 +1659,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1573,7 +1682,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1596,7 +1705,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1964,6 +2073,38 @@
 </div>
 
 
+<A NAME="findExistingFragment(int, int)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        Fragment
+      </span>
+      <span class="sympad">findExistingFragment</span>
+      <span class="normal">(int row, int column)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
 <A NAME="finishUpdate(android.view.ViewGroup)"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -2331,6 +2472,122 @@
 
 <!-- ========= METHOD DETAIL ======== -->
 
+<h2>Protected Methods</h2>
+
+
+
+<A NAME="applyItemPosition(java.lang.Object, android.graphics.Point)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        protected 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">applyItemPosition</span>
+      <span class="normal">(Object object, Point position)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Called after <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code> to allow superclasses to update their
+ internal bookkeeping if a subclass has overridden <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>object</td>
+          <td>Object representing the item passed to <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.</td>
+        </tr>
+        <tr>
+          <th>position</td>
+          <td>position which was returned from <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.
+</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+<A NAME="removeFragment(android.app.Fragment, android.app.FragmentTransaction)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        protected 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">removeFragment</span>
+      <span class="normal">(Fragment fragment, FragmentTransaction transaction)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
+<A NAME="restoreFragment(android.app.Fragment, android.app.FragmentTransaction)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        protected 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">restoreFragment</span>
+      <span class="normal">(Fragment fragment, FragmentTransaction transaction)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
+
 
 
 <!-- ========= END OF CLASS DATA ========= -->
@@ -2389,6 +2646,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridPageOptions.BackgroundListener.html b/docs/html/reference/android/support/wearable/view/GridPageOptions.BackgroundListener.html
index a37d8f8a..1e066c1 100644
--- a/docs/html/reference/android/support/wearable/view/GridPageOptions.BackgroundListener.html
+++ b/docs/html/reference/android/support/wearable/view/GridPageOptions.BackgroundListener.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -853,6 +854,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridPageOptions.html b/docs/html/reference/android/support/wearable/view/GridPageOptions.html
index 56cfa05..8c22582 100644
--- a/docs/html/reference/android/support/wearable/view/GridPageOptions.html
+++ b/docs/html/reference/android/support/wearable/view/GridPageOptions.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -948,6 +949,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridPagerAdapter.html b/docs/html/reference/android/support/wearable/view/GridPagerAdapter.html
index 9876a82..b157c39 100644
--- a/docs/html/reference/android/support/wearable/view/GridPagerAdapter.html
+++ b/docs/html/reference/android/support/wearable/view/GridPagerAdapter.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -600,6 +601,9 @@
   
 
 
+  &#124; <a href="#promethods">Protected Methods</a>
+  
+
 
   &#124; <a href="#inhmethods">Inherited Methods</a>
 
@@ -645,7 +649,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1369,6 +1373,39 @@
 
 
 
+<!-- ========== METHOD SUMMARY =========== -->
+<table id="promethods" class="jd-sumtable"><tr><th colspan="12">Protected Methods</th></tr>
+
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#applyItemPosition(java.lang.Object, android.graphics.Point)">applyItemPosition</a></span>(Object object, Point position)</nobr>
+        
+        <div class="jd-descrdiv">
+          Called after <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code> to allow superclasses to update their
+ internal bookkeeping if a subclass has overridden <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+
+</table>
+
+
 
 
 
@@ -2742,6 +2779,58 @@
 
 <!-- ========= METHOD DETAIL ======== -->
 
+<h2>Protected Methods</h2>
+
+
+
+<A NAME="applyItemPosition(java.lang.Object, android.graphics.Point)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        protected 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">applyItemPosition</span>
+      <span class="normal">(Object object, Point position)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Called after <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code> to allow superclasses to update their
+ internal bookkeeping if a subclass has overridden <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>object</td>
+          <td>Object representing the item passed to <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.</td>
+        </tr>
+        <tr>
+          <th>position</td>
+          <td>position which was returned from <code><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html#getItemPosition(java.lang.Object)">getItemPosition(Object)</a></code>.
+</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
+
 
 
 <!-- ========= END OF CLASS DATA ========= -->
@@ -2800,6 +2889,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridViewPager.LayoutParams.html b/docs/html/reference/android/support/wearable/view/GridViewPager.LayoutParams.html
index 9db55c9..c4d63e22 100644
--- a/docs/html/reference/android/support/wearable/view/GridViewPager.LayoutParams.html
+++ b/docs/html/reference/android/support/wearable/view/GridViewPager.LayoutParams.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -673,7 +674,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1787,6 +1788,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridViewPager.OnAdapterChangeListener.html b/docs/html/reference/android/support/wearable/view/GridViewPager.OnAdapterChangeListener.html
index 1cbec14..fcd6a3d 100644
--- a/docs/html/reference/android/support/wearable/view/GridViewPager.OnAdapterChangeListener.html
+++ b/docs/html/reference/android/support/wearable/view/GridViewPager.OnAdapterChangeListener.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -621,7 +622,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -968,6 +969,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridViewPager.OnPageChangeListener.html b/docs/html/reference/android/support/wearable/view/GridViewPager.OnPageChangeListener.html
index fd81fbe..072f6c5 100644
--- a/docs/html/reference/android/support/wearable/view/GridViewPager.OnPageChangeListener.html
+++ b/docs/html/reference/android/support/wearable/view/GridViewPager.OnPageChangeListener.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -621,7 +622,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1085,6 +1086,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/GridViewPager.html b/docs/html/reference/android/support/wearable/view/GridViewPager.html
index b92720c..3e2179d 100644
--- a/docs/html/reference/android/support/wearable/view/GridViewPager.html
+++ b/docs/html/reference/android/support/wearable/view/GridViewPager.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -717,7 +718,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -16881,6 +16882,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/SimpleAnimatorListener.html b/docs/html/reference/android/support/wearable/view/SimpleAnimatorListener.html
index 454f420..9940f3b 100644
--- a/docs/html/reference/android/support/wearable/view/SimpleAnimatorListener.html
+++ b/docs/html/reference/android/support/wearable/view/SimpleAnimatorListener.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -651,7 +652,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1525,6 +1526,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WatchViewStub.OnLayoutInflatedListener.html b/docs/html/reference/android/support/wearable/view/WatchViewStub.OnLayoutInflatedListener.html
index b05ce34..9492429 100644
--- a/docs/html/reference/android/support/wearable/view/WatchViewStub.OnLayoutInflatedListener.html
+++ b/docs/html/reference/android/support/wearable/view/WatchViewStub.OnLayoutInflatedListener.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -847,6 +848,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WatchViewStub.html b/docs/html/reference/android/support/wearable/view/WatchViewStub.html
index 8fd5fee..170a165 100644
--- a/docs/html/reference/android/support/wearable/view/WatchViewStub.html
+++ b/docs/html/reference/android/support/wearable/view/WatchViewStub.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -725,7 +726,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -15465,6 +15466,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableFrameLayout.LayoutParams.html b/docs/html/reference/android/support/wearable/view/WearableFrameLayout.LayoutParams.html
index 93f4b0d..fb54c95 100644
--- a/docs/html/reference/android/support/wearable/view/WearableFrameLayout.LayoutParams.html
+++ b/docs/html/reference/android/support/wearable/view/WearableFrameLayout.LayoutParams.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -684,7 +685,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -2322,6 +2323,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableFrameLayout.html b/docs/html/reference/android/support/wearable/view/WearableFrameLayout.html
index f2b0df7..e269ab8 100644
--- a/docs/html/reference/android/support/wearable/view/WearableFrameLayout.html
+++ b/docs/html/reference/android/support/wearable/view/WearableFrameLayout.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="selected api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -714,7 +715,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -16352,6 +16353,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.Adapter.html b/docs/html/reference/android/support/wearable/view/WearableListView.Adapter.html
index 9619c5d..0686ff2 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.Adapter.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.Adapter.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -647,7 +648,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1561,6 +1562,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.ClickListener.html b/docs/html/reference/android/support/wearable/view/WearableListView.ClickListener.html
index 84cb188..17431c4 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.ClickListener.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.ClickListener.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -919,6 +920,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.OnCenterProximityListener.html b/docs/html/reference/android/support/wearable/view/WearableListView.OnCenterProximityListener.html
index b2b9246..936a163 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.OnCenterProximityListener.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.OnCenterProximityListener.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -930,6 +931,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.OnCentralPositionChangedListener.html b/docs/html/reference/android/support/wearable/view/WearableListView.OnCentralPositionChangedListener.html
index 66eeac3..c49bbcc 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.OnCentralPositionChangedListener.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.OnCentralPositionChangedListener.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -861,6 +862,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.OnScrollListener.html b/docs/html/reference/android/support/wearable/view/WearableListView.OnScrollListener.html
index de2bcd7..2871600 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.OnScrollListener.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.OnScrollListener.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -602,7 +603,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1065,6 +1066,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.ViewHolder.html b/docs/html/reference/android/support/wearable/view/WearableListView.ViewHolder.html
index b7953d4..270d8d8 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.ViewHolder.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.ViewHolder.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -652,7 +653,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1346,6 +1347,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/WearableListView.html b/docs/html/reference/android/support/wearable/view/WearableListView.html
index eec5c32..7fb9565 100644
--- a/docs/html/reference/android/support/wearable/view/WearableListView.html
+++ b/docs/html/reference/android/support/wearable/view/WearableListView.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -501,6 +501,7 @@
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
           <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -724,7 +725,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -3236,7 +3237,7 @@
             boolean</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
-        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#onInterceptTouchEvent(android.view.MotionEvent)">onInterceptTouchEvent</a></span>(MotionEvent event)</nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#isAtTop()">isAtTop</a></span>()</nobr>
         
   </td></tr>
 
@@ -3252,7 +3253,7 @@
             boolean</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
-        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#onTouchEvent(android.view.MotionEvent)">onTouchEvent</a></span>(MotionEvent event)</nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#onInterceptTouchEvent(android.view.MotionEvent)">onInterceptTouchEvent</a></span>(MotionEvent event)</nobr>
         
   </td></tr>
 
@@ -3265,6 +3266,22 @@
             
             
             
+            boolean</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#onTouchEvent(android.view.MotionEvent)">onTouchEvent</a></span>(MotionEvent event)</nobr>
+        
+  </td></tr>
+
+
+	 
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
@@ -3281,7 +3298,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -3304,7 +3321,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -3327,7 +3344,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -3343,7 +3360,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -3366,7 +3383,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -3390,7 +3407,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -3413,7 +3430,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -3436,6 +3453,22 @@
   </td></tr>
 
 
+	 
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html#smoothScrollToPosition(int, android.support.v7.widget.RecyclerView.SmoothScroller)">smoothScrollToPosition</a></span>(int position, RecyclerView.SmoothScroller smoothScroller)</nobr>
+        
+  </td></tr>
+
+
 
 </table>
 
@@ -16613,6 +16646,43 @@
 </div>
 
 
+<A NAME="isAtTop()"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">isAtTop</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist"><li>true if the list is scrolled all the way to the top.
+</li></ul>
+  </div>
+
+    </div>
+</div>
+
+
 <A NAME="onInterceptTouchEvent(android.view.MotionEvent)"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -16963,6 +17033,38 @@
 </div>
 
 
+<A NAME="smoothScrollToPosition(int, android.support.v7.widget.RecyclerView.SmoothScroller)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">smoothScrollToPosition</span>
+      <span class="normal">(int position, RecyclerView.SmoothScroller smoothScroller)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p></p></div>
+
+    </div>
+</div>
+
+
 
 
 
@@ -17026,6 +17128,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/view/package-summary.html b/docs/html/reference/android/support/wearable/view/package-summary.html
index 28f94db..f76e378 100644
--- a/docs/html/reference/android/support/wearable/view/package-summary.html
+++ b/docs/html/reference/android/support/wearable/view/package-summary.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -502,6 +502,7 @@
         <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridPagerAdapter.html">GridPagerAdapter</a></li>
         <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.html">GridViewPager</a></li>
         <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/GridViewPager.LayoutParams.html">GridViewPager.LayoutParams</a></li>
+        <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></li>
         <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></li>
         <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></li>
         <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></li>
@@ -578,7 +579,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 
 
 
@@ -920,6 +921,17 @@
       
     
       <tr class=" api apilevel-" >
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/ProgressSpinner.html">ProgressSpinner</a></td>
+        <td class="jd-descrcol" width="100%">
+          An indeterminate progress spinner designed for wearables which cycles through colors.&nbsp;
+          
+    
+
+        </td>
+      </tr>
+      
+    
+      <tr class="alt-color api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/SimpleAnimatorListener.html">SimpleAnimatorListener</a></td>
         <td class="jd-descrcol" width="100%">
           Convenience class for listening for Animator events that implements the AnimatorListener
@@ -931,7 +943,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WatchViewStub.html">WatchViewStub</a></td>
         <td class="jd-descrcol" width="100%">
           A WatchViewStub allows for the use of different sub-layouts depending on the
@@ -944,7 +956,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.html">WearableFrameLayout</a></td>
         <td class="jd-descrcol" width="100%">
           WearableFrameLayout works exactly like FrameLayout, except it can have overrides for a round
@@ -956,7 +968,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WearableFrameLayout.LayoutParams.html">WearableFrameLayout.LayoutParams</a></td>
         <td class="jd-descrcol" width="100%">
           Per-child layout information for layouts on wearable devices.&nbsp;
@@ -967,7 +979,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WearableListView.html">WearableListView</a></td>
         <td class="jd-descrcol" width="100%">
           An alternative version of ListView that is optimized for ease of use on small screen wearable
@@ -979,7 +991,7 @@
       </tr>
       
     
-      <tr class="alt-color api apilevel-" >
+      <tr class=" api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WearableListView.Adapter.html">WearableListView.Adapter</a></td>
         <td class="jd-descrcol" width="100%">
           Base class for adapters providing data for the WearableListView.&nbsp;
@@ -990,7 +1002,7 @@
       </tr>
       
     
-      <tr class=" api apilevel-" >
+      <tr class="alt-color api apilevel-" >
         <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/view/WearableListView.ViewHolder.html">WearableListView.ViewHolder</a></td>
         <td class="jd-descrcol" width="100%">
           Wrapper around items displayed in the list view.&nbsp;
@@ -1070,6 +1082,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html b/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html
index bbae62a..1a7aa76 100644
--- a/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html
+++ b/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -466,6 +466,11 @@
 
             <ul>
               
+    <li><h2>Annotations</h2>
+      <ul>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+      </ul>
+    </li>
               
               
     <li><h2>Classes</h2>
@@ -631,7 +636,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -968,6 +973,29 @@
             final
             
             
+            int</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#getNotificationCount()">getNotificationCount</a></span>()</nobr>
+        
+        <div class="jd-descrdiv">
+          Returns the total number of notification cards in the stream.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            final
+            
+            
             Rect</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
@@ -984,7 +1012,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1007,7 +1035,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1030,7 +1058,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1053,7 +1081,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1069,7 +1097,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1085,7 +1113,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1101,7 +1129,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1124,6 +1152,29 @@
 
 
 	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onNotificationCountChanged(int)">onNotificationCountChanged</a></span>(int count)</nobr>
+        
+        <div class="jd-descrdiv">
+          Called when the total number of notification cards in the stream has changed.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
     <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
@@ -1180,6 +1231,29 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTapCommand(int, int, int, long)">onTapCommand</a></span>(int tapType, int x, int y, long eventTime)</nobr>
+        
+        <div class="jd-descrdiv">
+          Called when a tap or touch related event occurs.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
         <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTimeTick()">onTimeTick</a></span>()</nobr>
         
         <div class="jd-descrdiv">
@@ -1193,7 +1267,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1216,7 +1290,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1239,7 +1313,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -2201,6 +2275,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.html b/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.html
index 5dbd8ea..aee337f 100644
--- a/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.html
+++ b/docs/html/reference/android/support/wearable/watchface/CanvasWatchFaceService.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -466,6 +466,11 @@
 
             <ul>
               
+    <li><h2>Annotations</h2>
+      <ul>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+      </ul>
+    </li>
               
               
     <li><h2>Classes</h2>
@@ -694,7 +699,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -952,6 +957,44 @@
     </tr>
     
     
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol">int</td>
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP">TAP_TYPE_TAP</a></td>
+        <td class="jd-descrcol" width="100%">
+          Used in onTapCommaned to indicate that an "up" event on the watch face has occurred that
+ has not been consumed by another activity.
+          
+    
+
+        </td>
+    </tr>
+    
+    
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol">int</td>
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH">TAP_TYPE_TOUCH</a></td>
+        <td class="jd-descrcol" width="100%">
+          Used in onTapCommand to indicate a "down" touch event on the watch face.
+          
+    
+
+        </td>
+    </tr>
+    
+    
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol">int</td>
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL">TAP_TYPE_TOUCH_CANCEL</a></td>
+        <td class="jd-descrcol" width="100%">
+          Used in onTapCaommand to indicate that a previous TAP_TYPE_TOUCH touch event has been
+ canceled.
+          
+    
+
+        </td>
+    </tr>
+    
+    
 </table>
   </div>
 </div>
@@ -6238,6 +6281,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.Engine.html b/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.Engine.html
index 761917877..aba23a6 100644
--- a/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.Engine.html
+++ b/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.Engine.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -466,6 +466,11 @@
 
             <ul>
               
+    <li><h2>Annotations</h2>
+      <ul>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+      </ul>
+    </li>
               
               
     <li><h2>Classes</h2>
@@ -631,7 +636,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1138,6 +1143,29 @@
             final
             
             
+            int</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#getNotificationCount()">getNotificationCount</a></span>()</nobr>
+        
+        <div class="jd-descrdiv">
+          Returns the total number of notification cards in the stream.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            final
+            
+            
             Rect</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
@@ -1154,7 +1182,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1177,7 +1205,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1200,7 +1228,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1223,7 +1251,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1239,7 +1267,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1255,7 +1283,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1271,7 +1299,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1294,6 +1322,29 @@
 
 
 	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onNotificationCountChanged(int)">onNotificationCountChanged</a></span>(int count)</nobr>
+        
+        <div class="jd-descrdiv">
+          Called when the total number of notification cards in the stream has changed.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
     <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
@@ -1350,6 +1401,29 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTapCommand(int, int, int, long)">onTapCommand</a></span>(int tapType, int x, int y, long eventTime)</nobr>
+        
+        <div class="jd-descrdiv">
+          Called when a tap or touch related event occurs.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
         <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTimeTick()">onTimeTick</a></span>()</nobr>
         
         <div class="jd-descrdiv">
@@ -1363,7 +1437,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1386,7 +1460,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1409,7 +1483,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -2668,6 +2742,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.html b/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.html
index 6371290..1dcc7dd 100644
--- a/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.html
+++ b/docs/html/reference/android/support/wearable/watchface/Gles2WatchFaceService.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -466,6 +466,11 @@
 
             <ul>
               
+    <li><h2>Annotations</h2>
+      <ul>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+      </ul>
+    </li>
               
               
     <li><h2>Classes</h2>
@@ -694,7 +699,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -955,6 +960,44 @@
     </tr>
     
     
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol">int</td>
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP">TAP_TYPE_TAP</a></td>
+        <td class="jd-descrcol" width="100%">
+          Used in onTapCommaned to indicate that an "up" event on the watch face has occurred that
+ has not been consumed by another activity.
+          
+    
+
+        </td>
+    </tr>
+    
+    
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol">int</td>
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH">TAP_TYPE_TOUCH</a></td>
+        <td class="jd-descrcol" width="100%">
+          Used in onTapCommand to indicate a "down" touch event on the watch face.
+          
+    
+
+        </td>
+    </tr>
+    
+    
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol">int</td>
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL">TAP_TYPE_TOUCH_CANCEL</a></td>
+        <td class="jd-descrcol" width="100%">
+          Used in onTapCaommand to indicate that a previous TAP_TYPE_TOUCH touch event has been
+ canceled.
+          
+    
+
+        </td>
+    </tr>
+    
+    
 </table>
   </div>
 </div>
@@ -6241,6 +6284,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/WatchFaceService.Engine.html b/docs/html/reference/android/support/wearable/watchface/WatchFaceService.Engine.html
index 2326386..ad6cc2c 100644
--- a/docs/html/reference/android/support/wearable/watchface/WatchFaceService.Engine.html
+++ b/docs/html/reference/android/support/wearable/watchface/WatchFaceService.Engine.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -466,6 +466,11 @@
 
             <ul>
               
+    <li><h2>Annotations</h2>
+      <ul>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+      </ul>
+    </li>
               
               
     <li><h2>Classes</h2>
@@ -620,7 +625,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -831,6 +836,29 @@
             final
             
             
+            int</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#getNotificationCount()">getNotificationCount</a></span>()</nobr>
+        
+        <div class="jd-descrdiv">
+          Returns the total number of notification cards in the stream.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            final
+            
+            
             Rect</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
@@ -847,7 +875,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -870,7 +898,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -893,7 +921,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -916,7 +944,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -932,7 +960,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -948,7 +976,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -964,7 +992,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -987,6 +1015,29 @@
 
 
 	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onNotificationCountChanged(int)">onNotificationCountChanged</a></span>(int count)</nobr>
+        
+        <div class="jd-descrdiv">
+          Called when the total number of notification cards in the stream has changed.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
     <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
@@ -1043,6 +1094,29 @@
             void</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTapCommand(int, int, int, long)">onTapCommand</a></span>(int tapType, int x, int y, long eventTime)</nobr>
+        
+        <div class="jd-descrdiv">
+          Called when a tap or touch related event occurs.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            void</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
         <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTimeTick()">onTimeTick</a></span>()</nobr>
         
         <div class="jd-descrdiv">
@@ -1056,7 +1130,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1079,7 +1153,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1102,7 +1176,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1805,6 +1879,39 @@
 </div>
 
 
+<A NAME="getNotificationCount()"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+        final 
+         
+         
+        int
+      </span>
+      <span class="sympad">getNotificationCount</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Returns the total number of notification cards in the stream.
+</p></div>
+
+    </div>
+</div>
+
+
 <A NAME="getPeekCardPosition()"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -2075,6 +2182,48 @@
 </div>
 
 
+<A NAME="onNotificationCountChanged(int)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">onNotificationCountChanged</span>
+      <span class="normal">(int count)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Called when the total number of notification cards in the stream has changed.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>count</td>
+          <td>total number of the notification cards in the stream
+</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
 <A NAME="onPeekCardPositionUpdate(android.graphics.Rect)"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -2154,6 +2303,60 @@
 </div>
 
 
+<A NAME="onTapCommand(int, int, int, long)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        void
+      </span>
+      <span class="sympad">onTapCommand</span>
+      <span class="normal">(int tapType, int x, int y, long eventTime)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Called when a tap or touch related event occurs.</p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>tapType</td>
+          <td>Value representing the event sent to the wallpaper.</td>
+        </tr>
+        <tr>
+          <th>x</td>
+          <td>X coordinate of the event.</td>
+        </tr>
+        <tr>
+          <th>y</td>
+          <td>Y coordinate of the event.</td>
+        </tr>
+        <tr>
+          <th>eventTime</td>
+          <td>The time, in millis, of the event.
+</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
 <A NAME="onTimeTick()"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -2369,6 +2572,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/WatchFaceService.html b/docs/html/reference/android/support/wearable/watchface/WatchFaceService.html
index f566e7e..40cf0a3 100644
--- a/docs/html/reference/android/support/wearable/watchface/WatchFaceService.html
+++ b/docs/html/reference/android/support/wearable/watchface/WatchFaceService.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -466,6 +466,11 @@
 
             <ul>
               
+    <li><h2>Annotations</h2>
+      <ul>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+      </ul>
+    </li>
               
               
     <li><h2>Classes</h2>
@@ -684,7 +689,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -922,6 +927,23 @@
     </tr>
     
     
+    <tr class=" api apilevel-" >
+      <td class="jd-typecol"><nobr>
+        
+         
+         
+        
+        @interface</nobr></td>
+      <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></td>
+      <td class="jd-descrcol" width="100%">
+        &nbsp;
+        
+    
+
+      </td>
+    </tr>
+    
+    
 
 
 
@@ -1005,6 +1027,44 @@
     </tr>
     
     
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol">int</td>
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP">TAP_TYPE_TAP</a></td>
+        <td class="jd-descrcol" width="100%">
+          Used in onTapCommaned to indicate that an "up" event on the watch face has occurred that
+ has not been consumed by another activity.
+          
+    
+
+        </td>
+    </tr>
+    
+    
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol">int</td>
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH">TAP_TYPE_TOUCH</a></td>
+        <td class="jd-descrcol" width="100%">
+          Used in onTapCommand to indicate a "down" touch event on the watch face.
+          
+    
+
+        </td>
+    </tr>
+    
+    
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol">int</td>
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL">TAP_TYPE_TOUCH_CANCEL</a></td>
+        <td class="jd-descrcol" width="100%">
+          Used in onTapCaommand to indicate that a previous TAP_TYPE_TOUCH touch event has been
+ canceled.
+          
+    
+
+        </td>
+    </tr>
+    
+    
 
 </table>
 
@@ -6330,6 +6390,136 @@
 
 
 
+<A NAME="TAP_TYPE_TAP"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+        final 
+        int
+      </span>
+        TAP_TYPE_TAP
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Used in onTapCommaned to indicate that an "up" event on the watch face has occurred that
+ has not been consumed by another activity. A TAP_TYPE_TOUCH will always occur first. This
+ event will not occur if a TAP_TYPE_TOUCH_CANCEL is sent.
+</p></div>
+
+    
+        <div class="jd-tagdata">
+        <span class="jd-tagtitle">Constant Value: </span>
+        <span>
+            
+                2
+                (0x00000002)
+            
+        </span>
+        </div>
+    
+    </div>
+</div>
+
+
+
+<A NAME="TAP_TYPE_TOUCH"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+        final 
+        int
+      </span>
+        TAP_TYPE_TOUCH
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Used in onTapCommand to indicate a "down" touch event on the watch face.
+</p></div>
+
+    
+        <div class="jd-tagdata">
+        <span class="jd-tagtitle">Constant Value: </span>
+        <span>
+            
+                0
+                (0x00000000)
+            
+        </span>
+        </div>
+    
+    </div>
+</div>
+
+
+
+<A NAME="TAP_TYPE_TOUCH_CANCEL"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+        static 
+        final 
+        int
+      </span>
+        TAP_TYPE_TOUCH_CANCEL
+    </h4>
+      <div class="api-level">
+        
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Used in onTapCaommand to indicate that a previous TAP_TYPE_TOUCH touch event has been
+ canceled. This generally happens when the watch face is touched but then a move or long
+ press occurs.
+</p></div>
+
+    
+        <div class="jd-tagdata">
+        <span class="jd-tagtitle">Constant Value: </span>
+        <span>
+            
+                1
+                (0x00000001)
+            
+        </span>
+        </div>
+    
+    </div>
+</div>
+
+
+
 
 <!-- Fields -->
 
@@ -6484,6 +6674,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html b/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html
index 956e3a8..a5401e5 100644
--- a/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html
+++ b/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -466,6 +466,11 @@
 
             <ul>
               
+    <li><h2>Annotations</h2>
+      <ul>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+      </ul>
+    </li>
               
               
     <li><h2>Classes</h2>
@@ -609,7 +614,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -758,6 +763,29 @@
             <a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html">WatchFaceStyle.Builder</a></nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html#setAcceptsTapEvents(boolean)">setAcceptsTapEvents</a></span>(boolean acceptsTapEvents)</nobr>
+        
+        <div class="jd-descrdiv">
+          Sets whether this watchface accepts tap events.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
+    <tr class="alt-color api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
+            <a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html">WatchFaceStyle.Builder</a></nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
         <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html#setAmbientPeekMode(int)">setAmbientPeekMode</a></span>(int ambientPeekMode)</nobr>
         
         <div class="jd-descrdiv">
@@ -772,7 +800,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -795,7 +823,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -818,7 +846,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -841,7 +869,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -864,7 +892,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -887,7 +915,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -910,7 +938,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -933,7 +961,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -959,7 +987,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1312,6 +1340,53 @@
 </div>
 
 
+<A NAME="setAcceptsTapEvents(boolean)"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        <a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.Builder.html">WatchFaceStyle.Builder</a>
+      </span>
+      <span class="sympad">setAcceptsTapEvents</span>
+      <span class="normal">(boolean acceptsTapEvents)</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Sets whether this watchface accepts tap events. The default is false.
+ <p>
+ Watchfaces that set this <code>true</code> are indicating they are prepared to receive
+ <code><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH">TAP_TYPE_TOUCH</a></code>,
+ <code><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL">TAP_TYPE_TOUCH_CANCEL</a></code>,
+ and <code><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP">TAP_TYPE_TAP</a></code></p></div>
+  <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Parameters</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>acceptsTapEvents</td>
+          <td>whether to receive touch events.
+</td>
+        </tr>
+      </table>
+  </div>
+
+    </div>
+</div>
+
+
 <A NAME="setAmbientPeekMode(int)"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -1825,6 +1900,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.html b/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.html
index e08608f..70c3851 100644
--- a/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.html
+++ b/docs/html/reference/android/support/wearable/watchface/WatchFaceStyle.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -466,6 +466,11 @@
 
             <ul>
               
+    <li><h2>Annotations</h2>
+      <ul>
+          <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+      </ul>
+    </li>
               
               
     <li><h2>Classes</h2>
@@ -632,7 +637,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 <table class="jd-inheritance-table">
 
 
@@ -1022,6 +1027,29 @@
             
             
             
+            boolean</nobr>
+        </td>
+        <td class="jd-linkcol" width="100%"><nobr>
+        <span class="sympad"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceStyle.html#getAcceptsTapEvents()">getAcceptsTapEvents</a></span>()</nobr>
+        
+        <div class="jd-descrdiv">
+          Whether the watchface accepts tap events.
+          
+    
+
+        </div>
+  
+  </td></tr>
+
+
+	 
+    <tr class=" api apilevel-" >
+        <td class="jd-typecol"><nobr>
+            
+            
+            
+            
+            
             int</nobr>
         </td>
         <td class="jd-linkcol" width="100%"><nobr>
@@ -1039,7 +1067,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1062,7 +1090,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1085,7 +1113,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1108,7 +1136,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1131,7 +1159,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1154,7 +1182,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1177,7 +1205,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1200,7 +1228,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1223,7 +1251,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1247,7 +1275,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1263,7 +1291,7 @@
 
 
 	 
-    <tr class=" api apilevel-" >
+    <tr class="alt-color api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1279,7 +1307,7 @@
 
 
 	 
-    <tr class="alt-color api apilevel-" >
+    <tr class=" api apilevel-" >
         <td class="jd-typecol"><nobr>
             
             
@@ -1706,7 +1734,8 @@
 
       
   <div class="jd-tagdata jd-tagdescr"><p>When this background visibility is selected, the background of the peek card should only be
- shown briefly, and only if the peek card represents an interruptive notification.
+ shown briefly, and only if the peek card represents an interruptive notification. This is the
+ default mode.
 </p></div>
 
     
@@ -1749,7 +1778,7 @@
 
       
   <div class="jd-tagdata jd-tagdescr"><p>When this background visibility is selected, the background of the peek card should always
- be shown. This is the default mode.
+ be shown.
 
  Note that this will obscure your watch face whenever there is a peek card showing.
 </p></div>
@@ -2191,6 +2220,39 @@
 </div>
 
 
+<A NAME="getAcceptsTapEvents()"></A>
+
+<div class="jd-details api apilevel-"> 
+    <h4 class="jd-details-title">
+      <span class="normal">
+        public 
+         
+         
+         
+         
+        boolean
+      </span>
+      <span class="sympad">getAcceptsTapEvents</span>
+      <span class="normal">()</span>
+    </h4>
+      <div class="api-level">
+        <div></div>
+        
+  
+
+      </div>
+    <div class="jd-details-descr">
+      
+    
+
+      
+  <div class="jd-tagdata jd-tagdescr"><p>Whether the watchface accepts tap events.  The default is false.
+</p></div>
+
+    </div>
+</div>
+
+
 <A NAME="getAmbientPeekMode()"></A>
 
 <div class="jd-details api apilevel-"> 
@@ -2705,6 +2767,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/reference/android/support/wearable/watchface/package-summary.html b/docs/html/reference/android/support/wearable/watchface/package-summary.html
index 6853fc4..a654b13 100644
--- a/docs/html/reference/android/support/wearable/watchface/package-summary.html
+++ b/docs/html/reference/android/support/wearable/watchface/package-summary.html
@@ -128,7 +128,7 @@
   var metaTags = [];
   var devsite = false;
 </script>
-<script src="../../../../../assets/js/docs.js?v=5" type="text/javascript"></script>
+<script src="../../../../../assets/js/docs.js?v=6" type="text/javascript"></script>
 
 
 
@@ -467,6 +467,11 @@
 
             <ul>
               
+    <li><h2>Annotations</h2>
+      <ul>
+        <li class="api apilevel-"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></li>
+      </ul>
+    </li>
               
               
     <li><h2>Classes</h2>
@@ -548,7 +553,7 @@
 
 <div id="naMessage"></div>
 
-<div id="jd-content" class="api apilevel-"><p style="border:2px solid #99ccff;padding:12px;margin-top:20px"><strong>Note:</strong> The Wearable Support Library classes under the <code>android.support.wearable</code> package are subject to change. For the full Android API reference, see <a href="/reference/">Reference</a>.</p>
+<div id="jd-content" class="api apilevel-">
 
 
 
@@ -556,6 +561,27 @@
 
 
   
+    <h2>Annotations</h2>
+    <div class="jd-sumtable">
+    
+  
+  <table class="jd-sumtable-expando">
+    
+      <tr class="alt-color api apilevel-" >
+        <td class="jd-linkcol"><a href="../../../../../reference/android/support/wearable/watchface/WatchFaceService.TapType.html">WatchFaceService.TapType</a></td>
+        <td class="jd-descrcol" width="100%">
+          &nbsp;
+          
+    
+
+        </td>
+      </tr>
+      
+    
+  </table>
+
+    </div>
+  
 
 
   
@@ -726,6 +752,7 @@
           <option value="es">Español</option>
           <option value="ja">日本語</option>
           <option value="ko">한국어</option>
+          <option value="pt-br">Português Brasileiro</option>
           <option value="ru">Русский</option>
           <option value="zh-cn">中文(简体)</option>
           <option value="zh-tw">中文(繁體)</option>
diff --git a/docs/html/tools/help/adb.jd b/docs/html/tools/help/adb.jd
index 641d463..2faff4f 100644
--- a/docs/html/tools/help/adb.jd
+++ b/docs/html/tools/help/adb.jd
@@ -420,62 +420,54 @@
 <ol>
 
 <li>
-Connect Android device and adb host computer
+<p>Connect your Android device and adb host computer
 to a common Wi-Fi network accessible to both.
 We have found that not all access points
 are suitable; you may need to use an access point
-whose firewall is configured properly to support adb.
+whose firewall is configured properly to support adb.</p>
+
+<p class="note"><strong>Note: </strong>If you are attempting to connect
+to a Wear device, force it to connect to Wi-Fi by shutting off Bluetooth
+on the phone connected to it.</p>
 </li>
 
 <li>
-Connect the device with USB cable to host.
+Connect the device to the host computer with a USB cable.
 </li>
 
 <li>
-Make sure adb is running in USB mode on host.
-<pre>
-$ adb usb
-restarting in USB mode
-</pre>
-</li>
-
-<li>
-Connect to the device over USB.
-<pre>
-$ adb devices
-List of devices attached
-######## device
-</pre>
-</li>
-
-<li>
-Restart host adb in tcpip mode.
-<pre>
+Set the target device to listen for a TCP/IP connection on port 5555.
+<pre class="no-pretty-print">
 $ adb tcpip 5555
-restarting in TCP mode port: 5555
 </pre>
 </li>
 
 <li>
-Find out the IP address of the Android device:
-Settings -> About tablet -> Status -> IP address.
-Remember the IP address, of the form <code>#.#.#.#</code>.
+Disconnect the USB cable from the target device.
 </li>
 
 <li>
-Connect adb host to device:
-<pre>
-$ adb connect #.#.#.#
-connected to #.#.#.#:5555
+Find the IP address of the Android device. For example, on a Nexus device, you can find
+the IP address at <strong>Settings</strong> &gt; <strong>About tablet</strong>
+(or <strong>About phone</strong>) &gt; <strong>Status</strong> &gt; <strong>IP address</strong>. Or,
+on an Android Wear device, you can find the IP address at <strong>Settings</strong> &gt;
+<strong>Wi-Fi Settings</strong> &gt; <strong>Advanced</strong> &gt; <strong>IP address</strong>.
+</li>
+
+<li>
+Connect to the device, identifying it by IP address.
+<pre class="no-pretty-print">
+$ adb connect &lt;device-ip-address&gt;
 </pre>
 </li>
 
+
 <li>
-Remove USB cable from device, and confirm you can still access device:
-<pre>
+Confirm that your host computer is connected to the target device:
+<pre class="no-pretty-print">
 $ adb devices
 List of devices attached
-#.#.#.#:5555 device
+&lt;device-ip-address&gt;:5555 device
 </pre>
 
 </ol>
@@ -500,10 +492,10 @@
 
 <li>
 Or if that doesn't work, reset your adb host:
-<pre>
+<pre class="no-pretty-print">
 adb kill-server
 </pre>
 and then start over from the beginning.
 </li>
 
-</ol>
\ No newline at end of file
+</ol>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 5279969..7cffdd8 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -989,6 +989,9 @@
             <a href="<?cs var:toroot ?>training/wearables/watch-faces/information.html">Showing Information in Watch Faces</a>
           </li>
           <li>
+            <a href="<?cs var:toroot ?>training/wearables/watch-faces/interacting.html">Creating Interactive Watch Faces</a>
+          </li>
+          <li>
             <a href="<?cs var:toroot ?>training/wearables/watch-faces/configuration.html">Providing Configuration Activities</a>
           </li>
           <li>
diff --git a/docs/html/training/wearables/watch-faces/index.jd b/docs/html/training/wearables/watch-faces/index.jd
index ec428c1..a329fda 100644
--- a/docs/html/training/wearables/watch-faces/index.jd
+++ b/docs/html/training/wearables/watch-faces/index.jd
@@ -65,6 +65,9 @@
 <dt><a href="{@docRoot}training/wearables/watch-faces/information.html">
 Showing Information in Watch Faces</a></dt>
 <dd>Learn how to incorporate contextual information into your watch face.</dd>
+<dt><a href="{@docRoot}training/wearables/watch-faces/interacting.html">
+Creating Interactive Watch Faces</a></dt>
+<dd>Learn how to enable the user to interact with your watch face.</dd>
 <dt><a href="{@docRoot}training/wearables/watch-faces/configuration.html">
 Providing Configuration Activities</a></dt>
 <dd>Learn how to create watch faces with configurable parameters.</dd>
diff --git a/docs/html/training/wearables/watch-faces/interacting.jd b/docs/html/training/wearables/watch-faces/interacting.jd
new file mode 100644
index 0000000..5a44fde
--- /dev/null
+++ b/docs/html/training/wearables/watch-faces/interacting.jd
@@ -0,0 +1,133 @@
+page.title=Creating Interactive Watch Faces
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#Construct">Construct an Interactive Watch Face</a></li>
+  <li><a href="#Handle">Handle Gestures</a></li>
+</ol>
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}design/wear/watchfaces.html">Watch Faces for Android Wear</a></li>
+</ul>
+<h2>Related Samples</h2>
+  <ul>
+    <li><a href="{@docRoot}samples/WatchFace/index.html">WatchFace</a></li>
+  </ul>
+</div>
+</div>
+
+<p>Your watch's display is more than just a pretty face: Users can  interact with it.
+For example, a user might tap the watch face to learn what song is currently playing, or
+to see the day's agenda. Android Wear allows Android Wear watch faces to accept
+the single-tap gesture at a given location on the watch face, as long as there's not another
+UI element that also responds to that gesture.
+
+<p>This lesson teaches you how to implement an interactive watch face by first constructing the
+watch face style, and then implementing gesture handling.</p>
+
+<p class="note"><strong>Note:</strong> Before beginning development work on your interactive watch
+face, you should be sure to read the <a href="{@docRoot}design/wear/watchfaces.html">Watch Faces for
+Android Wear</a> design guide.
+
+<h2 id="Construct">Handling Tap Events</h2>
+
+<p>When constructing an interactive watch-face style, the first thing the app must do is tell the
+system that the watch face receives <a href="{@docRoot}design/wear/watchfaces.html#ag">tap events</a>.
+The following example shows how to do this:
+
+<pre>
+setWatchFaceStyle(new WatchFaceStyle.Builder(mService)
+    .setAcceptsTapEvents(true)
+    // other style customizations
+    .build());
+</pre>
+
+<p>When the system detects a tap on the watch face, it triggers the
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTapCommand(int, int, int, long)">
+{@code WatchFaceService.Engine.onTapCommand()}</a> method. Override this method in your
+implementation of
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.Engine.html">
+{@code WatchFaceService.Engine}</a>to initiate the action you wish to perform, such
+as showing a detailed step count or changing the theme of the watch face. The code snippet
+in <a href="#Handle">Handle Gestures</a> shows an example of such an
+implementation.</p>
+
+<h2 id="Handle">Handle Gestures</h2>
+
+<p> To provide a consistent user experience, the system
+reserves gestures such as drag and long-press for system UI elements.
+Therefore, the system does not send raw touch events to the watch face. Instead, the system forwards specific commands to the
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onTapCommand(int, int, int, long)">
+onTapCommand()</a> method.
+
+<p>The system sends the first command,
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH">
+{@code TAP_TYPE_TOUCH}</a>, when the user initially touches the
+screen. This event lets you provide visual feedback to the user on touch.  Your app should not
+launch a UI when this event triggers. Launching a UI prevents drag events from opening the app
+launcher, settings shade, and notifications stream.</p>
+
+<p>Before sending the next command, the system judges whether the contact is a single tap, which is
+<a href="{@docRoot}design/wear/watchfaces.html#ag">the only gesture allowed</a>. If the user
+immediately lifts their finger, the system determines that a single tap took place, and forwards
+a
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP"</a>
+{@code TAP_TYPE_TAP}</a> event. If the user does not immediately lift their finger, the system
+forwards a
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL"</a>
+{@code TAP_TYPE_TOUCH_CANCEL}</a> event. Once the user has triggered a
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TOUCH_CANCEL"</a>
+{@code TAP_TYPE_TOUCH_CANCEL}</a> event, they cannot trigger a
+<a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.html#TAP_TYPE_TAP"</a>
+{@code TAP_TYPE_TAP}</a> event until they
+make a new contact with the screen.</p>
+
+<p>The following example shows you how to implement tap events on a watch face:</p>
+
+
+<pre>
+&#64;Override
+public void onTapCommand(
+       &#64;TapType int tapType, int x, int y, long eventTime) {
+    switch (tapType) {
+        case WatchFaceService.TAP_TYPE_TAP:
+            hideTapHighlight();
+            if (withinTapRegion(x, y)) {
+                // Implement the tap action
+                // (e.g. show detailed step count)
+                onWatchFaceTap();
+            }
+            break;
+
+        case WatchFaceService.TAP_TYPE_TOUCH:
+            if (withinTapRegion(x, y)) {
+                // Provide visual feedback of touch event
+                startTapHighlight(x, y, eventTime);
+            }
+            break;
+
+        case WatchFaceService.TAP_TYPE_TOUCH_CANCEL:
+            hideTapHighlight();
+            break;
+
+        default:
+            super.onTapCommand(tapType, x, y, eventTime);
+            break;
+    }
+}
+</pre>
+
+<p>In this example, the app determines what kind of event has taken place,
+and responds accordingly. If the event is initial contact by the user's finger,
+the app displays visual feedback. If the event is an immediate lifting
+of the finger after contact, it performs the action on which the
+user tapped. If the event is prolonged contact by the finger, the app
+does nothing.</p>
+
+
+
+
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 0e9823d..91e704a 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -486,9 +486,9 @@
      */
     public enum Direction {
         /** clockwise */
-        CW  (1),    // must match enum in SkPath.h
+        CW  (0),    // must match enum in SkPath.h
         /** counter-clockwise */
-        CCW (2);    // must match enum in SkPath.h
+        CCW (1);    // must match enum in SkPath.h
 
         Direction(int ni) {
             nativeInt = ni;
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 32f6a89..464f3de 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -855,7 +855,8 @@
 
         // Position the shader to account for canvas translation.
         if (mMaskShader != null) {
-            mMaskMatrix.setTranslate(-x, -y);
+            final Rect bounds = getBounds();
+            mMaskMatrix.setTranslate(bounds.left - x, bounds.top - y);
             mMaskShader.setLocalMatrix(mMaskMatrix);
         }
 
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 751531e..20ecda2 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -52,14 +52,14 @@
 // If this is set to negative value, then all the edge will be tessellated.
 #define ALPHA_THRESHOLD (0.1f / 255.0f)
 
-#include <math.h>
-#include <utils/Log.h>
-
 #include "AmbientShadow.h"
+
 #include "ShadowTessellator.h"
 #include "Vertex.h"
 #include "VertexBuffer.h"
-#include "utils/MathUtils.h"
+
+#include <algorithm>
+#include <utils/Log.h>
 
 namespace android {
 namespace uirenderer {
@@ -78,7 +78,7 @@
 // The input z value will be converted to be non-negative inside.
 // The output must be ranged from 0 to 1.
 inline float getAlphaFromFactoredZ(float factoredZ) {
-    return 1.0 / (1 + MathUtils::max(factoredZ, 0.0f));
+    return 1.0 / (1 + std::max(factoredZ, 0.0f));
 }
 
 // The shader is using gaussian function e^-(1-x)*(1-x)*4, therefore, we transform
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 512e0e2..5ca2a2f 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -36,8 +36,8 @@
         , mFinalValue(finalValue)
         , mDeltaValue(0)
         , mFromValue(0)
-        , mStagingPlayState(NOT_STARTED)
-        , mPlayState(NOT_STARTED)
+        , mStagingPlayState(PlayState::NotStarted)
+        , mPlayState(PlayState::NotStarted)
         , mHasStartValue(false)
         , mStartTime(0)
         , mDuration(300)
@@ -50,7 +50,7 @@
 
 void BaseRenderNodeAnimator::checkMutable() {
     // Should be impossible to hit as the Java-side also has guards for this
-    LOG_ALWAYS_FATAL_IF(mStagingPlayState != NOT_STARTED,
+    LOG_ALWAYS_FATAL_IF(mStagingPlayState != PlayState::NotStarted,
             "Animator has already been started!");
 }
 
@@ -92,9 +92,9 @@
     if (mStagingPlayState > mPlayState) {
         mPlayState = mStagingPlayState;
         // Oh boy, we're starting! Man the battle stations!
-        if (mPlayState == RUNNING) {
+        if (mPlayState == PlayState::Running) {
             transitionToRunning(context);
-        } else if (mPlayState == FINISHED) {
+        } else if (mPlayState == PlayState::Finished) {
             callOnFinishedListener(context);
         }
     }
@@ -124,10 +124,10 @@
 }
 
 bool BaseRenderNodeAnimator::animate(AnimationContext& context) {
-    if (mPlayState < RUNNING) {
+    if (mPlayState < PlayState::Running) {
         return false;
     }
-    if (mPlayState == FINISHED) {
+    if (mPlayState == PlayState::Finished) {
         return true;
     }
 
@@ -141,18 +141,18 @@
     }
 
     float fraction = 1.0f;
-    if (mPlayState == RUNNING && mDuration > 0) {
+    if (mPlayState == PlayState::Running && mDuration > 0) {
         fraction = (float)(context.frameTimeMs() - mStartTime) / mDuration;
     }
     if (fraction >= 1.0f) {
         fraction = 1.0f;
-        mPlayState = FINISHED;
+        mPlayState = PlayState::Finished;
     }
 
     fraction = mInterpolator->interpolate(fraction);
     setValue(mTarget, mFromValue + (mDeltaValue * fraction));
 
-    if (mPlayState == FINISHED) {
+    if (mPlayState == PlayState::Finished) {
         callOnFinishedListener(context);
         return true;
     }
@@ -161,8 +161,8 @@
 }
 
 void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
-    if (mPlayState < FINISHED) {
-        mPlayState = FINISHED;
+    if (mPlayState < PlayState::Finished) {
+        mPlayState = PlayState::Finished;
         callOnFinishedListener(context);
     }
 }
@@ -212,9 +212,9 @@
 }
 
 void RenderPropertyAnimator::onStagingPlayStateChanged() {
-    if (mStagingPlayState == RUNNING) {
+    if (mStagingPlayState == PlayState::Running) {
         (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
-    } else if (mStagingPlayState == FINISHED) {
+    } else if (mStagingPlayState == PlayState::Finished) {
         // We're being canceled, so make sure that whatever values the UI thread
         // is observing for us is pushed over
         mTarget->setPropertyFieldsDirty(dirtyMask());
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 1b3d8e7..aea95bf 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -59,8 +59,8 @@
         mMayRunAsync = mayRunAsync;
     }
     bool mayRunAsync() { return mMayRunAsync; }
-    ANDROID_API void start() { mStagingPlayState = RUNNING; onStagingPlayStateChanged(); }
-    ANDROID_API void end() { mStagingPlayState = FINISHED; onStagingPlayStateChanged(); }
+    ANDROID_API void start() { mStagingPlayState = PlayState::Running; onStagingPlayStateChanged(); }
+    ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); }
 
     void attach(RenderNode* target);
     virtual void onAttached() {}
@@ -68,8 +68,8 @@
     void pushStaging(AnimationContext& context);
     bool animate(AnimationContext& context);
 
-    bool isRunning() { return mPlayState == RUNNING; }
-    bool isFinished() { return mPlayState == FINISHED; }
+    bool isRunning() { return mPlayState == PlayState::Running; }
+    bool isFinished() { return mPlayState == PlayState::Finished; }
     float finalValue() { return mFinalValue; }
 
     ANDROID_API virtual uint32_t dirtyMask() = 0;
@@ -77,6 +77,12 @@
     void forceEndNow(AnimationContext& context);
 
 protected:
+    enum class PlayState {
+        NotStarted,
+        Running,
+        Finished,
+    };
+
     BaseRenderNodeAnimator(float finalValue);
     virtual ~BaseRenderNodeAnimator();
 
@@ -88,12 +94,6 @@
 
     virtual void onStagingPlayStateChanged() {}
 
-    enum PlayState {
-        NOT_STARTED,
-        RUNNING,
-        FINISHED,
-    };
-
     RenderNode* mTarget;
 
     float mFinalValue;
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f663f07..ff71313 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -245,7 +245,7 @@
     FLUSH_LOGD("Flushing caches (mode %d)", mode);
 
     switch (mode) {
-        case kFlushMode_Full:
+        case FlushMode::Full:
             textureCache.clear();
             patchCache.clear();
             dropShadowCache.clear();
@@ -254,13 +254,13 @@
             fboCache.clear();
             dither.clear();
             // fall through
-        case kFlushMode_Moderate:
+        case FlushMode::Moderate:
             fontRenderer->flush();
             textureCache.flush();
             pathCache.clear();
             tessellationCache.clear();
             // fall through
-        case kFlushMode_Layers:
+        case FlushMode::Layers:
             layerCache.clear();
             renderBufferCache.clear();
             break;
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index a02e15d..929db17 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -83,10 +83,10 @@
     static Caches* sInstance;
 
 public:
-    enum FlushMode {
-        kFlushMode_Layers = 0,
-        kFlushMode_Moderate,
-        kFlushMode_Full
+    enum class FlushMode {
+        Layers = 0,
+        Moderate,
+        Full
     };
 
     /**
@@ -103,7 +103,7 @@
 
     /**
      * Destroys all resources associated with this cache. This should
-     * be called after a flush(kFlushMode_Full).
+     * be called after a flush(FlushMode::Full).
      */
     void terminate();
 
diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h
index 3c77b3d..4bd4ac8 100644
--- a/libs/hwui/Canvas.h
+++ b/libs/hwui/Canvas.h
@@ -85,10 +85,6 @@
     virtual void getMatrix(SkMatrix* outMatrix) const = 0;
     virtual void setMatrix(const SkMatrix& matrix) = 0;
 
-    /// Like setMatrix(), but to be translated into local / view-relative coordinates
-    /// rather than executed in global / device coordinates at rendering time.
-    virtual void setLocalMatrix(const SkMatrix& matrix) = 0;
-
     virtual void concat(const SkMatrix& matrix) = 0;
     virtual void rotate(float degrees) = 0;
     virtual void scale(float sx, float sy) = 0;
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index e22b0d3..e307ad9 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -138,7 +138,7 @@
 }
 
 void CanvasState::setMatrix(const Matrix4& matrix) {
-    mSnapshot->transform->load(matrix);
+    *(mSnapshot->transform) = matrix;
 }
 
 void CanvasState::concatMatrix(const SkMatrix& matrix) {
@@ -155,17 +155,20 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 bool CanvasState::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
-    mDirtyClip |= mSnapshot->clip(left, top, right, bottom, op);
+    mSnapshot->clip(left, top, right, bottom, op);
+    mDirtyClip = true;
     return !mSnapshot->clipIsEmpty();
 }
 
 bool CanvasState::clipPath(const SkPath* path, SkRegion::Op op) {
-    mDirtyClip |= mSnapshot->clipPath(*path, op);
+    mSnapshot->clipPath(*path, op);
+    mDirtyClip = true;
     return !mSnapshot->clipIsEmpty();
 }
 
 bool CanvasState::clipRegion(const SkRegion* region, SkRegion::Op op) {
-    mDirtyClip |= mSnapshot->clipRegionTransformed(*region, op);
+    mSnapshot->clipRegionTransformed(*region, op);
+    mDirtyClip = true;
     return !mSnapshot->clipIsEmpty();
 }
 
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index b1a6844..8e7efb4 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -32,9 +32,7 @@
 }
 
 static void handlePoint(Rect& transformedBounds, const Matrix4& transform, float x, float y) {
-    Vertex v;
-    v.x = x;
-    v.y = y;
+    Vertex v = {x, y};
     transform.mapPoint(v.x, v.y);
     transformedBounds.expandToCoverVertex(v.x, v.y);
 }
@@ -187,7 +185,7 @@
  */
 
 ClipArea::ClipArea()
-        : mMode(kModeRectangle) {
+        : mMode(Mode::Rectangle) {
 }
 
 /*
@@ -200,45 +198,46 @@
 }
 
 void ClipArea::setEmpty() {
-    mMode = kModeRectangle;
+    mMode = Mode::Rectangle;
     mClipRect.setEmpty();
     mClipRegion.setEmpty();
     mRectangleList.setEmpty();
 }
 
 void ClipArea::setClip(float left, float top, float right, float bottom) {
-    mMode = kModeRectangle;
+    mMode = Mode::Rectangle;
     mClipRect.set(left, top, right, bottom);
     mClipRegion.setEmpty();
 }
 
-bool ClipArea::clipRectWithTransform(float left, float top, float right,
+void ClipArea::clipRectWithTransform(float left, float top, float right,
         float bottom, const mat4* transform, SkRegion::Op op) {
     Rect r(left, top, right, bottom);
-    return clipRectWithTransform(r, transform, op);
+    clipRectWithTransform(r, transform, op);
 }
 
-bool ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform,
+void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform,
         SkRegion::Op op) {
     switch (mMode) {
-    case kModeRectangle:
-        return rectangleModeClipRectWithTransform(r, transform, op);
-    case kModeRectangleList:
-        return rectangleListModeClipRectWithTransform(r, transform, op);
-    case kModeRegion:
-        return regionModeClipRectWithTransform(r, transform, op);
+    case Mode::Rectangle:
+        rectangleModeClipRectWithTransform(r, transform, op);
+        break;
+    case Mode::RectangleList:
+        rectangleListModeClipRectWithTransform(r, transform, op);
+        break;
+    case Mode::Region:
+        regionModeClipRectWithTransform(r, transform, op);
+        break;
     }
-    return false;
 }
 
-bool ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
+void ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
     enterRegionMode();
     mClipRegion.op(region, op);
     onClipRegionUpdated();
-    return true;
 }
 
-bool ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform,
+void ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform,
         SkRegion::Op op) {
     SkMatrix skTransform;
     transform->copyTo(skTransform);
@@ -246,7 +245,7 @@
     path.transform(skTransform, &transformed);
     SkRegion region;
     regionFromPath(transformed, region);
-    return clipRegion(region, op);
+    clipRegion(region, op);
 }
 
 /*
@@ -257,19 +256,20 @@
     // Entering rectangle mode discards any
     // existing clipping information from the other modes.
     // The only way this occurs is by a clip setting operation.
-    mMode = kModeRectangle;
+    mMode = Mode::Rectangle;
 }
 
-bool ClipArea::rectangleModeClipRectWithTransform(const Rect& r,
+void ClipArea::rectangleModeClipRectWithTransform(const Rect& r,
         const mat4* transform, SkRegion::Op op) {
 
     if (op == SkRegion::kReplace_Op && transform->rectToRect()) {
         mClipRect = r;
         transform->mapRect(mClipRect);
-        return true;
+        return;
     } else if (op != SkRegion::kIntersect_Op) {
         enterRegionMode();
-        return regionModeClipRectWithTransform(r, transform, op);
+        regionModeClipRectWithTransform(r, transform, op);
+        return;
     }
 
     if (transform->rectToRect()) {
@@ -279,19 +279,18 @@
         if (!hasIntersection) {
             mClipRect.setEmpty();
         }
-        return true;
+        return;
     }
 
     enterRectangleListMode();
-    return rectangleListModeClipRectWithTransform(r, transform, op);
+    rectangleListModeClipRectWithTransform(r, transform, op);
 }
 
-bool ClipArea::rectangleModeClipRectWithTransform(float left, float top,
+void ClipArea::rectangleModeClipRectWithTransform(float left, float top,
         float right, float bottom, const mat4* transform, SkRegion::Op op) {
     Rect r(left, top, right, bottom);
-    bool result = rectangleModeClipRectWithTransform(r, transform, op);
+    rectangleModeClipRectWithTransform(r, transform, op);
     mClipRect = mRectangleList.calculateBounds();
-    return result;
 }
 
 /*
@@ -302,25 +301,24 @@
     // Is is only legal to enter rectangle list mode from
     // rectangle mode, since rectangle list mode cannot represent
     // all clip areas that can be represented by a region.
-    ALOG_ASSERT(mMode == kModeRectangle);
-    mMode = kModeRectangleList;
+    ALOG_ASSERT(mMode == Mode::Rectangle);
+    mMode = Mode::RectangleList;
     mRectangleList.set(mClipRect, Matrix4::identity());
 }
 
-bool ClipArea::rectangleListModeClipRectWithTransform(const Rect& r,
+void ClipArea::rectangleListModeClipRectWithTransform(const Rect& r,
         const mat4* transform, SkRegion::Op op) {
     if (op != SkRegion::kIntersect_Op
             || !mRectangleList.intersectWith(r, *transform)) {
         enterRegionMode();
-        return regionModeClipRectWithTransform(r, transform, op);
+        regionModeClipRectWithTransform(r, transform, op);
     }
-    return true;
 }
 
-bool ClipArea::rectangleListModeClipRectWithTransform(float left, float top,
+void ClipArea::rectangleListModeClipRectWithTransform(float left, float top,
         float right, float bottom, const mat4* transform, SkRegion::Op op) {
     Rect r(left, top, right, bottom);
-    return rectangleListModeClipRectWithTransform(r, transform, op);
+    rectangleListModeClipRectWithTransform(r, transform, op);
 }
 
 /*
@@ -329,9 +327,9 @@
 
 void ClipArea::enterRegionMode() {
     Mode oldMode = mMode;
-    mMode = kModeRegion;
-    if (oldMode != kModeRegion) {
-        if (oldMode == kModeRectangle) {
+    mMode = Mode::Region;
+    if (oldMode != Mode::Region) {
+        if (oldMode == Mode::Rectangle) {
             mClipRegion.setRect(mClipRect.left, mClipRect.top,
                     mClipRect.right, mClipRect.bottom);
         } else {
@@ -341,20 +339,18 @@
     }
 }
 
-bool ClipArea::regionModeClipRectWithTransform(const Rect& r,
+void ClipArea::regionModeClipRectWithTransform(const Rect& r,
         const mat4* transform, SkRegion::Op op) {
     SkPath transformedRect = pathFromTransformedRectangle(r, *transform);
     SkRegion transformedRectRegion;
     regionFromPath(transformedRect, transformedRectRegion);
     mClipRegion.op(transformedRectRegion, op);
     onClipRegionUpdated();
-    return true;
 }
 
-bool ClipArea::regionModeClipRectWithTransform(float left, float top,
+void ClipArea::regionModeClipRectWithTransform(float left, float top,
         float right, float bottom, const mat4* transform, SkRegion::Op op) {
-    return regionModeClipRectWithTransform(Rect(left, top, right, bottom),
-            transform, op);
+    regionModeClipRectWithTransform(Rect(left, top, right, bottom), transform, op);
 }
 
 void ClipArea::onClipRegionUpdated() {
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index 51ef27b..38fefe5 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -80,6 +80,13 @@
 };
 
 class ClipArea {
+private:
+    enum class Mode {
+        Rectangle,
+        Region,
+        RectangleList
+    };
+
 public:
     ClipArea();
 
@@ -91,12 +98,12 @@
 
     void setEmpty();
     void setClip(float left, float top, float right, float bottom);
-    bool clipRectWithTransform(float left, float top, float right, float bottom,
-            const mat4* transform, SkRegion::Op op = SkRegion::kIntersect_Op);
-    bool clipRectWithTransform(const Rect& r, const mat4* transform,
-            SkRegion::Op op = SkRegion::kIntersect_Op);
-    bool clipRegion(const SkRegion& region, SkRegion::Op op = SkRegion::kIntersect_Op);
-    bool clipPathWithTransform(const SkPath& path, const mat4* transform,
+    void clipRectWithTransform(float left, float top, float right, float bottom,
+            const mat4* transform, SkRegion::Op op);
+    void clipRectWithTransform(const Rect& r, const mat4* transform,
+            SkRegion::Op op);
+    void clipRegion(const SkRegion& region, SkRegion::Op op);
+    void clipPathWithTransform(const SkPath& path, const mat4* transform,
             SkRegion::Op op);
 
     const Rect& getClipRect() const {
@@ -112,41 +119,39 @@
     }
 
     bool isRegion() const {
-        return kModeRegion == mMode;
+        return Mode::Region == mMode;
     }
 
     bool isSimple() const {
-        return mMode == kModeRectangle;
+        return mMode == Mode::Rectangle;
     }
 
     bool isRectangleList() const {
-        return mMode == kModeRectangleList;
+        return mMode == Mode::RectangleList;
     }
 
 private:
     void enterRectangleMode();
-    bool rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
-    bool rectangleModeClipRectWithTransform(float left, float top, float right,
+    void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
+    void rectangleModeClipRectWithTransform(float left, float top, float right,
             float bottom, const mat4* transform, SkRegion::Op op);
 
     void enterRectangleListMode();
-    bool rectangleListModeClipRectWithTransform(float left, float top,
+    void rectangleListModeClipRectWithTransform(float left, float top,
             float right, float bottom, const mat4* transform, SkRegion::Op op);
-    bool rectangleListModeClipRectWithTransform(const Rect& r,
+    void rectangleListModeClipRectWithTransform(const Rect& r,
             const mat4* transform, SkRegion::Op op);
 
     void enterRegionModeFromRectangleMode();
     void enterRegionModeFromRectangleListMode();
     void enterRegionMode();
-    bool regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
+    void regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
             SkRegion::Op op);
-    bool regionModeClipRectWithTransform(float left, float top, float right,
+    void regionModeClipRectWithTransform(float left, float top, float right,
             float bottom, const mat4* transform, SkRegion::Op op);
 
     void ensureClipRegion();
     void onClipRegionUpdated();
-    bool clipRegionOp(float left, float top, float right, float bottom,
-            SkRegion::Op op);
 
     SkRegion createViewportRegion() {
         return SkRegion(mViewportBounds.toSkIRect());
@@ -158,12 +163,6 @@
         pathAsRegion.setPath(path, createViewportRegion());
     }
 
-    enum Mode {
-        kModeRectangle,
-        kModeRegion,
-        kModeRectangleList
-    };
-
     Mode mMode;
     Rect mViewportBounds;
     Rect mClipRect;
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 61c5883..506bfad 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -168,11 +168,6 @@
     mState.setMatrix(matrix);
 }
 
-void DisplayListCanvas::setLocalMatrix(const SkMatrix& matrix) {
-    addStateOp(new (alloc()) SetLocalMatrixOp(matrix));
-    mState.setMatrix(matrix);
-}
-
 void DisplayListCanvas::concat(const SkMatrix& matrix) {
     addStateOp(new (alloc()) ConcatMatrixOp(matrix));
     mState.concatMatrix(matrix);
@@ -221,11 +216,11 @@
     addRenderNodeOp(op);
 }
 
-void DisplayListCanvas::drawLayer(DeferredLayerUpdater* layerHandle, float x, float y) {
+void DisplayListCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
     // We ref the DeferredLayerUpdater due to its thread-safe ref-counting
     // semantics.
     mDisplayListData->ref(layerHandle);
-    addDrawOp(new (alloc()) DrawLayerOp(layerHandle->backingLayer(), x, y));
+    addDrawOp(new (alloc()) DrawLayerOp(layerHandle->backingLayer()));
 }
 
 void DisplayListCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index 3b61904..392bb3e 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -91,7 +91,7 @@
 // ----------------------------------------------------------------------------
 // HWUI Canvas draw operations - special
 // ----------------------------------------------------------------------------
-    void drawLayer(DeferredLayerUpdater* layerHandle, float x, float y);
+    void drawLayer(DeferredLayerUpdater* layerHandle);
     void drawRenderNode(RenderNode* renderNode);
 
     // TODO: rename for consistency
@@ -143,7 +143,6 @@
     // Matrix
     virtual void getMatrix(SkMatrix* outMatrix) const override { mState.getMatrix(outMatrix); }
     virtual void setMatrix(const SkMatrix& matrix) override;
-    virtual void setLocalMatrix(const SkMatrix& matrix) override;
 
     virtual void concat(const SkMatrix& matrix) override;
     virtual void rotate(float degrees) override;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 8ff58d4..14126a9 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -472,7 +472,9 @@
             : mMatrix(matrix) {}
 
     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
-        renderer.setMatrix(mMatrix);
+        // Setting a matrix on a Canvas isn't equivalent to setting a total matrix on the scene.
+        // Set a canvas-relative matrix on the renderer instead.
+        renderer.setLocalMatrix(mMatrix);
     }
 
     virtual void output(int level, uint32_t logFlags) const override {
@@ -489,25 +491,6 @@
     const SkMatrix mMatrix;
 };
 
-class SetLocalMatrixOp : public StateOp {
-public:
-    SetLocalMatrixOp(const SkMatrix& matrix)
-            : mMatrix(matrix) {}
-
-    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
-        renderer.setLocalMatrix(mMatrix);
-    }
-
-    virtual void output(int level, uint32_t logFlags) const override {
-        OP_LOG("SetLocalMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
-    }
-
-    virtual const char* name() override { return "SetLocalMatrix"; }
-
-private:
-    const SkMatrix mMatrix;
-};
-
 class ConcatMatrixOp : public StateOp {
 public:
     ConcatMatrixOp(const SkMatrix& matrix)
@@ -1541,23 +1524,21 @@
 
 class DrawLayerOp : public DrawOp {
 public:
-    DrawLayerOp(Layer* layer, float x, float y)
-            : DrawOp(nullptr), mLayer(layer), mX(x), mY(y) {}
+    DrawLayerOp(Layer* layer)
+            : DrawOp(nullptr), mLayer(layer) {}
 
     virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
-        renderer.drawLayer(mLayer, mX, mY);
+        renderer.drawLayer(mLayer);
     }
 
     virtual void output(int level, uint32_t logFlags) const override {
-        OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
+        OP_LOG("Draw Layer %p", mLayer);
     }
 
     virtual const char* name() override { return "DrawLayer"; }
 
 private:
     Layer* mLayer;
-    float mX;
-    float mY;
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 057c231..75c3ead 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -26,14 +26,12 @@
 #include "Rect.h"
 #include "renderstate/RenderState.h"
 #include "utils/Blur.h"
-#include "utils/MathUtils.h"
 #include "utils/Timing.h"
 
+#include <algorithm>
+#include <cutils/properties.h>
 #include <SkGlyph.h>
 #include <SkUtils.h>
-
-#include <cutils/properties.h>
-
 #include <utils/Log.h>
 
 #ifdef ANDROID_ENABLE_RENDERSCRIPT
@@ -118,10 +116,10 @@
 
     uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize;
 
-    mSmallCacheWidth = MathUtils::min(mSmallCacheWidth, maxTextureSize);
-    mSmallCacheHeight = MathUtils::min(mSmallCacheHeight, maxTextureSize);
-    mLargeCacheWidth = MathUtils::min(mLargeCacheWidth, maxTextureSize);
-    mLargeCacheHeight = MathUtils::min(mLargeCacheHeight, maxTextureSize);
+    mSmallCacheWidth = std::min(mSmallCacheWidth, maxTextureSize);
+    mSmallCacheHeight = std::min(mSmallCacheHeight, maxTextureSize);
+    mLargeCacheWidth = std::min(mLargeCacheWidth, maxTextureSize);
+    mLargeCacheHeight = std::min(mLargeCacheHeight, maxTextureSize);
 
     if (sLogFontRendererCreate) {
         INIT_LOGD("  Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i",
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 288fed3..e27b26b 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -274,7 +274,7 @@
         SkXfermode::Mode mode;
         SkScalar srcColorMatrix[20];
         if (colorFilter->asColorMode(&color, &mode)) {
-            mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::kColorBlend;
+            mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Blend;
             mDescription.colorMode = mode;
 
             const float alpha = SkColorGetA(color) / 255.0f;
@@ -286,7 +286,7 @@
                     alpha,
             };
         } else if (colorFilter->asColorMatrix(srcColorMatrix)) {
-            mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::kColorMatrix;
+            mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Matrix;
 
             float* colorMatrix = mOutGlop->fill.filter.matrix.matrix;
             memcpy(colorMatrix, srcColorMatrix, 4 * sizeof(float));
@@ -305,7 +305,7 @@
             LOG_ALWAYS_FATAL("unsupported ColorFilter");
         }
     } else {
-        mOutGlop->fill.filterMode = ProgramDescription::kColorNone;
+        mOutGlop->fill.filterMode = ProgramDescription::ColorFilterMode::None;
     }
 }
 
@@ -467,8 +467,8 @@
         const int transformFlags) {
     TRIGGER_STAGE(kTransformStage);
 
-    mOutGlop->transform.ortho.load(ortho);
-    mOutGlop->transform.canvas.load(canvas);
+    mOutGlop->transform.ortho = ortho;
+    mOutGlop->transform.canvas = canvas;
     mOutGlop->transform.transformFlags = transformFlags;
 }
 
@@ -615,7 +615,7 @@
             shaderMatrix.loadInverse(mOutGlop->transform.canvas);
             shaderMatrix.multiply(mOutGlop->transform.modelView);
         } else {
-            shaderMatrix.load(mOutGlop->transform.modelView);
+            shaderMatrix = mOutGlop->transform.modelView;
         }
         SkiaShader::store(mCaches, *mShader, shaderMatrix,
                 &textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData));
diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp
index e1b0fc3..cc47f00 100644
--- a/libs/hwui/Interpolator.cpp
+++ b/libs/hwui/Interpolator.cpp
@@ -16,11 +16,11 @@
 
 #include "Interpolator.h"
 
-#include <cmath>
-#include <cutils/log.h>
-
 #include "utils/MathUtils.h"
 
+#include <algorithm>
+#include <cutils/log.h>
+
 namespace android {
 namespace uirenderer {
 
@@ -106,7 +106,7 @@
     weight = modff(lutpos, &ipart);
 
     int i1 = (int) ipart;
-    int i2 = MathUtils::min(i1 + 1, (int) mSize - 1);
+    int i2 = std::min(i1 + 1, (int) mSize - 1);
 
     LOG_ALWAYS_FATAL_IF(i1 < 0 || i2 < 0, "negatives in interpolation!"
             " i1=%d, i2=%d, input=%f, lutpos=%f, size=%zu, values=%p, ipart=%f, weight=%f",
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 928f91b..e748221 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -36,7 +36,7 @@
 namespace uirenderer {
 
 Layer::Layer(Type layerType, RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
-        : state(kState_Uncached)
+        : state(State::Uncached)
         , caches(Caches::getInstance())
         , renderState(renderState)
         , texture(caches)
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index b670870..e90f055 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -56,19 +56,19 @@
  */
 class Layer : public VirtualLightRefBase {
 public:
-    enum Type {
-        kType_Texture,
-        kType_DisplayList,
+    enum class Type {
+        Texture,
+        DisplayList,
     };
 
     // layer lifecycle, controlled from outside
-    enum State {
-        kState_Uncached = 0,
-        kState_InCache = 1,
-        kState_FailedToCache = 2,
-        kState_RemovedFromCache = 3,
-        kState_DeletedFromCache = 4,
-        kState_InGarbageList = 5,
+    enum class State {
+        Uncached = 0,
+        InCache = 1,
+        FailedToCache = 2,
+        RemovedFromCache = 3,
+        DeletedFromCache = 4,
+        InGarbageList = 5,
     };
     State state; // public for logging/debugging purposes
 
@@ -241,7 +241,7 @@
     }
 
     inline bool isTextureLayer() const {
-        return type == kType_Texture;
+        return type == Type::Texture;
     }
 
     inline SkColorFilter* getColorFilter() const {
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 33f40b0..39cadd1 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -81,7 +81,7 @@
         LAYER_LOGD("Destroying layer %dx%d, fbo %d", layer->getWidth(), layer->getHeight(),
                 layer->getFbo());
         mSize -= layer->getWidth() * layer->getHeight() * 4;
-        layer->state = Layer::kState_DeletedFromCache;
+        layer->state = Layer::State::DeletedFromCache;
         layer->decStrong(nullptr);
     }
 }
@@ -104,14 +104,14 @@
         mCache.erase(iter);
 
         layer = entry.mLayer;
-        layer->state = Layer::kState_RemovedFromCache;
+        layer->state = Layer::State::RemovedFromCache;
         mSize -= layer->getWidth() * layer->getHeight() * 4;
 
         LAYER_LOGD("Reusing layer %dx%d", layer->getWidth(), layer->getHeight());
     } else {
         LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight);
 
-        layer = new Layer(Layer::kType_DisplayList, renderState, entry.mWidth, entry.mHeight);
+        layer = new Layer(Layer::Type::DisplayList, renderState, entry.mWidth, entry.mHeight);
         layer->setBlend(true);
         layer->generateTexture();
         layer->bindTexture();
@@ -156,11 +156,11 @@
         mCache.insert(entry);
         mSize += size;
 
-        layer->state = Layer::kState_InCache;
+        layer->state = Layer::State::InCache;
         return true;
     }
 
-    layer->state = Layer::kState_FailedToCache;
+    layer->state = Layer::State::FailedToCache;
     return false;
 }
 
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 00add29..d8e6392 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -272,7 +272,7 @@
 Layer* LayerRenderer::createTextureLayer(RenderState& renderState) {
     LAYER_RENDERER_LOGD("Creating new texture layer");
 
-    Layer* layer = new Layer(Layer::kType_Texture, renderState, 0, 0);
+    Layer* layer = new Layer(Layer::Type::Texture, renderState, 0, 0);
     layer->setCacheable(false);
     layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
     layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f);
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 115e23c..73ebd1304 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -152,10 +152,6 @@
     mType = kTypeUnknown;
 }
 
-void Matrix4::load(const Matrix4& v) {
-    *this = v;
-}
-
 void Matrix4::load(const SkMatrix& v) {
     memset(data, 0, sizeof(data));
 
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index ed54a25..ed517ac 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -114,7 +114,6 @@
     void loadIdentity();
 
     void load(const float* v);
-    void load(const Matrix4& v);
     void load(const SkMatrix& v);
 
     void loadInverse(const Matrix4& v);
@@ -139,7 +138,7 @@
     void multiply(const Matrix4& v) {
         Matrix4 u;
         u.loadMultiply(*this, v);
-        load(u);
+        *this = u;
     }
 
     void multiply(float v);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7a56d42..5692d7e 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1141,7 +1141,7 @@
 
     // Transform and alpha always deferred, since they are used by state operations
     // (Note: saveLayer/restore use colorFilter and alpha, so we just save restore everything)
-    state.mMatrix.load(*currentMatrix);
+    state.mMatrix = *currentMatrix;
     state.mAlpha = currentSnapshot()->alpha;
 
     // always store/restore, since these are just pointers
@@ -1151,7 +1151,7 @@
 }
 
 void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore) {
-    setMatrix(state.mMatrix);
+    setGlobalMatrix(state.mMatrix);
     writableSnapshot()->alpha = state.mAlpha;
     writableSnapshot()->roundRectClipState = state.mRoundRectClipState;
     writableSnapshot()->projectionPathMask = state.mProjectionPathMask;
@@ -2098,8 +2098,9 @@
     mState.skew(sx, sy);
 }
 
-void OpenGLRenderer::setMatrix(const Matrix4& matrix) {
-    mState.setMatrix(matrix);
+void OpenGLRenderer::setLocalMatrix(const Matrix4& matrix) {
+    mState.setMatrix(mBaseTransform);
+    mState.concatMatrix(matrix);
 }
 
 void OpenGLRenderer::setLocalMatrix(const SkMatrix& matrix) {
@@ -2267,7 +2268,7 @@
     mDirty = true;
 }
 
-void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
+void OpenGLRenderer::drawLayer(Layer* layer) {
     if (!layer) {
         return;
     }
@@ -2283,7 +2284,7 @@
 
     bool clipRequired = false;
     const bool rejected = mState.calculateQuickRejectForScissor(
-            x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(),
+            0, 0, layer->layer.getWidth(), layer->layer.getHeight(),
             &clipRequired, nullptr, false);
 
     if (rejected) {
@@ -2312,7 +2313,7 @@
                     .setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
                     .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
                     .setTransform(*currentSnapshot(),  TransformFlags::None)
-                    .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
+                    .setModelViewOffsetRectSnap(0, 0, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
                     .build();
             DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
 #if DEBUG_LAYERS_AS_REGIONS
@@ -2325,7 +2326,7 @@
 
             SkPaint paint;
             paint.setColor(0x7f00ff00);
-            drawColorRect(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(), &paint);
+            drawColorRect(0, 0, layer->layer.getWidth(), layer->layer.getHeight(), &paint);
         }
     }
     layer->hasDrawnSinceUpdate = true;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 4f75482..af85e8c 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -35,6 +35,7 @@
 #include <SkBitmap.h>
 #include <SkCanvas.h>
 #include <SkColorFilter.h>
+#include <SkDrawLooper.h>
 #include <SkMatrix.h>
 #include <SkPaint.h>
 #include <SkRegion.h>
@@ -187,7 +188,7 @@
             const SkPaint* paint, int flags);
 
     void drawRenderNode(RenderNode* displayList, Rect& dirty, int32_t replayFlags = 1);
-    void drawLayer(Layer* layer, float x, float y);
+    void drawLayer(Layer* layer);
     void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
     void drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entry, int bitmapCount,
             TextureVertex* vertices, bool pureTranslate, const Rect& bounds, const SkPaint* paint);
@@ -367,8 +368,10 @@
     void restore();
     void restoreToCount(int saveCount);
 
-    void getMatrix(SkMatrix* outMatrix) const { mState.getMatrix(outMatrix); }
-    void setMatrix(const SkMatrix& matrix) { mState.setMatrix(matrix); }
+    void setGlobalMatrix(const Matrix4& matrix) {
+        mState.setMatrix(matrix);
+    }
+    void setLocalMatrix(const Matrix4& matrix);
     void setLocalMatrix(const SkMatrix& matrix);
     void concatMatrix(const SkMatrix& matrix) { mState.concatMatrix(matrix); }
 
diff --git a/libs/hwui/Outline.h b/libs/hwui/Outline.h
index 8d4d4f0..4bd4ae1 100644
--- a/libs/hwui/Outline.h
+++ b/libs/hwui/Outline.h
@@ -28,13 +28,13 @@
 public:
     Outline()
             : mShouldClip(false)
-            , mType(kOutlineType_None)
+            , mType(Type::None)
             , mRadius(0)
             , mAlpha(0.0f) {}
 
     void setRoundRect(int left, int top, int right, int bottom, float radius, float alpha) {
         mAlpha = alpha;
-        if (mType == kOutlineType_RoundRect
+        if (mType == Type::RoundRect
                 && left == mBounds.left
                 && right == mBounds.right
                 && top == mBounds.top
@@ -44,7 +44,7 @@
             return;
         }
 
-        mType = kOutlineType_RoundRect;
+        mType = Type::RoundRect;
         mBounds.set(left, top, right, bottom);
         mRadius = radius;
 
@@ -63,26 +63,26 @@
             setEmpty();
             return;
         }
-        mType = kOutlineType_ConvexPath;
+        mType = Type::ConvexPath;
         mPath = *outline;
         mBounds.set(outline->getBounds());
         mAlpha = alpha;
     }
 
     void setEmpty() {
-        mType = kOutlineType_Empty;
+        mType = Type::Empty;
         mPath.reset();
         mAlpha = 0.0f;
     }
 
     void setNone() {
-        mType = kOutlineType_None;
+        mType = Type::None;
         mPath.reset();
         mAlpha = 0.0f;
     }
 
     bool isEmpty() const {
-        return mType == kOutlineType_Empty;
+        return mType == Type::Empty;
     }
 
     float getAlpha() const {
@@ -99,7 +99,7 @@
 
     bool willClip() const {
         // only round rect outlines can be used for clipping
-        return mShouldClip && (mType == kOutlineType_RoundRect);
+        return mShouldClip && (mType == Type::RoundRect);
     }
 
     bool willRoundRectClip() const {
@@ -108,7 +108,7 @@
     }
 
     bool getAsRoundRect(Rect* outRect, float* outRadius) const {
-        if (mType == kOutlineType_RoundRect) {
+        if (mType == Type::RoundRect) {
             outRect->set(mBounds);
             *outRadius = mRadius;
             return true;
@@ -117,21 +117,21 @@
     }
 
     const SkPath* getPath() const {
-        if (mType == kOutlineType_None || mType == kOutlineType_Empty) return nullptr;
+        if (mType == Type::None || mType == Type::Empty) return nullptr;
 
         return &mPath;
     }
 
 private:
-    enum OutlineType {
-        kOutlineType_None = 0,
-        kOutlineType_Empty = 1,
-        kOutlineType_ConvexPath = 2,
-        kOutlineType_RoundRect = 3
+    enum class Type {
+        None = 0,
+        Empty = 1,
+        ConvexPath = 2,
+        RoundRect = 3
     };
 
     bool mShouldClip;
-    OutlineType mType;
+    Type mType;
     Rect mBounds;
     float mRadius;
     float mAlpha;
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 500f9e9..b471e78 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-#include <cmath>
-
-#include <utils/Log.h>
+#include "Patch.h"
 
 #include "Caches.h"
-#include "Patch.h"
 #include "Properties.h"
 #include "UvMapper.h"
 #include "utils/MathUtils.h"
 
+#include <algorithm>
+#include <utils/Log.h>
+
 namespace android {
 namespace uirenderer {
 
@@ -189,10 +189,10 @@
     const uint32_t oldQuadCount = quadCount;
     quadCount++;
 
-    x1 = MathUtils::max(x1, 0.0f);
-    x2 = MathUtils::max(x2, 0.0f);
-    y1 = MathUtils::max(y1, 0.0f);
-    y2 = MathUtils::max(y2, 0.0f);
+    x1 = std::max(x1, 0.0f);
+    x2 = std::max(x2, 0.0f);
+    y1 = std::max(y1, 0.0f);
+    y2 = std::max(y2, 0.0f);
 
     // Skip degenerate and transparent (empty) quads
     if ((mColors[oldQuadCount] == 0) || x1 >= x2 || y1 >= y2) {
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 8fa187c..b57b8f0 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -32,6 +32,15 @@
 #define DEBUG_DUMP_BUFFER()
 #endif
 
+#include "PathTessellator.h"
+
+#include "Matrix.h"
+#include "Vector.h"
+#include "Vertex.h"
+#include "utils/MathUtils.h"
+
+#include <algorithm>
+
 #include <SkPath.h>
 #include <SkPaint.h>
 #include <SkPoint.h>
@@ -44,12 +53,6 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
-#include "PathTessellator.h"
-#include "Matrix.h"
-#include "Vector.h"
-#include "Vertex.h"
-#include "utils/MathUtils.h"
-
 namespace android {
 namespace uirenderer {
 
@@ -152,7 +155,7 @@
             // always use 2 points for hairline
             if (halfStrokeWidth == 0.0f) return 2;
 
-            float threshold = MathUtils::min(inverseScaleX, inverseScaleY) * ROUND_CAP_THRESH;
+            float threshold = std::min(inverseScaleX, inverseScaleY) * ROUND_CAP_THRESH;
             return MathUtils::divisionsNeededToApproximateArc(halfStrokeWidth, PI, threshold);
         }
         return 0;
diff --git a/libs/hwui/PathTessellator.h b/libs/hwui/PathTessellator.h
index b66e832..cddfb04 100644
--- a/libs/hwui/PathTessellator.h
+++ b/libs/hwui/PathTessellator.h
@@ -22,8 +22,12 @@
 #include "Vertex.h"
 #include "VertexBuffer.h"
 
+#include <algorithm>
 #include <vector>
 
+class SkPath;
+class SkPaint;
+
 namespace android {
 namespace uirenderer {
 
@@ -38,7 +42,7 @@
         : thresholdSquared(pixelThreshold * pixelThreshold)
         , sqrInvScaleX(invScaleX * invScaleX)
         , sqrInvScaleY(invScaleY * invScaleY)
-        , thresholdForConicQuads(pixelThreshold * MathUtils::min(invScaleX, invScaleY) / 2.0f) {
+        , thresholdForConicQuads(pixelThreshold * std::min(invScaleX, invScaleY) / 2.0f) {
     };
 
     const float thresholdSquared;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index af1e4a7..b09c207 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -103,10 +103,10 @@
  * A ProgramDescription must be used in conjunction with a ProgramCache.
  */
 struct ProgramDescription {
-    enum ColorFilterMode {
-        kColorNone = 0,
-        kColorMatrix,
-        kColorBlend
+    enum class ColorFilterMode {
+        None = 0,
+        Matrix,
+        Blend
     };
 
     enum Gradient {
@@ -193,7 +193,7 @@
         bitmapWrapS = GL_CLAMP_TO_EDGE;
         bitmapWrapT = GL_CLAMP_TO_EDGE;
 
-        colorOp = kColorNone;
+        colorOp = ColorFilterMode::None;
         colorMode = SkXfermode::kClear_Mode;
 
         framebufferMode = SkXfermode::kClear_Mode;
@@ -249,14 +249,14 @@
             key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
         }
         switch (colorOp) {
-            case kColorMatrix:
+            case ColorFilterMode::Matrix:
                 key |= PROGRAM_KEY_COLOR_MATRIX;
                 break;
-            case kColorBlend:
+            case ColorFilterMode::Blend:
                 key |= PROGRAM_KEY_COLOR_BLEND;
                 key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
                 break;
-            case kColorNone:
+            case ColorFilterMode::None:
                 break;
         }
         key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 7f16deb..b25a4ac 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -38,7 +38,8 @@
 // Vertex shaders snippets
 ///////////////////////////////////////////////////////////////////////////////
 
-const char* gVS_Header_Attributes =
+const char* gVS_Header_Start =
+        "#version 100\n"
         "attribute vec4 position;\n";
 const char* gVS_Header_Attributes_TexCoords =
         "attribute vec2 texCoords;\n";
@@ -132,6 +133,8 @@
 // Fragment shaders snippets
 ///////////////////////////////////////////////////////////////////////////////
 
+const char* gFS_Header_Start =
+        "#version 100\n";
 const char* gFS_Header_Extension_FramebufferFetch =
         "#extension GL_NV_shader_framebuffer_fetch : enable\n\n";
 const char* gFS_Header_Extension_ExternalTexture =
@@ -457,7 +460,7 @@
 
 String8 ProgramCache::generateVertexShader(const ProgramDescription& description) {
     // Add attributes
-    String8 shader(gVS_Header_Attributes);
+    String8 shader(gVS_Header_Start);
     if (description.hasTexture || description.hasExternalTexture) {
         shader.append(gVS_Header_Attributes_TexCoords);
     }
@@ -543,7 +546,7 @@
 }
 
 String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) {
-    String8 shader;
+    String8 shader(gFS_Header_Start);
 
     const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode;
     if (blendFramebuffer) {
@@ -604,7 +607,7 @@
     if (!description.hasVertexAlpha
             && !blendFramebuffer
             && !description.hasColors
-            && description.colorOp == ProgramDescription::kColorNone
+            && description.colorOp == ProgramDescription::ColorFilterMode::None
             && !description.hasDebugHighlight
             && !description.hasRoundRectClip) {
         bool fast = false;
@@ -668,13 +671,13 @@
     if (description.hasBitmap) {
         shader.append(gFS_Uniforms_BitmapSampler);
     }
-    shader.append(gFS_Uniforms_ColorOp[description.colorOp]);
+    shader.append(gFS_Uniforms_ColorOp[static_cast<int>(description.colorOp)]);
 
     // Generate required functions
     if (description.hasGradient && description.hasBitmap) {
         generateBlend(shader, "blendShaders", description.shadersMode);
     }
-    if (description.colorOp == ProgramDescription::kColorBlend) {
+    if (description.colorOp == ProgramDescription::ColorFilterMode::Blend) {
         generateBlend(shader, "blendColors", description.colorMode);
     }
     if (blendFramebuffer) {
@@ -737,7 +740,7 @@
         }
 
         // Apply the color op if needed
-        shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
+        shader.append(gFS_Main_ApplyColorOp[static_cast<int>(description.colorOp)]);
 
         if (description.hasVertexAlpha) {
             if (description.useShadowAlphaInterp) {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 48da3e8..7d09c0b 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -532,7 +532,7 @@
     if (properties().getProjectBackwards()) {
         // composited projectee, flag for out of order draw, save matrix, and store in proj surface
         opState->mSkipInOrderDraw = true;
-        opState->mTransformFromCompositingAncestor.load(localTransformFromProjectionSurface);
+        opState->mTransformFromCompositingAncestor = localTransformFromProjectionSurface;
         compositedChildrenOfProjectionSurface->push_back(opState);
     } else {
         // standard in order draw
@@ -710,8 +710,8 @@
         OpenGLRenderer& renderer, T& handler) {
     const int size = zTranslatedNodes.size();
     if (size == 0
-            || (mode == kNegativeZChildren && zTranslatedNodes[0].key > 0.0f)
-            || (mode == kPositiveZChildren && zTranslatedNodes[size - 1].key < 0.0f)) {
+            || (mode == ChildrenSelectMode::NegativeZChildren && zTranslatedNodes[0].key > 0.0f)
+            || (mode == ChildrenSelectMode::PositiveZChildren && zTranslatedNodes[size - 1].key < 0.0f)) {
         // no 3d children to draw
         return;
     }
@@ -719,7 +719,7 @@
     // Apply the base transform of the parent of the 3d children. This isolates
     // 3d children of the current chunk from transformations made in previous chunks.
     int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag);
-    renderer.setMatrix(initialTransform);
+    renderer.setGlobalMatrix(initialTransform);
 
     /**
      * Draw shadows and (potential) casters mostly in order, but allow the shadows of casters
@@ -730,7 +730,7 @@
      */
     const size_t nonNegativeIndex = findNonNegativeIndex(zTranslatedNodes);
     size_t drawIndex, shadowIndex, endIndex;
-    if (mode == kNegativeZChildren) {
+    if (mode == ChildrenSelectMode::NegativeZChildren) {
         drawIndex = 0;
         endIndex = nonNegativeIndex;
         shadowIndex = endIndex; // draw no shadows
@@ -875,7 +875,7 @@
         renderer.setBaseTransform(initialTransform);
 
         if (drawLayer) {
-            handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
+            handler(new (alloc) DrawLayerOp(mLayer),
                     renderer.getSaveCount() - 1, properties().getClipToBounds());
         } else {
             const int saveCountOffset = renderer.getSaveCount() - 1;
@@ -886,7 +886,7 @@
                 std::vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
                 buildZSortedChildList(chunk, zTranslatedNodes);
 
-                issueOperationsOf3dChildren(kNegativeZChildren,
+                issueOperationsOf3dChildren(ChildrenSelectMode::NegativeZChildren,
                         initialTransform, zTranslatedNodes, renderer, handler);
 
 
@@ -903,7 +903,7 @@
                     }
                 }
 
-                issueOperationsOf3dChildren(kPositiveZChildren,
+                issueOperationsOf3dChildren(ChildrenSelectMode::PositiveZChildren,
                         initialTransform, zTranslatedNodes, renderer, handler);
             }
         }
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 6d1a2b7..3bff2b3 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -184,9 +184,9 @@
         return nodes.size();
     }
 
-    enum ChildrenSelectMode {
-        kNegativeZChildren,
-        kPositiveZChildren
+    enum class ChildrenSelectMode {
+        NegativeZChildren,
+        PositiveZChildren
     };
 
     void computeOrderingImpl(DrawRenderNodeOp* opState,
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index c122d99..36633b5 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -74,7 +74,6 @@
 
     virtual void getMatrix(SkMatrix* outMatrix) const override;
     virtual void setMatrix(const SkMatrix& matrix) override;
-    virtual void setLocalMatrix(const SkMatrix& matrix) override { this->setMatrix(matrix); }
     virtual void concat(const SkMatrix& matrix) override;
     virtual void rotate(float degrees) override;
     virtual void scale(float sx, float sy) override;
@@ -702,7 +701,7 @@
     SkPaint paintCopy(paint);
     paintCopy.setTextAlign(SkPaint::kLeft_Align);
 
-    SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+    static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
     mCanvas->drawPosText(text, count << 1, reinterpret_cast<const SkPoint*>(positions), paintCopy);
 }
 
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 5e6d774..c3f5eb2 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -45,7 +45,7 @@
     }
 
     // convert the SkPoints into floats
-    SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+    static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
     const size_t floatCount = count << 1;
     const float* floatArray = &pts[0].fX;
 
@@ -142,7 +142,7 @@
         const SkPaint* paint) {
     // TODO: if bitmap is a subset, do we need to add pixelRefOrigin to src?
     mCanvas->save(SkCanvas::kMatrixClip_SaveFlag);
-    mCanvas->setLocalMatrix(SkMatrix::I());
+    mCanvas->setMatrix(SkMatrix::I());
     mCanvas->drawBitmap(bitmap, left, top, paint);
     mCanvas->restore();
 }
@@ -154,7 +154,7 @@
         return;
     }
     // convert the SkPoints into floats
-    SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+    static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
     const int floatCount = vertexCount << 1;
     const float* vArray = &vertices[0].fX;
     const float* tArray = (texs) ? &texs[0].fX : NULL;
@@ -192,9 +192,7 @@
 }
 
 void SkiaCanvasProxy::didSetMatrix(const SkMatrix& matrix) {
-    // SkCanvas setMatrix() is relative to the Canvas origin, but OpenGLRenderer's
-    // setMatrix() is relative to device origin; call setLocalMatrix() instead.
-    mCanvas->setLocalMatrix(matrix);
+    mCanvas->setMatrix(matrix);
 }
 
 void SkiaCanvasProxy::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
@@ -286,7 +284,7 @@
         }
     }
 
-    SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+    static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
     mCanvas->drawText(glyphs.glyphIDs, &pointStorage[0].fX, glyphs.count, glyphs.paint,
                       x, y, bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
 }
@@ -322,7 +320,7 @@
     glyphs.paint.measureText(glyphs.glyphIDs, glyphs.count << 1, &bounds);
     bounds.offset(x, y);
 
-    SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
+    static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
     mCanvas->drawText(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y,
                       bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
 }
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 1f95946..6c105cf 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -32,12 +32,19 @@
 // Support
 ///////////////////////////////////////////////////////////////////////////////
 
-static const GLenum gTileModes[] = {
+static constexpr GLenum gTileModes[] = {
         GL_CLAMP_TO_EDGE,   // == SkShader::kClamp_TileMode
         GL_REPEAT,          // == SkShader::kRepeat_Mode
         GL_MIRRORED_REPEAT  // == SkShader::kMirror_TileMode
 };
 
+static_assert(gTileModes[SkShader::kClamp_TileMode] == GL_CLAMP_TO_EDGE,
+        "SkShader TileModes have changed");
+static_assert(gTileModes[SkShader::kRepeat_TileMode] == GL_REPEAT,
+        "SkShader TileModes have changed");
+static_assert(gTileModes[SkShader::kMirror_TileMode] == GL_MIRRORED_REPEAT,
+        "SkShader TileModes have changed");
+
 /**
  * This function does not work for n == 0.
  */
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index fd077d9..4d60b8d 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -58,7 +58,7 @@
         , mViewportData(s->mViewportData)
         , mRelativeLightCenter(s->mRelativeLightCenter) {
     if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
-        mTransformRoot.load(*s->transform);
+        mTransformRoot = *s->transform;
         transform = &mTransformRoot;
     } else {
         transform = s->transform;
@@ -83,24 +83,24 @@
 // Clipping
 ///////////////////////////////////////////////////////////////////////////////
 
-bool Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
+void Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
     flags |= Snapshot::kFlagClipSet;
-    return mClipArea->clipRegion(region, op);
+    mClipArea->clipRegion(region, op);
 }
 
-bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
+void Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
     flags |= Snapshot::kFlagClipSet;
-    return mClipArea->clipRectWithTransform(left, top, right, bottom, transform, op);
+    mClipArea->clipRectWithTransform(left, top, right, bottom, transform, op);
 }
 
-bool Snapshot::clipPath(const SkPath& path, SkRegion::Op op) {
+void Snapshot::clipPath(const SkPath& path, SkRegion::Op op) {
     flags |= Snapshot::kFlagClipSet;
-    return mClipArea->clipPathWithTransform(path, transform, op);
+    mClipArea->clipPathWithTransform(path, transform, op);
 }
 
 void Snapshot::setClip(float left, float top, float right, float bottom) {
-    mClipArea->setClip(left, top, right, bottom);
     flags |= Snapshot::kFlagClipSet;
+    mClipArea->setClip(left, top, right, bottom);
 }
 
 bool Snapshot::hasPerspectiveTransform() const {
@@ -190,8 +190,7 @@
     state->highPriority = highPriority;
 
     // store the inverse drawing matrix
-    Matrix4 roundRectDrawingMatrix;
-    roundRectDrawingMatrix.load(getOrthoMatrix());
+    Matrix4 roundRectDrawingMatrix = getOrthoMatrix();
     roundRectDrawingMatrix.multiply(*transform);
     state->matrix.loadInverse(roundRectDrawingMatrix);
 
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index af6ad72..cf8f11c 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -124,26 +124,25 @@
      * the specified operation. The specified rectangle is transformed
      * by this snapshot's trasnformation.
      */
-    bool clip(float left, float top, float right, float bottom,
-            SkRegion::Op op = SkRegion::kIntersect_Op);
+    void clip(float left, float top, float right, float bottom, SkRegion::Op op);
 
     /**
      * Modifies the current clip with the new clip rectangle and
      * the specified operation. The specified rectangle is considered
      * already transformed.
      */
-    bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op);
+    void clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op);
 
     /**
      * Modifies the current clip with the specified region and operation.
      * The specified region is considered already transformed.
      */
-    bool clipRegionTransformed(const SkRegion& region, SkRegion::Op op);
+    void clipRegionTransformed(const SkRegion& region, SkRegion::Op op);
 
     /**
      * Modifies the current clip with the specified path and operation.
      */
-    bool clipPath(const SkPath& path, SkRegion::Op op);
+    void clipPath(const SkPath& path, SkRegion::Op op);
 
     /**
      * Sets the current clip.
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index eaf0303..9b0a1aa 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -46,17 +46,18 @@
 #define TRANSFORMED_PENUMBRA_ALPHA 1.0f
 #define TRANSFORMED_UMBRA_ALPHA 0.0f
 
+#include "SpotShadow.h"
+
+#include "ShadowTessellator.h"
+#include "Vertex.h"
+#include "VertexBuffer.h"
+#include "utils/MathUtils.h"
+
 #include <algorithm>
 #include <math.h>
 #include <stdlib.h>
 #include <utils/Log.h>
 
-#include "ShadowTessellator.h"
-#include "SpotShadow.h"
-#include "Vertex.h"
-#include "VertexBuffer.h"
-#include "utils/MathUtils.h"
-
 // TODO: After we settle down the new algorithm, we can remove the old one and
 // its utility functions.
 // Right now, we still need to keep it for comparison purpose and future expansion.
@@ -543,7 +544,7 @@
         }
 
         float ratioVI = outlineData[i].radius / distOutline;
-        minRaitoVI = MathUtils::min(minRaitoVI, ratioVI);
+        minRaitoVI = std::min(minRaitoVI, ratioVI);
         if (ratioVI >= (1 - FAKE_UMBRA_SIZE_RATIO)) {
             ratioVI = (1 - FAKE_UMBRA_SIZE_RATIO);
         }
diff --git a/libs/hwui/VertexBuffer.h b/libs/hwui/VertexBuffer.h
index 9be4d84..c0373ac 100644
--- a/libs/hwui/VertexBuffer.h
+++ b/libs/hwui/VertexBuffer.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_HWUI_VERTEX_BUFFER_H
 #define ANDROID_HWUI_VERTEX_BUFFER_H
 
-#include "utils/MathUtils.h"
+#include <algorithm>
 
 namespace android {
 namespace uirenderer {
@@ -129,10 +129,10 @@
     unsigned int getSize() const { return mByteCount; }
     unsigned int getIndexCount() const { return mIndexCount; }
     void updateIndexCount(unsigned int newCount)  {
-        mIndexCount = MathUtils::min(newCount, mAllocatedIndexCount);
+        mIndexCount = std::min(newCount, mAllocatedIndexCount);
     }
     void updateVertexCount(unsigned int newCount)  {
-        mVertexCount = MathUtils::min(newCount, mAllocatedVertexCount);
+        mVertexCount = std::min(newCount, mAllocatedVertexCount);
     }
     MeshFeatureFlags getMeshFeatureFlags() const { return mMeshFeatureFlags; }
     void setMeshFeatureFlags(int flags) {
diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp
index 29927ed..b21e15e 100644
--- a/libs/hwui/renderstate/Blend.cpp
+++ b/libs/hwui/renderstate/Blend.cpp
@@ -30,6 +30,26 @@
     GLenum dst;
 };
 
+// assumptions made by lookup tables in either this file or ProgramCache
+static_assert(0 == SkXfermode::kClear_Mode, "SkXfermode enums have changed");
+static_assert(1 == SkXfermode::kSrc_Mode, "SkXfermode enums have changed");
+static_assert(2 == SkXfermode::kDst_Mode, "SkXfermode enums have changed");
+static_assert(3 == SkXfermode::kSrcOver_Mode, "SkXfermode enums have changed");
+static_assert(4 == SkXfermode::kDstOver_Mode, "SkXfermode enums have changed");
+static_assert(5 == SkXfermode::kSrcIn_Mode, "SkXfermode enums have changed");
+static_assert(6 == SkXfermode::kDstIn_Mode, "SkXfermode enums have changed");
+static_assert(7 == SkXfermode::kSrcOut_Mode, "SkXfermode enums have changed");
+static_assert(8 == SkXfermode::kDstOut_Mode, "SkXfermode enums have changed");
+static_assert(9 == SkXfermode::kSrcATop_Mode, "SkXfermode enums have changed");
+static_assert(10 == SkXfermode::kDstATop_Mode, "SkXfermode enums have changed");
+static_assert(11 == SkXfermode::kXor_Mode, "SkXfermode enums have changed");
+static_assert(12 == SkXfermode::kPlus_Mode, "SkXfermode enums have changed");
+static_assert(13 == SkXfermode::kModulate_Mode, "SkXfermode enums have changed");
+static_assert(14 == SkXfermode::kScreen_Mode, "SkXfermode enums have changed");
+static_assert(15 == SkXfermode::kOverlay_Mode, "SkXfermode enums have changed");
+static_assert(16 == SkXfermode::kDarken_Mode, "SkXfermode enums have changed");
+static_assert(17 == SkXfermode::kLighten_Mode, "SkXfermode enums have changed");
+
 // In this array, the index of each Blender equals the value of the first
 // entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
 const Blender kBlends[] = {
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 1e39bfa..c5126de 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -19,6 +19,8 @@
 #include "renderthread/EglManager.h"
 #include "utils/GLUtils.h"
 
+#include <algorithm>
+
 namespace android {
 namespace uirenderer {
 
@@ -227,11 +229,11 @@
             glop.transform.transformFlags & TransformFlags::OffsetByFudgeFactor);
 
     // Color filter uniforms
-    if (fill.filterMode == ProgramDescription::kColorBlend) {
+    if (fill.filterMode == ProgramDescription::ColorFilterMode::Blend) {
         const FloatColor& color = fill.filter.color;
         glUniform4f(mCaches->program().getUniform("colorBlend"),
                 color.r, color.g, color.b, color.a);
-    } else if (fill.filterMode == ProgramDescription::kColorMatrix) {
+    } else if (fill.filterMode == ProgramDescription::ColorFilterMode::Matrix) {
         glUniformMatrix4fv(mCaches->program().getUniform("colorMatrix"), 1, GL_FALSE,
                 fill.filter.matrix.matrix);
         glUniform4fv(mCaches->program().getUniform("colorMatrixVector"), 1,
@@ -320,7 +322,7 @@
         GLsizei elementsCount = mesh.elementCount;
         const GLbyte* vertexData = static_cast<const GLbyte*>(vertices.position);
         while (elementsCount > 0) {
-            GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
+            GLsizei drawCount = std::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
 
             // rebind pointers without forcing, since initial bind handled above
             meshState().bindPositionVertexPointer(false, vertexData, vertices.stride);
diff --git a/libs/hwui/renderstate/Stencil.cpp b/libs/hwui/renderstate/Stencil.cpp
index 319cfe4..d25ad51 100644
--- a/libs/hwui/renderstate/Stencil.cpp
+++ b/libs/hwui/renderstate/Stencil.cpp
@@ -34,10 +34,6 @@
 #define STENCIL_MASK_VALUE 0x1
 #endif
 
-Stencil::Stencil()
-        : mState(kDisabled) {
-}
-
 uint8_t Stencil::getStencilSize() {
     return STENCIL_BUFFER_SIZE;
 }
@@ -64,14 +60,14 @@
     glClearStencil(0);
     glClear(GL_STENCIL_BUFFER_BIT);
 
-    if (mState == kTest) {
+    if (mState == StencilState::Test) {
         // reset to test state, with immutable stencil
         glStencilMask(0);
     }
 }
 
 void Stencil::enableTest(int incrementThreshold) {
-    if (mState != kTest) {
+    if (mState != StencilState::Test) {
         enable();
         if (incrementThreshold > 0) {
             glStencilFunc(GL_EQUAL, incrementThreshold, 0xff);
@@ -82,12 +78,12 @@
         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
         glStencilMask(0);
-        mState = kTest;
+        mState = StencilState::Test;
     }
 }
 
 void Stencil::enableWrite(int incrementThreshold) {
-    if (mState != kWrite) {
+    if (mState != StencilState::Write) {
         enable();
         if (incrementThreshold > 0) {
             glStencilFunc(GL_ALWAYS, 1, 0xff);
@@ -100,7 +96,7 @@
         }
         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
         glStencilMask(0xff);
-        mState = kWrite;
+        mState = StencilState::Write;
     }
 }
 
@@ -109,7 +105,7 @@
     glStencilFunc(greater ? GL_LESS : GL_EQUAL, value, 0xffffffff);
     // We only want to test, let's keep everything
     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-    mState = kTest;
+    mState = StencilState::Test;
     glStencilMask(0);
 }
 
@@ -119,20 +115,20 @@
     // The test always passes so the first two values are meaningless
     glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-    mState = kWrite;
+    mState = StencilState::Write;
     glStencilMask(0xff);
 }
 
 void Stencil::enable() {
-    if (mState == kDisabled) {
+    if (mState == StencilState::Disabled) {
         glEnable(GL_STENCIL_TEST);
     }
 }
 
 void Stencil::disable() {
-    if (mState != kDisabled) {
+    if (mState != StencilState::Disabled) {
         glDisable(GL_STENCIL_TEST);
-        mState = kDisabled;
+        mState = StencilState::Disabled;
     }
 }
 
diff --git a/libs/hwui/renderstate/Stencil.h b/libs/hwui/renderstate/Stencil.h
index 3261823..5f7d405 100644
--- a/libs/hwui/renderstate/Stencil.h
+++ b/libs/hwui/renderstate/Stencil.h
@@ -30,8 +30,6 @@
 
 class ANDROID_API Stencil {
 public:
-    Stencil();
-
     /**
      * Returns the desired size for the stencil buffer. If the returned value
      * is 0, then no stencil buffer is required.
@@ -81,32 +79,31 @@
      * Indicates whether either test or write is enabled.
      */
     bool isEnabled() {
-        return mState != kDisabled;
+        return mState != StencilState::Disabled;
     }
 
     /**
      * Indicates whether testing only is enabled.
      */
     bool isTestEnabled() {
-        return mState == kTest;
+        return mState == StencilState::Test;
     }
 
     bool isWriteEnabled() {
-        return mState == kWrite;
+        return mState == StencilState::Write;
     }
 
     void dump();
 
 private:
-    void enable();
-
-    enum StencilState {
-        kDisabled,
-        kTest,
-        kWrite
+    enum class StencilState {
+        Disabled,
+        Test,
+        Write
     };
 
-    StencilState mState;
+    void enable();
+    StencilState mState = StencilState::Disabled;
 
 }; // class Stencil
 
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 67c42f3..7cb7738 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -421,7 +421,7 @@
         // Make sure to release all the textures we were owning as there won't
         // be another draw
         caches.textureCache.resetMarkInUse(this);
-        caches.flush(Caches::kFlushMode_Layers);
+        caches.flush(Caches::FlushMode::Layers);
     }
 }
 
@@ -431,10 +431,10 @@
 
     ATRACE_CALL();
     if (level >= TRIM_MEMORY_COMPLETE) {
-        Caches::getInstance().flush(Caches::kFlushMode_Full);
+        Caches::getInstance().flush(Caches::FlushMode::Full);
         thread.eglManager().destroy();
     } else if (level >= TRIM_MEMORY_UI_HIDDEN) {
-        Caches::getInstance().flush(Caches::kFlushMode_Moderate);
+        Caches::getInstance().flush(Caches::FlushMode::Moderate);
     }
 }
 
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 9c3787c..8d20f21 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -16,6 +16,7 @@
 #ifndef MATHUTILS_H
 #define MATHUTILS_H
 
+#include <algorithm>
 #include <math.h>
 
 namespace android {
@@ -82,18 +83,8 @@
     }
 
     template<typename T>
-    static inline T max(T a, T b) {
-        return a > b ? a : b;
-    }
-
-    template<typename T>
-    static inline T min(T a, T b) {
-        return a < b ? a : b;
-    }
-
-    template<typename T>
     static inline T clamp(T a, T minValue, T maxValue) {
-        return min(max(a, minValue), maxValue);
+        return std::min(std::max(a, minValue), maxValue);
     }
 
     inline static float lerp(float v1, float v2, float t) {
diff --git a/media/java/android/mtp/MtpObjectInfo.java b/media/java/android/mtp/MtpObjectInfo.java
index d2824b5..f79d52e 100644
--- a/media/java/android/mtp/MtpObjectInfo.java
+++ b/media/java/android/mtp/MtpObjectInfo.java
@@ -256,7 +256,7 @@
     /**
      * Builds a new object info instance.
      */
-    public class Builder {
+    public static class Builder {
         private MtpObjectInfo mObjectInfo;
 
         public Builder() {
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index ad804f3..9dd3861 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -430,12 +430,14 @@
 android_mtp_MtpDevice_send_object_info(JNIEnv *env, jobject thiz, jobject info)
 {
     MtpDevice* device = get_device_from_object(env, thiz);
-    if (!device)
+    if (!device) {
         return JNI_FALSE;
+    }
 
     // Updating existing objects is not supported.
-    if (env->GetIntField(info, field_objectInfo_handle) != -1)
+    if (env->GetIntField(info, field_objectInfo_handle) != -1) {
         return JNI_FALSE;
+    }
 
     MtpObjectInfo* object_info = new MtpObjectInfo(-1);
     object_info->mStorageID = env->GetIntField(info, field_objectInfo_storageId);
@@ -456,17 +458,21 @@
     object_info->mSequenceNumber = env->GetIntField(info, field_objectInfo_sequenceNumber);
 
     jstring name_jstring = (jstring) env->GetObjectField(info, field_objectInfo_name);
-    const char* name_string = env->GetStringUTFChars(name_jstring, NULL);
-    object_info->mName = strdup(name_string);
-    env->ReleaseStringUTFChars(name_jstring, name_string);
+    if (name_jstring != NULL) {
+        const char* name_string = env->GetStringUTFChars(name_jstring, NULL);
+        object_info->mName = strdup(name_string);
+        env->ReleaseStringUTFChars(name_jstring, name_string);
+    }
 
     object_info->mDateCreated = env->GetLongField(info, field_objectInfo_dateCreated) / 1000LL;
     object_info->mDateModified = env->GetLongField(info, field_objectInfo_dateModified) / 1000LL;
 
     jstring keywords_jstring = (jstring) env->GetObjectField(info, field_objectInfo_keywords);
-    const char* keywords_string = env->GetStringUTFChars(keywords_jstring, NULL);
-    object_info->mKeywords = strdup(keywords_string);
-    env->ReleaseStringUTFChars(keywords_jstring, keywords_string);
+    if (keywords_jstring != NULL) {
+        const char* keywords_string = env->GetStringUTFChars(keywords_jstring, NULL);
+        object_info->mKeywords = strdup(keywords_string);
+        env->ReleaseStringUTFChars(keywords_jstring, keywords_string);
+    }
 
     int object_handle = device->sendObjectInfo(object_info);
     if (object_handle == -1) {
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index 1001e10..71e618b 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.documentsui.GridItem xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="@dimen/grid_item_height"
     android:layout_margin="@dimen/grid_item_margin"
@@ -140,4 +140,4 @@
         android:contentDescription="@null"
         android:duplicateParentState="true" />
 
-</FrameLayout>
+</com.android.documentsui.GridItem>
diff --git a/packages/DocumentsUI/res/layout/item_loading_grid.xml b/packages/DocumentsUI/res/layout/item_loading_grid.xml
index 005a111..147dfd4 100644
--- a/packages/DocumentsUI/res/layout/item_loading_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_loading_grid.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.documentsui.GridItem xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="@dimen/grid_height"
     android:orientation="horizontal">
@@ -26,4 +26,4 @@
         android:indeterminate="true"
         style="?android:attr/progressBarStyle" />
 
-</FrameLayout>
+</com.android.documentsui.GridItem>
diff --git a/packages/DocumentsUI/res/layout/item_message_grid.xml b/packages/DocumentsUI/res/layout/item_message_grid.xml
index 385563d..45d61a5 100644
--- a/packages/DocumentsUI/res/layout/item_message_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_message_grid.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.documentsui.GridItem xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="@dimen/grid_height"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
@@ -48,4 +48,4 @@
 
     </LinearLayout>
 
-</FrameLayout>
+</com.android.documentsui.GridItem>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BandSelectMatrix.java b/packages/DocumentsUI/src/com/android/documentsui/BandSelectMatrix.java
new file mode 100644
index 0000000..f259059
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/BandSelectMatrix.java
@@ -0,0 +1,645 @@
+/*
+ * 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.
+ */
+
+package com.android.documentsui;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.base.Preconditions;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.LayoutManager;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
+import android.util.SparseBooleanArray;
+import android.view.View;
+
+/**
+ * Provides a band selection item model for views within a RecyclerView. This class queries the
+ * RecyclerView to determine where its items are placed; then, once band selection is underway, it
+ * alerts listeners of which items are covered by the selections.
+ */
+public final class BandSelectMatrix extends RecyclerView.OnScrollListener {
+
+    private final RecyclerViewHelper mHelper;
+    private final List<OnSelectionChangedListener> mOnSelectionChangedListeners = new ArrayList<>();
+
+    // Map from the x-value of the left side of an item to an ordered list of metadata of all items
+    // whose x-values are the same. The list is ordered by the y-values of the items in the column.
+    // For example, if the first column of the view starts at an x-value of 5, mColumns.get(5) would
+    // return a list of all items in that column, with the top-most item first in the list and the
+    // bottom-most item last in the list.
+    private final Map<Integer, List<ItemData>> mColumns = new HashMap<>();
+
+    // List of limits along the x-axis. For example, if the view has two columns, this list will
+    // have two elements, each of which lists the lower- and upper-limits of the x-values of the
+    // view items. This list is sorted from furthest left to furthest right.
+    private final List<Limits> mXLimitsList = new ArrayList<>();
+
+    // Like mXLimitsList, but for y-coordinates. Note that this list only contains items which have
+    // been in the viewport. Thus, limits which exist in an area of the view to which the view has
+    // not scrolled are not present in the list.
+    private final List<Limits> mYLimitsList = new ArrayList<>();
+
+    // The adapter positions which have been recorded so far.
+    private final SparseBooleanArray mRecordedPositions = new SparseBooleanArray();
+
+    // Array passed to registered OnSelectionChangedListeners. One array is created and reused
+    // throughout the lifetime of the object.
+    private final SparseBooleanArray mSelectionForListeners = new SparseBooleanArray();
+
+    // The current pointer (in absolute positioning from the top of the view).
+    private Point mPointer = null;
+
+    // The bounds of the band selection.
+    private RelativePoint mRelativeOrigin;
+    private RelativePoint mRelativePointer;
+
+    BandSelectMatrix(RecyclerViewHelper helper) {
+        mHelper = helper;
+        mHelper.addOnScrollListener(this);
+    }
+
+    BandSelectMatrix(RecyclerView rv) {
+        this(new RuntimeRecyclerViewHelper(rv));
+    }
+
+    /**
+     * Stops listening to the view's scrolls. Call this function before discarding a
+     * BandSelecMatrix object to prevent memory leaks.
+     */
+    void stopListening() {
+        mHelper.removeOnScrollListener(this);
+    }
+
+    /**
+     * Start a band select operation at the given point.
+     * @param relativeOrigin The origin of the band select operation, relative to the viewport.
+     *     For example, if the view is scrolled to the bottom, the top-left of the viewport would
+     *     have a relative origin of (0, 0), even though its absolute point has a higher y-value.
+     */
+    void startSelection(Point relativeOrigin) {
+        Point absoluteOrigin = mHelper.createAbsolutePoint(relativeOrigin);
+        mPointer = new Point(absoluteOrigin.x, absoluteOrigin.y);
+
+        processVisibleChildren();
+        mRelativeOrigin = new RelativePoint(absoluteOrigin);
+        mRelativePointer = new RelativePoint(mPointer);
+        computeCurrentSelection();
+        notifyListeners();
+    }
+
+    /**
+     * Resizes the selection by adjusting the pointer (i.e., the corner of the selection opposite
+     * the origin.
+     * @param relativePointer The pointer (opposite of the origin) of the band select operation,
+     *     relative to the viewport. For example, if the view is scrolled to the bottom, the
+     *     top-left of the viewport would have a relative origin of (0, 0), even though its absolute
+     *     point has a higher y-value.
+     */
+    void resizeSelection(Point relativePointer) {
+        mPointer = mHelper.createAbsolutePoint(relativePointer);
+        handlePointerMoved();
+    }
+
+    @Override
+    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+        if (mPointer == null) {
+            return;
+        }
+
+        mPointer.x += dx;
+        mPointer.y += dy;
+        processVisibleChildren();
+        handlePointerMoved();
+    }
+
+    /**
+     * Queries the view for all children and records their location metadata.
+     */
+    private void processVisibleChildren() {
+        for (int i = 0; i < mHelper.getVisibleChildCount(); i++) {
+            int adapterPosition = mHelper.getAdapterPositionAt(i);
+            if (!mRecordedPositions.get(adapterPosition)) {
+                mRecordedPositions.put(adapterPosition, true);
+                captureItemLayoutData(mHelper.getAbsoluteRectForChildViewAt(i), adapterPosition);
+            }
+        }
+    }
+
+    /**
+     * Updates the limits lists and column map with the given item metadata.
+     * @param absoluteChildRect The absolute rectangle for the child view being processed.
+     * @param adapterPosition The position of the child view being processed.
+     */
+    private void captureItemLayoutData(Rect absoluteChildRect, int adapterPosition) {
+        if (mXLimitsList.size() != mHelper.getNumColumns()) {
+            // If not all x-limits have been recorded, record this one.
+            recordLimits(
+                    mXLimitsList, new Limits(absoluteChildRect.left, absoluteChildRect.right));
+        }
+
+        if (mYLimitsList.size() != mHelper.getNumRows()) {
+            // If not all y-limits have been recorded, record this one.
+            recordLimits(
+                    mYLimitsList, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
+        }
+
+        List<ItemData> columnList = mColumns.get(absoluteChildRect.left);
+        if (columnList == null) {
+            columnList = new ArrayList<ItemData>();
+            mColumns.put(absoluteChildRect.left, columnList);
+        }
+        recordItemData(
+                columnList, new ItemData(adapterPosition, absoluteChildRect.top));
+    }
+
+    /**
+     * Ensures limits exists within the sorted list limitsList, and adds it to the list if it does
+     * not exist.
+     */
+    private static void recordLimits(List<Limits> limitsList, Limits limits) {
+        int index = Collections.binarySearch(limitsList, limits);
+        if (index < 0) {
+            limitsList.add(~index, limits);
+        }
+    }
+
+    /**
+     * Ensures itemData exists within the sorted list itemDataList, and adds it to the list if it
+     * does not exist.
+     */
+    private static void recordItemData(List<ItemData> itemDataList, ItemData itemData) {
+        int index = Collections.binarySearch(itemDataList, itemData);
+        if (index < 0) {
+            itemDataList.add(~index, itemData);
+        }
+    }
+
+    /**
+     * Handles a moved pointer; this function determines whether the pointer movement resulted in a
+     * selection change and, if it has, notifies listeners of this change.
+     */
+    private void handlePointerMoved() {
+        RelativePoint old = mRelativePointer;
+        mRelativePointer = new RelativePoint(mPointer);
+        if (old != null && mRelativePointer.equals(old)) {
+            return;
+        }
+
+        computeCurrentSelection();
+        notifyListeners();
+    }
+
+    /**
+     * Computes the currently-selected items.
+     */
+    private void computeCurrentSelection() {
+        Rect selectionRect = mRelativePointer.computeBounds(mRelativeOrigin);
+        computePositionsCoveredByRect(selectionRect);
+    }
+
+    /**
+     * Notifies all listeners of a selection change. Note that this function simply passes
+     * mSelectionForListeners, so computeCurrentSelection() should be called before this function.
+     */
+    private void notifyListeners() {
+        for (OnSelectionChangedListener listener : mOnSelectionChangedListeners) {
+            listener.onSelectionChanged(mSelectionForListeners);
+        }
+    }
+
+    /**
+     * @param rect Rectangle including all covered items.
+     */
+    private void computePositionsCoveredByRect(@Nullable Rect rect) {
+        mSelectionForListeners.clear();
+        if (rect == null) {
+            // If there is no bounding rectangle, there are no items selected, so just return early.
+            return;
+        }
+
+        int columnIndex = Collections.binarySearch(mXLimitsList, new Limits(rect.left, rect.left));
+        Preconditions.checkState(columnIndex >= 0);
+
+        for (; columnIndex < mXLimitsList.size() &&
+                mXLimitsList.get(columnIndex).lowerLimit <= rect.right; columnIndex++) {
+            List<ItemData> positions =
+                    mColumns.get(mXLimitsList.get(columnIndex).lowerLimit);
+            int rowIndex = Collections.binarySearch(positions, new ItemData(0, rect.top));
+            if (rowIndex < 0) {
+                // If band select occurs after the last item in a row with fewer items than columns,
+                // go to the next column. This situation occurs in the last row of the grid when the
+                // total number of items is not a multiple of the number of columns (e.g., when 10
+                // items exist in a grid with 4 columns).
+                continue;
+            }
+
+            for (; rowIndex < positions.size() &&
+                    positions.get(rowIndex).offset <= rect.bottom; rowIndex++) {
+                mSelectionForListeners.append(positions.get(rowIndex).position, true);
+            }
+        }
+    }
+
+    /**
+     * Provides functionality for interfacing with the view. In practice, RecyclerViewMatrixHelper
+     * should be used; this interface exists solely for the purpose of decoupling the view from
+     * this class so that the view can be mocked out for tests.
+     */
+    interface RecyclerViewHelper {
+        public void addOnScrollListener(RecyclerView.OnScrollListener listener);
+        public void removeOnScrollListener(RecyclerView.OnScrollListener listener);
+        public Point createAbsolutePoint(Point relativePoint);
+        public int getVisibleChildCount();
+        public int getTotalChildCount();
+        public int getNumColumns();
+        public int getNumRows();
+        public int getAdapterPositionAt(int index);
+        public Rect getAbsoluteRectForChildViewAt(int index);
+    }
+
+    /**
+     * Concrete MatrixHelper implementation for use within the Files app.
+     */
+    static class RuntimeRecyclerViewHelper implements RecyclerViewHelper {
+        private final RecyclerView mRecyclerView;
+
+        RuntimeRecyclerViewHelper(RecyclerView rv) {
+            mRecyclerView = rv;
+        }
+
+        @Override
+        public int getAdapterPositionAt(int index) {
+            View child = mRecyclerView.getChildAt(index);
+            return mRecyclerView.getChildViewHolder(child).getAdapterPosition();
+        }
+
+        @Override
+        public void addOnScrollListener(OnScrollListener listener) {
+            mRecyclerView.addOnScrollListener(listener);
+        }
+
+        @Override
+        public void removeOnScrollListener(OnScrollListener listener) {
+            mRecyclerView.removeOnScrollListener(listener);
+        }
+
+        @Override
+        public Point createAbsolutePoint(Point relativePoint) {
+            return new Point(relativePoint.x + mRecyclerView.computeHorizontalScrollOffset(),
+                    relativePoint.y + mRecyclerView.computeVerticalScrollOffset());
+        }
+
+        @Override
+        public Rect getAbsoluteRectForChildViewAt(int index) {
+            final View child = mRecyclerView.getChildAt(index);
+            final Rect childRect = new Rect();
+            child.getHitRect(childRect);
+            childRect.left += mRecyclerView.computeHorizontalScrollOffset();
+            childRect.right += mRecyclerView.computeHorizontalScrollOffset();
+            childRect.top += mRecyclerView.computeVerticalScrollOffset();
+            childRect.bottom += mRecyclerView.computeVerticalScrollOffset();
+            return childRect;
+        }
+
+        @Override
+        public int getVisibleChildCount() {
+            return mRecyclerView.getChildCount();
+        }
+
+        @Override
+        public int getTotalChildCount() {
+            return mRecyclerView.getAdapter().getItemCount();
+        }
+
+        @Override
+        public int getNumColumns() {
+            LayoutManager layoutManager = mRecyclerView.getLayoutManager();
+            if (layoutManager instanceof GridLayoutManager) {
+                return ((GridLayoutManager) layoutManager).getSpanCount();
+            }
+
+            // Otherwise, it is a list with 1 column.
+            return 1;
+        }
+
+        @Override
+        public int getNumRows() {
+            int numFullColumns = getTotalChildCount() / getNumColumns();
+            boolean hasPartiallyFullColumn = getTotalChildCount() % getNumColumns() != 0;
+            return numFullColumns + (hasPartiallyFullColumn ? 1 : 0);
+        }
+    }
+
+    /**
+     * Listener for changes in which items have been band selected.
+     */
+    interface OnSelectionChangedListener {
+        public void onSelectionChanged(SparseBooleanArray updatedSelection);
+    }
+
+    void addOnSelectionChangedListener(OnSelectionChangedListener listener) {
+        mOnSelectionChangedListeners.add(listener);
+    }
+
+    void removeOnSelectionChangedListener(OnSelectionChangedListener listener) {
+        mOnSelectionChangedListeners.remove(listener);
+    }
+
+    /**
+     * Metadata for an item in the view, consisting of the adapter position and the offset from the
+     * top of the view (in pixels). Stored in the mColumns map to model the item grid.
+     */
+    private static class ItemData implements Comparable<ItemData> {
+        int position;
+        int offset;
+
+        ItemData(int position, int offset) {
+            this.position = position;
+            this.offset = offset;
+        }
+
+        @Override
+        public int compareTo(ItemData other) {
+            // The list of columns is sorted via the offset from the top, so PositionMetadata
+            // objects with lower y-values are befor those with higher y-values.
+            return offset - other.offset;
+        }
+    }
+
+    /**
+     * Limits of a view item. For example, if an item's left side is at x-value 5 and its right side
+     * is at x-value 10, the limits would be from 5 to 10. Used to record the left- and right sides
+     * of item columns and the top- and bottom sides of item rows so that it can be determined
+     * whether the pointer is located within the bounds of an item.
+     */
+    private static class Limits implements Comparable<Limits> {
+        int lowerLimit;
+        int upperLimit;
+
+        Limits(int lowerLimit, int upperLimit) {
+            this.lowerLimit = lowerLimit;
+            this.upperLimit = upperLimit;
+        }
+
+        @Override
+        public int compareTo(Limits other) {
+            return lowerLimit - other.lowerLimit;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof Limits)) {
+                return false;
+            }
+
+            return ((Limits) other).lowerLimit == lowerLimit &&
+                    ((Limits) other).upperLimit == upperLimit;
+        }
+    }
+
+    /**
+     * The location of a coordinate relative to items. This class represents a general area of the
+     * view as it relates to band selection rather than an explicit point. For example, two
+     * different points within an item are considered to have the same "location" because band
+     * selection originating within the item would select the same items no matter which point
+     * was used. Same goes for points between items as well as those at the very beginning or end
+     * of the view.
+     *
+     * Tracking a coordinate (e.g., an x-value) as a CoordinateLocation instead of as an int has the
+     * advantage of tying the value to the Limits of items along that axis. This allows easy
+     * selection of items within those Limits as opposed to a search through every item to see if a
+     * given coordinate value falls within those Limits.
+     */
+    private static class RelativeCoordinate
+            implements Comparable<RelativeCoordinate> {
+        /**
+         * Location describing points after the last known item.
+         */
+        static final int AFTER_LAST_ITEM = 0;
+
+        /**
+         * Location describing points before the first known item.
+         */
+        static final int BEFORE_FIRST_ITEM = 1;
+
+        /**
+         * Location describing points between two items.
+         */
+        static final int BETWEEN_TWO_ITEMS = 2;
+
+        /**
+         * Location describing points within the limits of one item.
+         */
+        static final int WITHIN_LIMITS = 3;
+
+        /**
+         * The type of this coordinate, which is one of AFTER_LAST_ITEM, BEFORE_FIRST_ITEM,
+         * BETWEEN_TWO_ITEMS, or WITHIN_LIMITS.
+         */
+        final int type;
+
+        /**
+         * The limits before the coordinate; only populated when type == WITHIN_LIMITS or type ==
+         * BETWEEN_TWO_ITEMS.
+         */
+        Limits limitsBeforeCoordinate;
+
+        /**
+         * The limits after the coordinate; only populated when type == BETWEEN_TWO_ITEMS.
+         */
+        Limits limitsAfterCoordinate;
+
+        // Limits of the first known item; only populated when type == BEFORE_FIRST_ITEM.
+        Limits mFirstKnownItem;
+        // Limits of the last known item; only populated when type == AFTER_LAST_ITEM.
+        Limits mLastKnownItem;
+
+        /**
+         * @param limitsList The sorted limits list for the coordinate type. If this
+         *     CoordinateLocation is an x-value, mXLimitsList should be passed; otherwise,
+         *     mYLimitsList should be pased.
+         * @param value The coordinate value.
+         */
+        RelativeCoordinate(List<Limits> limitsList, int value) {
+            Limits dummyLimits = new Limits(value, value);
+            int index = Collections.binarySearch(limitsList, dummyLimits);
+
+            if (index >= 0) {
+                this.type = WITHIN_LIMITS;
+                this.limitsBeforeCoordinate = limitsList.get(index);
+            } else if (~index == 0) {
+                this.type = BEFORE_FIRST_ITEM;
+                this.mFirstKnownItem = limitsList.get(0);
+            } else if (~index == limitsList.size()) {
+                Limits lastLimits = limitsList.get(limitsList.size() - 1);
+                if (lastLimits.lowerLimit <= value && value <= lastLimits.upperLimit) {
+                    this.type = WITHIN_LIMITS;
+                    this.limitsBeforeCoordinate = lastLimits;
+                } else {
+                    this.type = AFTER_LAST_ITEM;
+                    this.mLastKnownItem = lastLimits;
+                }
+            } else {
+                Limits limitsBeforeIndex = limitsList.get(~index - 1);
+                if (limitsBeforeIndex.lowerLimit <= value && value <= limitsBeforeIndex.upperLimit) {
+                    this.type = WITHIN_LIMITS;
+                    this.limitsBeforeCoordinate = limitsList.get(~index - 1);
+                } else {
+                    this.type = BETWEEN_TWO_ITEMS;
+                    this.limitsBeforeCoordinate = limitsList.get(~index - 1);
+                    this.limitsAfterCoordinate = limitsList.get(~index);
+                }
+            }
+        }
+
+        int toComparisonValue() {
+            if (type == BEFORE_FIRST_ITEM) {
+                return mFirstKnownItem.lowerLimit - 1;
+            } else if (type == AFTER_LAST_ITEM) {
+                return mLastKnownItem.upperLimit + 1;
+            } else if (type == BETWEEN_TWO_ITEMS) {
+                return limitsBeforeCoordinate.upperLimit + 1;
+            } else {
+                return limitsBeforeCoordinate.lowerLimit;
+            }
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof RelativeCoordinate)) {
+                return false;
+            }
+
+            RelativeCoordinate otherCoordinate = (RelativeCoordinate) other;
+            return toComparisonValue() == otherCoordinate.toComparisonValue();
+        }
+
+        @Override
+        public int compareTo(RelativeCoordinate other) {
+            return toComparisonValue() - other.toComparisonValue();
+        }
+    }
+
+    /**
+     * The location of a point relative to the Limits of nearby items; consists of both an x- and
+     * y-RelativeCoordinateLocation.
+     */
+    private class RelativePoint {
+        final RelativeCoordinate xLocation;
+        final RelativeCoordinate yLocation;
+
+        RelativePoint(Point point) {
+            this.xLocation = new RelativeCoordinate(mXLimitsList, point.x);
+            this.yLocation = new RelativeCoordinate(mYLimitsList, point.y);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof RelativePoint)) {
+                return false;
+            }
+
+            RelativePoint otherPoint = (RelativePoint) other;
+            return xLocation.equals(otherPoint.xLocation) && yLocation.equals(otherPoint.yLocation);
+        }
+
+        /**
+         * Generates a rectangle which contains the items selected by the two points.
+         * @param other The other PointLocation. A rectangle will be formed between "this" and
+         *     "other".
+         * @return The rectangle, or null if no items were selected.
+         */
+        Rect computeBounds(RelativePoint other) {
+            if (!areItemsCoveredBySelection(mRelativePointer, mRelativeOrigin)) {
+                return null;
+            }
+
+            RelativeCoordinate minXLocation =
+                    xLocation.compareTo(other.xLocation) < 0 ? xLocation : other.xLocation;
+            RelativeCoordinate maxXLocation =
+                    minXLocation == xLocation ? other.xLocation : xLocation;
+            RelativeCoordinate minYLocation =
+                    yLocation.compareTo(other.yLocation) < 0 ? yLocation : other.yLocation;
+            RelativeCoordinate maxYLocation =
+                    minYLocation == yLocation ? other.yLocation : yLocation;
+
+            Rect rect = new Rect();
+            rect.left = getCoordinateValue(minXLocation, mXLimitsList, true);
+            rect.right = getCoordinateValue(maxXLocation, mXLimitsList, false);
+            rect.top = getCoordinateValue(minYLocation, mYLimitsList, true);
+            rect.bottom = getCoordinateValue(maxYLocation, mYLimitsList, false);
+            return rect;
+        }
+
+        int getCoordinateValue(RelativeCoordinate coordinate,
+                List<Limits> limitsList, boolean isStartOfRange) {
+            switch (coordinate.type) {
+                case RelativeCoordinate.BEFORE_FIRST_ITEM:
+                    return limitsList.get(0).lowerLimit;
+                case RelativeCoordinate.AFTER_LAST_ITEM:
+                    return limitsList.get(limitsList.size() - 1).upperLimit;
+                case RelativeCoordinate.BETWEEN_TWO_ITEMS:
+                    if (isStartOfRange) {
+                        return coordinate.limitsAfterCoordinate.lowerLimit;
+                    } else {
+                        return coordinate.limitsBeforeCoordinate.upperLimit;
+                    }
+                case RelativeCoordinate.WITHIN_LIMITS:
+                    return coordinate.limitsBeforeCoordinate.lowerLimit;
+            }
+
+            throw new RuntimeException("Invalid coordinate value.");
+        }
+    }
+
+    private static boolean areItemsCoveredBySelection(
+            RelativePoint first, RelativePoint second) {
+        return doesCoordinateLocationCoverItems(first.xLocation, second.xLocation) &&
+                doesCoordinateLocationCoverItems(first.yLocation, second.yLocation);
+    }
+
+    private static boolean doesCoordinateLocationCoverItems(
+            RelativeCoordinate pointerCoordinate,
+            RelativeCoordinate originCoordinate) {
+        if (pointerCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM &&
+                originCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM) {
+            return false;
+        }
+
+        if (pointerCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM &&
+                originCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM) {
+            return false;
+        }
+
+        if (pointerCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
+                originCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
+                pointerCoordinate.limitsBeforeCoordinate.equals(originCoordinate) &&
+                pointerCoordinate.limitsAfterCoordinate.equals(originCoordinate)) {
+            return false;
+        }
+
+        return true;
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 9b8d847..a804e9a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -22,7 +22,6 @@
 import static com.android.documentsui.DirectoryFragment.ANIM_UP;
 import static com.android.internal.util.Preconditions.checkArgument;
 
-import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.Fragment;
 import android.content.Intent;
@@ -38,6 +37,7 @@
 import android.os.Parcelable;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
+import android.support.annotation.Nullable;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
@@ -60,8 +60,6 @@
 import com.android.documentsui.model.DurableUtils;
 import com.android.documentsui.model.RootInfo;
 
-import com.google.common.collect.Maps;
-
 import libcore.io.IoUtils;
 
 import java.io.FileNotFoundException;
@@ -371,7 +369,7 @@
         public String currentSearch;
 
         /** Instance state for every shown directory */
-        public HashMap<String, SparseArray<Parcelable>> dirState = Maps.newHashMap();
+        public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>();
 
         /** Currently copying file */
         public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<DocumentInfo>();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index f927595..e408e6e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -16,7 +16,7 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
 
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -36,7 +36,6 @@
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.inputmethod.EditorInfo;
 import android.widget.EditText;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 5223d76..704e607 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -24,14 +24,13 @@
 import static com.android.documentsui.BaseActivity.State.MODE_LIST;
 import static com.android.documentsui.BaseActivity.State.MODE_UNKNOWN;
 import static com.android.documentsui.BaseActivity.State.SORT_ORDER_UNKNOWN;
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.internal.util.Preconditions.checkState;
 
-import android.annotation.NonNull;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.Fragment;
@@ -98,7 +97,7 @@
 import com.android.documentsui.model.RootInfo;
 import com.android.internal.util.Preconditions;
 
-import com.google.android.collect.Lists;
+import com.google.common.collect.Lists;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -235,8 +234,7 @@
                     public void onLayoutChange(
                             View v, int left, int top, int right, int bottom, int oldLeft,
                             int oldTop, int oldRight, int oldBottom) {
-                        int thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width);
-                        mColumnCount = pickColumnCount(thumbSize);
+                        mColumnCount = calculateColumnCount();
                         if (mGridLayout != null) {
                             mGridLayout.setSpanCount(mColumnCount);
                         }
@@ -535,8 +533,6 @@
 
         updateLayout(state.derivedMode);
 
-        final int thumbSize = getResources().getDimensionPixelSize(R.dimen.icon_size);
-        mThumbSize = new Point(thumbSize, thumbSize);
         mRecView.setAdapter(mAdapter);
     }
 
@@ -573,13 +569,15 @@
         mThumbSize = new Point(thumbSize, thumbSize);
     }
 
-    private int pickColumnCount(final int thumbSize) {
-        int itemPadding =
-                getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
+    private int calculateColumnCount() {
+        int cellWidth = getResources().getDimensionPixelSize(R.dimen.grid_width);
+        int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
         int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight();
+
         checkState(mRecView.getWidth() > 0);
         int columnCount = Math.max(1,
-                (mRecView.getWidth() - viewPadding) / (thumbSize + itemPadding));
+                (mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin));
+
         return columnCount;
     }
 
@@ -753,7 +751,7 @@
                 Intent intent;
 
                 // Filter out directories - those can't be shared.
-                List<DocumentInfo> docsForSend = Lists.newArrayList();
+                List<DocumentInfo> docsForSend = new ArrayList<>();
                 for (DocumentInfo doc: docs) {
                     if (!Document.MIME_TYPE_DIR.equals(doc.mimeType)) {
                         docsForSend.add(doc);
@@ -774,8 +772,8 @@
                     intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                     intent.addCategory(Intent.CATEGORY_DEFAULT);
 
-                    final ArrayList<String> mimeTypes = Lists.newArrayList();
-                    final ArrayList<Uri> uris = Lists.newArrayList();
+                    final ArrayList<String> mimeTypes = new ArrayList<>();
+                    final ArrayList<Uri> uris = new ArrayList<>();
                     for (DocumentInfo doc : docsForSend) {
                         mimeTypes.add(doc.mimeType);
                         uris.add(doc.derivedUri);
@@ -956,7 +954,7 @@
         private final Context mContext;
         private final LayoutInflater mInflater;
         // TODO: Bring back support for footers.
-        private final List<Footer> mFooters = Lists.newArrayList();
+        private final List<Footer> mFooters = new ArrayList<>();
 
         private Cursor mCursor;
         private int mCursorCount;
@@ -1330,7 +1328,7 @@
         return MimePredicate.mimeMatches(state.acceptMimes, docMimeType);
     }
 
-    private @NonNull List<DocumentInfo> getSelectedDocuments() {
+    private List<DocumentInfo> getSelectedDocuments() {
         Selection sel = mSelectionManager.getSelection(new Selection());
         return getItemsAsDocuments(sel);
     }
@@ -1570,6 +1568,7 @@
         final Cursor cursor = mAdapter.getItem(position);
         checkNotNull(cursor, "Cursor cannot be null.");
         final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
+
         return Lists.newArrayList(doc);
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index a8a61d2..0edb241 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -16,12 +16,12 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.DocumentsActivity.TAG;
 import static com.android.documentsui.BaseActivity.State.MODE_UNKNOWN;
 import static com.android.documentsui.BaseActivity.State.SORT_ORDER_DISPLAY_NAME;
 import static com.android.documentsui.BaseActivity.State.SORT_ORDER_LAST_MODIFIED;
 import static com.android.documentsui.BaseActivity.State.SORT_ORDER_SIZE;
 import static com.android.documentsui.BaseActivity.State.SORT_ORDER_UNKNOWN;
+import static com.android.documentsui.Shared.TAG;
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 
 import android.content.AsyncTaskLoader;
@@ -31,8 +31,6 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.Looper;
 import android.os.OperationCanceledException;
 import android.os.RemoteException;
 import android.provider.DocumentsContract;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
index 2370575..6ba07fbb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
@@ -16,8 +16,6 @@
 
 package com.android.documentsui;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.ContentProviderClient;
@@ -26,15 +24,15 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.DocumentsContract;
+import android.support.annotation.Nullable;
 import android.util.Log;
 
 import com.android.documentsui.model.DocumentInfo;
 import com.android.internal.util.Preconditions;
 
-import com.google.android.collect.Lists;
-
 import libcore.io.IoUtils;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -78,7 +76,7 @@
      * Returns a list of Documents as decoded from Clipboard primary clipdata.
      * This should be run from inside an AsyncTask.
      */
-    public @NonNull List<DocumentInfo> getClippedDocuments() {
+    public List<DocumentInfo> getClippedDocuments() {
         return getDocumentsFromClipData(mClipboard.getPrimaryClip());
     }
 
@@ -86,9 +84,9 @@
      * Returns a list of Documents as decoded in clipData.
      * This should be run from inside an AsyncTask.
      */
-    public @NonNull List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) {
+    public List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) {
         Preconditions.checkNotNull(clipData);
-        final List<DocumentInfo> srcDocs = Lists.newArrayList();
+        final List<DocumentInfo> srcDocs = new ArrayList<>();
 
         int count = clipData.getItemCount();
         if (count == 0) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 2de7fc4..2c6bdb3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -26,7 +26,6 @@
 import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
 import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
 import static com.android.documentsui.DirectoryFragment.ANIM_UP;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -48,9 +47,6 @@
 import android.os.Parcelable;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
-import android.support.v4.app.ActionBarDrawerToggle;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v4.widget.DrawerLayout.DrawerListener;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -81,9 +77,7 @@
 
     private Toolbar mRootsToolbar;
 
-    private DrawerLayout mDrawerLayout;
-    private ActionBarDrawerToggle mDrawerToggle;
-    private View mRootsDrawer;
+    private DrawerController mDrawer;
 
     private DirectoryContainerView mDirectoryContainer;
 
@@ -105,6 +99,7 @@
         final Resources res = getResources();
         mShowAsDialog = res.getBoolean(R.bool.show_as_dialog) && mState.action != ACTION_MANAGE &&
                 mState.action != ACTION_BROWSE;
+
         if (!mShowAsDialog) {
             setTheme(R.style.DocumentsNonDialogTheme);
         }
@@ -117,6 +112,8 @@
         final Context context = this;
 
         if (mShowAsDialog) {
+            mDrawer = DrawerController.createDummy();
+
             // Strongly define our horizontal dimension; we leave vertical as
             // WRAP_CONTENT so that system resizes us when IME is showing.
             final WindowManager.LayoutParams a = getWindow().getAttributes();
@@ -128,17 +125,7 @@
             getWindow().setAttributes(a);
 
         } else {
-            // Non-dialog means we have a drawer
-            mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
-
-            if (mDrawerLayout != null) {
-                mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
-                        R.drawable.ic_hamburger, R.string.drawer_open, R.string.drawer_close);
-
-                mDrawerLayout.setDrawerListener(mDrawerListener);
-
-                mRootsDrawer = findViewById(R.id.drawer_roots);
-            }
+            mDrawer = DrawerController.create(this);
         }
 
         mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
@@ -162,10 +149,9 @@
 
         // Hide roots when we're managing a specific root
         if (mState.action == ACTION_MANAGE || mState.action == ACTION_BROWSE) {
-            if (mShowAsDialog || mDrawerLayout == null) {
+            mDrawer.lockClosed();
+            if (mShowAsDialog) {
                 findViewById(R.id.container_roots).setVisibility(View.GONE);
-            } else {
-                mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
             }
         }
 
@@ -341,53 +327,15 @@
         }
     }
 
-    private DrawerListener mDrawerListener = new DrawerListener() {
-        @Override
-        public void onDrawerSlide(View drawerView, float slideOffset) {
-            mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
-        }
-
-        @Override
-        public void onDrawerOpened(View drawerView) {
-            mDrawerToggle.onDrawerOpened(drawerView);
-        }
-
-        @Override
-        public void onDrawerClosed(View drawerView) {
-            mDrawerToggle.onDrawerClosed(drawerView);
-        }
-
-        @Override
-        public void onDrawerStateChanged(int newState) {
-            mDrawerToggle.onDrawerStateChanged(newState);
-        }
-    };
-
     @Override
     protected void onPostCreate(Bundle savedInstanceState) {
         super.onPostCreate(savedInstanceState);
-        if (mDrawerToggle != null) {
-            mDrawerToggle.syncState();
-        }
+        mDrawer.syncState();
         updateActionBar();
     }
 
     public void setRootsDrawerOpen(boolean open) {
-        if (!mShowAsDialog && mDrawerLayout != null) {
-            if (open) {
-                mDrawerLayout.openDrawer(mRootsDrawer);
-            } else {
-                mDrawerLayout.closeDrawer(mRootsDrawer);
-            }
-        }
-    }
-
-    private boolean isRootsDrawerOpen() {
-        if (mShowAsDialog || mDrawerLayout == null) {
-            return false;
-        } else {
-            return mDrawerLayout.isDrawerOpen(mRootsDrawer);
-        }
+        mDrawer.setOpen(open);
     }
 
     @Override
@@ -408,8 +356,7 @@
             }
         }
 
-        if (!mShowAsDialog && mDrawerLayout != null &&
-                mDrawerLayout.getDrawerLockMode(mRootsDrawer) == DrawerLayout.LOCK_MODE_UNLOCKED) {
+        if (!mShowAsDialog && mDrawer.isUnlocked()) {
             mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
             mToolbar.setNavigationContentDescription(R.string.drawer_open);
             mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@@ -504,10 +451,7 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        if (mDrawerToggle != null && mDrawerToggle.onOptionsItemSelected(item)) {
-            return true;
-        }
-        return super.onOptionsItemSelected(item);
+        return mDrawer.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
     }
 
     @Override
@@ -526,7 +470,7 @@
         if (size > 1) {
             mState.stack.pop();
             onCurrentDirectoryChanged(ANIM_UP);
-        } else if (size == 1 && !isRootsDrawerOpen()) {
+        } else if (size == 1 && !mDrawer.isOpen()) {
             // TODO: open root drawer once we can capture back key
             super.onBackPressed();
         } else {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
new file mode 100644
index 0000000..cf16c3f
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -0,0 +1,196 @@
+/*
+ * 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 static com.android.internal.util.Preconditions.checkArgument;
+
+import android.app.Activity;
+import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v4.widget.DrawerLayout.DrawerListener;
+import android.view.MenuItem;
+import android.view.View;
+
+/**
+ * A facade over the various pieces comprising "roots fragment in a Drawer".
+ *
+ * @see DrawerController#create(DrawerLayout)
+ */
+abstract class DrawerController implements DrawerListener {
+
+    abstract void setOpen(boolean open);
+    abstract void lockOpen();
+    abstract void lockClosed();
+    abstract boolean isOpen();
+    abstract boolean isUnlocked();
+    abstract void syncState();
+    abstract boolean onOptionsItemSelected(MenuItem item);
+
+    /**
+     * Returns a controller suitable for {@code Layout}.
+     */
+    static DrawerController create(Activity activity) {
+
+        DrawerLayout layout = (DrawerLayout) activity.findViewById(R.id.drawer_layout);
+
+        if (layout == null) {
+            return new DummyDrawerController();
+        }
+
+        View drawer = activity.findViewById(R.id.drawer_roots);
+        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
+                activity,
+                layout,
+                R.drawable.ic_hamburger,
+                R.string.drawer_open,
+                R.string.drawer_close);
+
+        return new RuntimeDrawerController(layout, drawer, toggle);
+    }
+
+    /**
+     * Returns a controller suitable for {@code Layout}.
+     */
+    static DrawerController createDummy() {
+        return new DummyDrawerController();
+    }
+
+    /**
+     * Runtime controller that manages a real drawer.
+     */
+    private static final class RuntimeDrawerController extends DrawerController {
+
+        private final ActionBarDrawerToggle mToggle;
+        private DrawerLayout mLayout;
+        private View mDrawer;
+
+        public RuntimeDrawerController(
+                DrawerLayout layout, View drawer, ActionBarDrawerToggle toggle) {
+            checkArgument(layout != null);
+
+            mLayout = layout;
+            mDrawer = drawer;
+            mToggle = toggle;
+
+            mLayout.setDrawerListener(this);
+        }
+
+        @Override
+        void setOpen(boolean open) {
+            if (open) {
+                mLayout.openDrawer(mDrawer);
+            } else {
+                mLayout.closeDrawer(mDrawer);
+            }
+        }
+
+        @Override
+        boolean isOpen() {
+            return mLayout.isDrawerOpen(mDrawer);
+        }
+
+        @Override
+        void syncState() {
+            mToggle.syncState();
+        }
+
+        @Override
+        boolean isUnlocked() {
+            return mLayout.getDrawerLockMode(mDrawer) == DrawerLayout.LOCK_MODE_UNLOCKED;
+        }
+
+        @Override
+        void lockOpen() {
+            mLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
+        }
+
+        @Override
+        void lockClosed() {
+            mLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
+        }
+
+        @Override
+        boolean onOptionsItemSelected(MenuItem item) {
+            return false;
+        }
+
+        @Override
+        public void onDrawerSlide(View drawerView, float slideOffset) {
+            mToggle.onDrawerSlide(drawerView, slideOffset);
+        }
+
+        @Override
+        public void onDrawerOpened(View drawerView) {
+            mToggle.onDrawerOpened(drawerView);
+        }
+
+        @Override
+        public void onDrawerClosed(View drawerView) {
+            mToggle.onDrawerClosed(drawerView);
+        }
+
+        @Override
+        public void onDrawerStateChanged(int newState) {
+            mToggle.onDrawerStateChanged(newState);
+        }
+    }
+
+    /*
+     * Dummy controller useful with clients that don't host a real drawer.
+     */
+    private static final class DummyDrawerController extends DrawerController {
+
+        @Override
+        boolean isOpen() {
+            return false;
+        }
+
+        @Override
+        void syncState() {}
+
+        @Override
+        void lockOpen() {}
+
+        @Override
+        void lockClosed() {}
+
+        @Override
+        boolean isUnlocked() {
+            return true;
+        }
+
+        @Override
+        boolean onOptionsItemSelected(MenuItem item) {
+            return false;
+        }
+
+        @Override
+        public void onDrawerSlide(View drawerView, float slideOffset) {}
+
+        @Override
+        public void onDrawerOpened(View drawerView) {}
+
+        @Override
+        public void onDrawerClosed(View drawerView) {}
+
+        @Override
+        public void onDrawerStateChanged(int newState) {}
+
+        @Override
+        void setOpen(boolean open) {}
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
index 1cbc221..17a1161 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
@@ -16,7 +16,7 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/GridItem.java b/packages/DocumentsUI/src/com/android/documentsui/GridItem.java
new file mode 100644
index 0000000..990dca7
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/GridItem.java
@@ -0,0 +1,51 @@
+/*
+ * 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 android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/**
+ * A FrameLayout subclass used by DirectoryFragment. Ensures that the resulting grid item is always
+ * square.
+ */
+public class GridItem extends FrameLayout {
+    public GridItem(Context context) {
+        super(context);
+    }
+
+    public GridItem(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public GridItem(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // Grid layout uses item width to figure out the number of columns, then dynamically fits
+        // rows into the view. The upshot of this is that changing the item width will mess up the
+        // grid layout - so to make the items square, throw out the height and use the width for
+        // both dimensions. The grid layout will correctly adjust the row height.
+        //
+        // Note that this code will need to be changed if the layout manager's orientation is
+        // changed from VERTICAL to HORIZONTAL.
+        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
index b43fedf..9959265 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
@@ -23,13 +23,11 @@
 import android.provider.DocumentsContract.Document;
 import android.util.TypedValue;
 
-import com.google.android.collect.Maps;
-
 import java.util.HashMap;
 
 public class IconUtils {
 
-    private static HashMap<String, Integer> sMimeIcons = Maps.newHashMap();
+    private static HashMap<String, Integer> sMimeIcons = new HashMap<>();
 
     private static void add(String mimeType, int resId) {
         if (sMimeIcons.put(mimeType, resId) != null) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
index 02edd0c..f87fe4c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
@@ -31,7 +31,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.google.common.annotations.VisibleForTesting;
+import android.support.annotation.VisibleForTesting;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
index f94aebd..b0e332f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
@@ -20,8 +20,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -32,7 +30,7 @@
 public class ProviderExecutor extends Thread implements Executor {
 
     @GuardedBy("sExecutors")
-    private static HashMap<String, ProviderExecutor> sExecutors = Maps.newHashMap();
+    private static HashMap<String, ProviderExecutor> sExecutors = new HashMap<>();
 
     public static ProviderExecutor forAuthority(String authority) {
         synchronized (sExecutors) {
@@ -53,7 +51,7 @@
 
     private final LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<Runnable>();
 
-    private final ArrayList<WeakReference<Preemptable>> mPreemptable = Lists.newArrayList();
+    private final ArrayList<WeakReference<Preemptable>> mPreemptable = new ArrayList<>();
 
     private void preempt() {
         synchronized (mPreemptable) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
index 878c4c2..4685c41 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
@@ -18,7 +18,6 @@
 
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
 
-import android.annotation.Nullable;
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.ComponentName;
@@ -28,6 +27,7 @@
 import android.net.Uri;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
+import android.support.annotation.Nullable;
 import android.util.Log;
 
 import com.android.documentsui.BaseActivity.DocumentContext;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
index f5908c5..1a7095a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
@@ -16,8 +16,8 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.DocumentsActivity.TAG;
 import static com.android.documentsui.BaseActivity.State.SORT_ORDER_LAST_MODIFIED;
+import static com.android.documentsui.Shared.TAG;
 
 import android.app.ActivityManager;
 import android.content.AsyncTaskLoader;
@@ -36,14 +36,14 @@
 
 import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.model.RootInfo;
-import com.google.android.collect.Maps;
-import com.google.common.collect.Lists;
+
 import com.google.common.util.concurrent.AbstractFuture;
 
 import libcore.io.IoUtils;
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -53,7 +53,7 @@
 import java.util.concurrent.TimeUnit;
 
 public class RecentLoader extends AsyncTaskLoader<DirectoryResult> {
-    private static final boolean LOGD = true;
+    private static final boolean DEBUG = false;
 
     // TODO: clean up cursor ownership so background thread doesn't traverse
     // previously returned cursors for filtering/sorting; this currently races
@@ -81,7 +81,7 @@
     private final RootsCache mRoots;
     private final State mState;
 
-    private final HashMap<RootInfo, RecentTask> mTasks = Maps.newHashMap();
+    private final HashMap<RootInfo, RecentTask> mTasks = new HashMap<>();
 
     private final int mSortOrder = State.SORT_ORDER_LAST_MODIFIED;
 
@@ -196,7 +196,7 @@
 
         // Collect all finished tasks
         boolean allDone = true;
-        List<Cursor> cursors = Lists.newArrayList();
+        List<Cursor> cursors = new ArrayList<>();
         for (RecentTask task : mTasks.values()) {
             if (task.isDone()) {
                 try {
@@ -221,7 +221,7 @@
             }
         }
 
-        if (LOGD) {
+        if (DEBUG) {
             Log.d(TAG, "Found " + cursors.size() + " of " + mTasks.size() + " recent queries done");
         }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index e11d7d9..662822e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -16,7 +16,7 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
 
 import android.app.Fragment;
 import android.app.FragmentManager;
@@ -50,7 +50,6 @@
 import com.android.documentsui.model.DocumentStack;
 import com.android.documentsui.model.DurableUtils;
 import com.android.documentsui.model.RootInfo;
-import com.google.android.collect.Lists;
 
 import libcore.io.IoUtils;
 
@@ -157,7 +156,7 @@
         @Override
         public List<DocumentStack> loadInBackground(Uri uri, CancellationSignal signal) {
             final Collection<RootInfo> matchingRoots = mRoots.getMatchingRootsBlocking(mState);
-            final ArrayList<DocumentStack> result = Lists.newArrayList();
+            final ArrayList<DocumentStack> result = new ArrayList<>();
 
             final ContentResolver resolver = getContext().getContentResolver();
             final Cursor cursor = resolver.query(
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index fbcb938..05f7d8d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -16,7 +16,7 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
 
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
@@ -39,14 +39,14 @@
 import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.model.RootInfo;
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
+import android.support.annotation.VisibleForTesting;
+
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Multimap;
 
 import libcore.io.IoUtils;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
@@ -74,10 +74,10 @@
     @GuardedBy("mLock")
     private Multimap<String, RootInfo> mRoots = ArrayListMultimap.create();
     @GuardedBy("mLock")
-    private HashSet<String> mStoppedAuthorities = Sets.newHashSet();
+    private HashSet<String> mStoppedAuthorities = new HashSet<>();
 
     @GuardedBy("mObservedAuthorities")
-    private final HashSet<String> mObservedAuthorities = Sets.newHashSet();
+    private final HashSet<String> mObservedAuthorities = new HashSet<>();
 
     public RootsCache(Context context) {
         mContext = context;
@@ -159,7 +159,7 @@
         private final String mFilterPackage;
 
         private final Multimap<String, RootInfo> mTaskRoots = ArrayListMultimap.create();
-        private final HashSet<String> mTaskStoppedAuthorities = Sets.newHashSet();
+        private final HashSet<String> mTaskStoppedAuthorities = new HashSet<>();
 
         /**
          * Update all roots.
@@ -251,7 +251,7 @@
             }
         }
 
-        final List<RootInfo> roots = Lists.newArrayList();
+        final List<RootInfo> roots = new ArrayList<>();
         final Uri rootsUri = DocumentsContract.buildRootsUri(authority);
 
         ContentProviderClient client = null;
@@ -350,7 +350,7 @@
 
     @VisibleForTesting
     static List<RootInfo> getMatchingRoots(Collection<RootInfo> roots, State state) {
-        final List<RootInfo> matching = Lists.newArrayList();
+        final List<RootInfo> matching = new ArrayList<>();
         for (RootInfo root : roots) {
             final boolean supportsCreate = (root.flags & Root.FLAG_SUPPORTS_CREATE) != 0;
             final boolean supportsIsChild = (root.flags & Root.FLAG_SUPPORTS_IS_CHILD) != 0;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index fd67a77..c02184b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -44,8 +44,8 @@
 import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.RootInfo;
-import com.google.common.collect.Lists;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -293,8 +293,8 @@
             RootItem audio = null;
             RootItem downloads = null;
 
-            final List<RootInfo> clouds = Lists.newArrayList();
-            final List<RootInfo> locals = Lists.newArrayList();
+            final List<RootInfo> clouds = new ArrayList<>();
+            final List<RootInfo> locals = new ArrayList<>();
 
             for (RootInfo root : roots) {
                 if (root.isRecents()) {
@@ -338,7 +338,7 @@
                 final List<ResolveInfo> infos = pm.queryIntentActivities(
                         includeApps, PackageManager.MATCH_DEFAULT_ONLY);
 
-                final List<AppItem> apps = Lists.newArrayList();
+                final List<AppItem> apps = new ArrayList<>();
 
                 // Omit ourselves from the list
                 for (ResolveInfo info : infos) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java
index 088e3fa..ae959f9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java
@@ -22,8 +22,6 @@
 import android.widget.BaseAdapter;
 import android.widget.ListAdapter;
 
-import com.google.android.collect.Lists;
-
 import java.util.ArrayList;
 
 /**
@@ -31,7 +29,7 @@
  * provide a header, and correctly handling item types across child adapters.
  */
 public class SectionedListAdapter extends BaseAdapter {
-    private ArrayList<SectionAdapter> mSections = Lists.newArrayList();
+    private ArrayList<SectionAdapter> mSections = new ArrayList<>();
 
     public interface SectionAdapter extends ListAdapter {
         public View getHeaderView(View convertView, ViewGroup parent);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
new file mode 100644
index 0000000..b414ee3
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+/**
+ * @hide
+ */
+public final class Shared {
+    public static final String TAG = "Documents";
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java b/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java
index 1ca277d..7ca3954 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java
@@ -20,7 +20,6 @@
 import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
 import static com.android.documentsui.DirectoryFragment.ANIM_UP;
 
-import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.FragmentManager;
 import android.content.ActivityNotFoundException;
@@ -33,6 +32,7 @@
 import android.os.Bundle;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
+import android.support.annotation.Nullable;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.Menu;
@@ -70,6 +70,8 @@
     private ItemSelectedListener mStackListener;
     private BaseAdapter mStackAdapter;
     private DocumentClipper mClipper;
+    private DrawerController mDrawer;
+    private boolean mCompactMode;
 
     public StandaloneActivity() {
         super(TAG);
@@ -107,6 +109,18 @@
 
         setActionBar(mToolbar);
 
+
+        // "show as dialog" is true on BIG screens. But we *assume* a big screen
+        // and specialize for smaller screens by moving roots into an auto-hide drawer.
+        // This works in conjunction with the specialized layouts defined for sw720dp.
+        mCompactMode = !getResources().getBoolean(R.bool.show_as_dialog);
+
+        if (mCompactMode) {
+            setTheme(R.style.DocumentsNonDialogTheme);
+        }
+
+        mDrawer = DrawerController.create(this);
+
         mClipper = new DocumentClipper(this);
 
         RootsFragment.show(getFragmentManager(), null);
@@ -164,10 +178,23 @@
     @Override
     public void updateActionBar() {
         final RootInfo root = getCurrentRoot();
-        mToolbar.setNavigationIcon(
-                root != null ? root.loadToolbarIcon(mToolbar.getContext()) : null);
-        mToolbar.setNavigationContentDescription(R.string.drawer_open);
-        mToolbar.setNavigationOnClickListener(null);
+
+        if (mCompactMode) {
+            mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
+            mToolbar.setNavigationContentDescription(R.string.drawer_open);
+            mToolbar.setNavigationOnClickListener(
+                    new View.OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            mDrawer.setOpen(true);
+                        }
+                    });
+        } else {
+            mToolbar.setNavigationIcon(
+                    root != null ? root.loadToolbarIcon(mToolbar.getContext()) : null);
+            mToolbar.setNavigationContentDescription(R.string.drawer_open);
+            mToolbar.setNavigationOnClickListener(null);
+        }
 
         if (mSearchManager.isExpanded()) {
             mToolbar.setTitle(null);
@@ -284,6 +311,12 @@
     }
 
     @Override
+    void onRootPicked(RootInfo root) {
+        super.onRootPicked(root);
+        mDrawer.setOpen(false);
+    }
+
+    @Override
     public void onDocumentsPicked(List<DocumentInfo> docs) {
         throw new UnsupportedOperationException();
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java b/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
index 1a5bb0c..7bb662c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
@@ -27,16 +27,16 @@
  * changes while started, manages {@link CancellationSignal}, and caches
  * returned results.
  */
-public abstract class UriDerivativeLoader<P, R> extends AsyncTaskLoader<R> {
+public abstract class UriDerivativeLoader<Param, Res> extends AsyncTaskLoader<Res> {
     final ForceLoadContentObserver mObserver;
 
-    private final P mParam;
+    private final Param mParam;
 
-    private R mResult;
+    private Res mResult;
     private CancellationSignal mCancellationSignal;
 
     @Override
-    public final R loadInBackground() {
+    public final Res loadInBackground() {
         synchronized (this) {
             if (isLoadInBackgroundCanceled()) {
                 throw new OperationCanceledException();
@@ -52,7 +52,7 @@
         }
     }
 
-    public abstract R loadInBackground(P param, CancellationSignal signal);
+    public abstract Res loadInBackground(Param param, CancellationSignal signal);
 
     @Override
     public void cancelLoadInBackground() {
@@ -66,12 +66,12 @@
     }
 
     @Override
-    public void deliverResult(R result) {
+    public void deliverResult(Res result) {
         if (isReset()) {
             closeQuietly(result);
             return;
         }
-        R oldResult = mResult;
+        Res oldResult = mResult;
         mResult = result;
 
         if (isStarted()) {
@@ -83,7 +83,7 @@
         }
     }
 
-    public UriDerivativeLoader(Context context, P param) {
+    public UriDerivativeLoader(Context context, Param param) {
         super(context);
         mObserver = new ForceLoadContentObserver();
         mParam = param;
@@ -105,7 +105,7 @@
     }
 
     @Override
-    public void onCanceled(R result) {
+    public void onCanceled(Res result) {
         closeQuietly(result);
     }
 
@@ -122,7 +122,7 @@
         getContext().getContentResolver().unregisterContentObserver(mObserver);
     }
 
-    private void closeQuietly(R result) {
+    private void closeQuietly(Res result) {
         if (result instanceof AutoCloseable) {
             try {
                 ((AutoCloseable) result).close();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
index 5d5f2eb..cc981e1e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
@@ -24,7 +24,6 @@
 import android.os.Parcelable;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsProvider;
 import android.text.TextUtils;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java b/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java
index 2a29cbc..e21dd49 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java
@@ -16,7 +16,7 @@
 
 package com.android.documentsui.model;
 
-import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.Shared.TAG;
 
 import android.os.BadParcelableException;
 import android.os.Parcel;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectMatrixTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectMatrixTest.java
new file mode 100644
index 0000000..f15a643
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectMatrixTest.java
@@ -0,0 +1,277 @@
+/*
+ * 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 static org.junit.Assert.*;
+
+import com.android.documentsui.BandSelectMatrix;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
+import android.util.SparseBooleanArray;
+
+import org.junit.After;
+import org.junit.Test;
+
+public class BandSelectMatrixTest {
+
+    private static final int VIEW_PADDING_PX = 5;
+    private static final int CHILD_VIEW_EDGE_PX = 100;
+    private static final int VIEWPORT_HEIGHT = 500;
+
+    private static BandSelectMatrix matrix;
+    private static TestHelper helper;
+    private static SparseBooleanArray lastSelection;
+    private static int viewWidth;
+
+    private static void setUp(int numChildren, int numColumns) {
+        helper = new TestHelper(numChildren, numColumns);
+        viewWidth = VIEW_PADDING_PX + numColumns * (VIEW_PADDING_PX + CHILD_VIEW_EDGE_PX);
+        matrix = new BandSelectMatrix(helper);
+        matrix.addOnSelectionChangedListener(new BandSelectMatrix.OnSelectionChangedListener() {
+
+            @Override
+            public void onSelectionChanged(SparseBooleanArray updatedSelection) {
+                lastSelection = updatedSelection;
+            }
+        });
+    }
+
+    @After
+    public void tearDown() {
+        matrix = null;
+        helper = null;
+        lastSelection = null;
+    }
+
+    @Test
+    public void testSelectionLeftOfItems() {
+        setUp(20, 5);
+        matrix.startSelection(new Point(0, 10));
+        matrix.resizeSelection(new Point(1, 11));
+        assertSelected(new int[0]);
+    }
+
+    @Test
+    public void testSelectionRightOfItems() {
+        setUp(20, 4);
+        matrix.startSelection(new Point(viewWidth - 1, 10));
+        matrix.resizeSelection(new Point(viewWidth - 2, 11));
+        assertSelected(new int[0]);
+    }
+
+    @Test
+    public void testSelectionAboveItems() {
+        setUp(20, 4);
+        matrix.startSelection(new Point(10, 0));
+        matrix.resizeSelection(new Point(11, 1));
+        assertSelected(new int[0]);
+    }
+
+    @Test
+    public void testSelectionBelowItems() {
+        setUp(5, 4);
+        matrix.startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
+        matrix.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
+        assertSelected(new int[0]);
+    }
+
+    @Test
+    public void testVerticalSelectionBetweenItems() {
+        setUp(20, 4);
+        matrix.startSelection(new Point(106, 0));
+        matrix.resizeSelection(new Point(107, 200));
+        assertSelected(new int[0]);
+    }
+
+    @Test
+    public void testHorizontalSelectionBetweenItems() {
+        setUp(20, 4);
+        matrix.startSelection(new Point(0, 105));
+        matrix.resizeSelection(new Point(200, 106));
+        assertSelected(new int[0]);
+    }
+
+    @Test
+    public void testGrowingAndShrinkingSelection() {
+        setUp(20, 4);
+        matrix.startSelection(new Point(0, 0));
+        matrix.resizeSelection(new Point(5, 5));
+        assertSelected(new int[] {0});
+        matrix.resizeSelection(new Point(109, 109));
+        assertSelected(new int[] {0});
+        matrix.resizeSelection(new Point(110, 109));
+        assertSelected(new int[] {0, 1});
+        matrix.resizeSelection(new Point(110, 110));
+        assertSelected(new int[] {0, 1, 4, 5});
+        matrix.resizeSelection(new Point(214, 214));
+        assertSelected(new int[] {0, 1, 4, 5});
+        matrix.resizeSelection(new Point(215, 214));
+        assertSelected(new int[] {0, 1, 2, 4, 5, 6});
+        matrix.resizeSelection(new Point(214, 214));
+        assertSelected(new int[] {0, 1, 4, 5});
+        matrix.resizeSelection(new Point(110, 110));
+        assertSelected(new int[] {0, 1, 4, 5});
+        matrix.resizeSelection(new Point(110, 109));
+        assertSelected(new int[] {0, 1});
+        matrix.resizeSelection(new Point(109, 109));
+        assertSelected(new int[] {0});
+        matrix.resizeSelection(new Point(5, 5));
+        assertSelected(new int[] {0});
+        matrix.resizeSelection(new Point(0, 0));
+        assertSelected(new int[0]);
+    }
+
+    @Test
+    public void testSelectionMovingAroundOrigin() {
+        setUp(16, 4);
+        matrix.startSelection(new Point(210, 210));
+        matrix.resizeSelection(new Point(viewWidth - 1, 0));
+        assertSelected(new int[] {2, 3, 6, 7});
+        matrix.resizeSelection(new Point(0, 0));
+        assertSelected(new int[] {0, 1, 4, 5});
+        matrix.resizeSelection(new Point(0, 420));
+        assertSelected(new int[] {8, 9, 12, 13});
+        matrix.resizeSelection(new Point(viewWidth - 1, 420));
+        assertSelected(new int[] {10, 11, 14, 15});
+    }
+
+    @Test
+    public void testScrollingBandSelect() {
+        setUp(40, 4);
+        matrix.startSelection(new Point(0, 0));
+        matrix.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+        assertSelected(new int[] {0, 4, 8, 12, 16});
+        scroll(CHILD_VIEW_EDGE_PX);
+        assertSelected(new int[] {0, 4, 8, 12, 16, 20});
+        matrix.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
+        assertSelected(new int[] {0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21});
+        scroll(CHILD_VIEW_EDGE_PX);
+        assertSelected(new int[] {0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25});
+        scroll(-2 * CHILD_VIEW_EDGE_PX);
+        assertSelected(new int[] {0, 1, 4, 5, 8, 9, 12, 13, 16, 17});
+        matrix.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+        assertSelected(new int[] {0, 4, 8, 12, 16});
+    }
+
+    private static void assertSelected(int[] selectedPositions) {
+        assertEquals(selectedPositions.length, lastSelection.size());
+        for (int position : selectedPositions) {
+            assertTrue(lastSelection.get(position));
+        }
+    }
+
+    private static void scroll(int dy) {
+        assertTrue(helper.verticalOffset + VIEWPORT_HEIGHT + dy <= helper.getTotalHeight());
+        helper.verticalOffset += dy;
+        matrix.onScrolled(null, 0, dy);
+    }
+
+    private static final class TestHelper implements BandSelectMatrix.RecyclerViewHelper {
+
+        public int horizontalOffset = 0;
+        public int verticalOffset = 0;
+        private final int mNumColumns;
+        private final int mNumRows;
+        private final int mNumChildren;
+
+        public TestHelper(int numChildren, int numColumns) {
+            mNumChildren = numChildren;
+            mNumColumns = numColumns;
+            mNumRows = (int) Math.ceil((double) numChildren / mNumColumns);
+        }
+
+        private int getTotalHeight() {
+            return CHILD_VIEW_EDGE_PX * mNumRows + VIEW_PADDING_PX * (mNumRows + 1);
+        }
+
+        private int getFirstVisibleRowIndex() {
+            return verticalOffset / (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
+        }
+
+        private int getLastVisibleRowIndex() {
+            int lastVisibleRowUncapped =
+                    (VIEWPORT_HEIGHT + verticalOffset - 1) / (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
+            return Math.min(lastVisibleRowUncapped, mNumRows - 1);
+        }
+
+        private int getNumItemsInRow(int index) {
+            assertTrue(index >= 0 && index < mNumRows);
+            if (index == mNumRows - 1 && mNumChildren % mNumColumns != 0) {
+                return mNumChildren % mNumColumns;
+            }
+
+            return mNumColumns;
+        }
+
+        @Override
+        public void addOnScrollListener(OnScrollListener listener) {}
+
+        @Override
+        public void removeOnScrollListener(OnScrollListener listener) {}
+
+        @Override
+        public Point createAbsolutePoint(Point relativePoint) {
+            return new Point(
+                    relativePoint.x + horizontalOffset, relativePoint.y + verticalOffset);
+        }
+
+        @Override
+        public int getVisibleChildCount() {
+            int childCount = 0;
+            for (int i = getFirstVisibleRowIndex(); i <= getLastVisibleRowIndex(); i++) {
+                childCount += getNumItemsInRow(i);
+            }
+            return childCount;
+        }
+
+        @Override
+        public int getAdapterPositionAt(int index) {
+            return index + mNumColumns * (getFirstVisibleRowIndex());
+        }
+
+        @Override
+        public Rect getAbsoluteRectForChildViewAt(int index) {
+            int adapterPosition = getAdapterPositionAt(index);
+            int rowIndex = adapterPosition / mNumColumns;
+            int columnIndex = adapterPosition % mNumColumns;
+
+            Rect rect = new Rect();
+            rect.top = VIEW_PADDING_PX + rowIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
+            rect.bottom = rect.top + CHILD_VIEW_EDGE_PX - 1;
+            rect.left = VIEW_PADDING_PX + columnIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
+            rect.right = rect.left + CHILD_VIEW_EDGE_PX - 1;
+            return rect;
+        }
+
+        @Override
+        public int getTotalChildCount() {
+            return mNumChildren;
+        }
+
+        @Override
+        public int getNumColumns() {
+            return mNumColumns;
+        }
+
+        @Override
+        public int getNumRows() {
+            return mNumRows;
+        }
+    }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
index 8c5bac1..1325706 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
@@ -21,7 +21,8 @@
 
 import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.model.RootInfo;
-import com.google.android.collect.Lists;
+
+import com.google.common.collect.Lists;
 
 import java.util.List;
 
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
index c2f1762..6a2e03a 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
@@ -36,8 +36,6 @@
 import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 
-import com.google.android.collect.Maps;
-
 import libcore.io.IoUtils;
 
 import java.io.File;
@@ -101,7 +99,7 @@
             });
         }
         // Create new roots.
-        mRoots = Maps.newHashMap();
+        mRoots = new HashMap<>();
         for (String rootId : rootIds) {
             final RootInfo rootInfo = new RootInfo(rootId, getSize(rootId));
             mRoots.put(rootId, rootInfo);
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java b/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
index 4ffe799..0553270 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
@@ -22,6 +22,7 @@
 
 @RunWith(Suite.class)
 @SuiteClasses({
+        BandSelectMatrixTest.class,
         MultiSelectManager_SelectionTest.class,
         MultiSelectManagerTest.class
 })
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 4eb6f88..ead0307 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -29,36 +29,19 @@
 import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
-
-import static android.os.BatteryManager.BATTERY_STATUS_FULL;
-import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
-import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
-import static android.os.BatteryManager.EXTRA_STATUS;
-import static android.os.BatteryManager.EXTRA_PLUGGED;
-import static android.os.BatteryManager.EXTRA_LEVEL;
-import static android.os.BatteryManager.EXTRA_HEALTH;
-import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
-
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
 import android.media.AudioManager;
 import android.os.BatteryManager;
 import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.IRemoteCallback;
 import android.os.Message;
-import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
-
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.TelephonyIntents;
-
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
-import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -71,6 +54,12 @@
 
 import com.google.android.collect.Lists;
 
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.widget.LockPatternUtils;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
@@ -79,6 +68,15 @@
 import java.util.List;
 import java.util.Map.Entry;
 
+import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
+import static android.os.BatteryManager.BATTERY_STATUS_FULL;
+import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.BatteryManager.EXTRA_HEALTH;
+import static android.os.BatteryManager.EXTRA_LEVEL;
+import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
+import static android.os.BatteryManager.EXTRA_PLUGGED;
+import static android.os.BatteryManager.EXTRA_STATUS;
+
 /**
  * Watches for updates that may be interesting to the keyguard, and provides
  * the up to date information as well as a registration for callbacks that care
@@ -138,6 +136,24 @@
     private static final int MSG_SCREEN_TURNED_ON = 331;
     private static final int MSG_SCREEN_TURNED_OFF = 332;
 
+    /** Fingerprint state: Not listening to fingerprint. */
+    private static final int FINGERPRINT_STATE_STOPPED = 0;
+
+    /** Fingerprint state: Listening. */
+    private static final int FINGERPRINT_STATE_RUNNING = 1;
+
+    /**
+     * Fingerprint state: Cancelling and waiting for the confirmation from FingerprintService to
+     * send us the confirmation that cancellation has happened.
+     */
+    private static final int FINGERPRINT_STATE_CANCELLING = 2;
+
+    /**
+     * Fingerprint state: During cancelling we got another request to start listening, so when we
+     * receive the cancellation done signal, we should start listening again.
+     */
+    private static final int FINGERPRINT_STATE_CANCELLING_RESTARTING = 3;
+
     private static KeyguardUpdateMonitor sInstance;
 
     private final Context mContext;
@@ -147,9 +163,14 @@
     private int mRingMode;
     private int mPhoneState;
     private boolean mKeyguardIsVisible;
+
+    /**
+     * If true, fingerprint was already authenticated and we don't need to start listening again
+     * until the Keyguard has been dismissed.
+     */
+    private boolean mFingerprintAlreadyAuthenticated;
     private boolean mBouncer;
     private boolean mBootCompleted;
-    private boolean mUserHasAuthenticatedSinceBoot;
 
     // Device provisioning state
     private boolean mDeviceProvisioned;
@@ -161,7 +182,8 @@
     private SparseIntArray mFailedAttempts = new SparseIntArray();
 
     /** Tracks whether strong authentication hasn't been used since quite some time per user. */
-    private ArraySet<Integer> mStrongAuthTimedOut = new ArraySet<>();
+    private ArraySet<Integer> mStrongAuthNotTimedOut = new ArraySet<>();
+    private final StrongAuthTracker mStrongAuthTracker = new StrongAuthTracker();
 
     private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
             mCallbacks = Lists.newArrayList();
@@ -174,8 +196,8 @@
     private SubscriptionManager mSubscriptionManager;
     private AlarmManager mAlarmManager;
     private List<SubscriptionInfo> mSubscriptionInfo;
-    private boolean mFingerprintDetectionRunning;
     private TrustManager mTrustManager;
+    private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED;
 
     private final Handler mHandler = new Handler() {
         @Override
@@ -269,8 +291,6 @@
 
     private static int sCurrentUser;
 
-    private int mFpWakeMode;
-
     public synchronized static void setCurrentUser(int currentUser) {
         sCurrentUser = currentUser;
     }
@@ -373,6 +393,11 @@
 
     private void onFingerprintAuthenticated(int userId) {
         mUserFingerprintAuthenticated.put(userId, true);
+
+        // If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a
+        // wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is
+        // fully gone.
+        mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -418,7 +443,7 @@
             }
             onFingerprintAuthenticated(userId);
         } finally {
-            setFingerprintRunningDetectionRunning(false);
+            setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
         }
     }
 
@@ -432,7 +457,13 @@
     }
 
     private void handleFingerprintError(int msgId, String errString) {
-        setFingerprintRunningDetectionRunning(false);
+        if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED
+                && mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) {
+            setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
+            startListeningForFingerprint();
+        } else {
+            setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
+        }
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -441,9 +472,15 @@
         }
     }
 
-    private void setFingerprintRunningDetectionRunning(boolean running) {
-        if (running != mFingerprintDetectionRunning) {
-            mFingerprintDetectionRunning = running;
+    private void setFingerprintRunningState(int fingerprintRunningState) {
+        boolean wasRunning = mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
+        boolean isRunning = fingerprintRunningState == FINGERPRINT_STATE_RUNNING;
+        mFingerprintRunningState = fingerprintRunningState;
+
+        // Clients of KeyguardUpdateMonitor don't care about the internal state about the
+        // asynchronousness of the cancel cycle. So only notify them if the actualy running state
+        // has changed.
+        if (wasRunning != isRunning) {
             notifyFingerprintRunningStateChanged();
         }
     }
@@ -452,7 +489,7 @@
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
-                cb.onFingerprintRunningStateChanged(mFingerprintDetectionRunning);
+                cb.onFingerprintRunningStateChanged(isFingerprintDetectionRunning());
             }
         }
     }
@@ -471,7 +508,7 @@
     }
 
     public boolean isFingerprintDetectionRunning() {
-        return mFingerprintDetectionRunning;
+        return mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
     }
 
     private boolean isTrustDisabled(int userId) {
@@ -503,7 +540,12 @@
     }
 
     public boolean isUnlockingWithFingerprintAllowed() {
-        return mUserHasAuthenticatedSinceBoot && !hasFingerprintUnlockTimedOut(sCurrentUser);
+        return mStrongAuthTracker.isUnlockingWithFingerprintAllowed()
+                && !hasFingerprintUnlockTimedOut(sCurrentUser);
+    }
+
+    public StrongAuthTracker getStrongAuthTracker() {
+        return mStrongAuthTracker;
     }
 
     /**
@@ -511,11 +553,11 @@
      *         while and thus can't unlock with fingerprint, false otherwise
      */
     public boolean hasFingerprintUnlockTimedOut(int userId) {
-        return mStrongAuthTimedOut.contains(userId);
+        return !mStrongAuthNotTimedOut.contains(userId);
     }
 
     public void reportSuccessfulStrongAuthUnlockAttempt() {
-        mStrongAuthTimedOut.remove(sCurrentUser);
+        mStrongAuthNotTimedOut.add(sCurrentUser);
         scheduleStrongAuthTimeout();
         if (mFpm != null) {
             byte[] token = null; /* TODO: pass real auth token once fp HAL supports it */
@@ -530,14 +572,14 @@
         PendingIntent sender = PendingIntent.getBroadcast(mContext,
                 sCurrentUser, intent, PendingIntent.FLAG_CANCEL_CURRENT);
         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, sender);
-        notifyStrongAuthTimedOutChanged(sCurrentUser);
+        notifyStrongAuthStateChanged(sCurrentUser);
     }
 
-    private void notifyStrongAuthTimedOutChanged(int userId) {
+    private void notifyStrongAuthStateChanged(int userId) {
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
-                cb.onStrongAuthTimeoutExpiredChanged(userId);
+                cb.onStrongAuthStateChanged(userId);
             }
         }
     }
@@ -632,8 +674,8 @@
         public void onReceive(Context context, Intent intent) {
             if (ACTION_STRONG_AUTH_TIMEOUT.equals(intent.getAction())) {
                 int userId = intent.getIntExtra(USER_ID, -1);
-                mStrongAuthTimedOut.add(userId);
-                notifyStrongAuthTimedOutChanged(userId);
+                mStrongAuthNotTimedOut.remove(userId);
+                notifyStrongAuthStateChanged(userId);
             }
         }
     };
@@ -791,6 +833,25 @@
         }
     }
 
+    public class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
+
+        public boolean isUnlockingWithFingerprintAllowed() {
+            int userId = getCurrentUser();
+            return isFingerprintAllowedForUser(userId);
+        }
+
+        public boolean hasUserAuthenticatedSinceBoot() {
+            int userId = getCurrentUser();
+            return (getStrongAuthForUser(userId)
+                    & STRONG_AUTH_REQUIRED_AFTER_BOOT) == 0;
+        }
+
+        @Override
+        public void onStrongAuthRequiredChanged(int userId) {
+            notifyStrongAuthStateChanged(userId);
+        }
+    }
+
     public static KeyguardUpdateMonitor getInstance(Context context) {
         if (sInstance == null) {
             sInstance = new KeyguardUpdateMonitor(context);
@@ -818,6 +879,7 @@
                 cb.onFinishedGoingToSleep(arg1);
             }
         }
+        mFingerprintAlreadyAuthenticated = false;
         updateFingerprintListeningState();
     }
 
@@ -936,6 +998,7 @@
                 PERMISSION_SELF, null /* handler */);
         mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
         mTrustManager.registerTrustListener(this);
+        new LockPatternUtils(context).registerStrongAuthTracker(mStrongAuthTracker);
 
         mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
         updateFingerprintListeningState();
@@ -943,29 +1006,33 @@
 
     private void updateFingerprintListeningState() {
         boolean shouldListenForFingerprint = shouldListenForFingerprint();
-        if (mFingerprintDetectionRunning && !shouldListenForFingerprint) {
+        if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) {
             stopListeningForFingerprint();
-        } else if (!mFingerprintDetectionRunning && shouldListenForFingerprint) {
+        } else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING
+                && shouldListenForFingerprint) {
             startListeningForFingerprint();
         }
     }
 
     private boolean shouldListenForFingerprint() {
-        return (mKeyguardIsVisible || !mDeviceInteractive) && !mSwitchingUser;
+        return (mKeyguardIsVisible || !mDeviceInteractive) && !mSwitchingUser
+                && !mFingerprintAlreadyAuthenticated;
     }
 
     private void startListeningForFingerprint() {
+        if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) {
+            setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING);
+            return;
+        }
         if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
         int userId = ActivityManager.getCurrentUser();
-        if (!mFingerprintDetectionRunning && isUnlockWithFingerprintPossible(userId)) {
-            mUserHasAuthenticatedSinceBoot = mTrustManager.hasUserAuthenticatedSinceBoot(
-                    ActivityManager.getCurrentUser());
+        if (isUnlockWithFingerprintPossible(userId)) {
             if (mFingerprintCancelSignal != null) {
                 mFingerprintCancelSignal.cancel();
             }
             mFingerprintCancelSignal = new CancellationSignal();
             mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);
-            setFingerprintRunningDetectionRunning(true);
+            setFingerprintRunningState(FINGERPRINT_STATE_RUNNING);
         }
     }
 
@@ -976,11 +1043,14 @@
 
     private void stopListeningForFingerprint() {
         if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
-        if (isFingerprintDetectionRunning()) {
+        if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING) {
             mFingerprintCancelSignal.cancel();
             mFingerprintCancelSignal = null;
+            setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING);
         }
-        setFingerprintRunningDetectionRunning(false);
+        if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) {
+            setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING);
+        }
     }
 
     private boolean isDeviceProvisionedInSettingsDb() {
@@ -1249,6 +1319,9 @@
                 cb.onKeyguardVisibilityChangedRaw(isShowing);
             }
         }
+        if (!isShowing) {
+            mFingerprintAlreadyAuthenticated = false;
+        }
         updateFingerprintListeningState();
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 7ca67b0..15ffe9f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -233,5 +233,5 @@
      * Called when the state that the user hasn't used strong authentication since quite some time
      * has changed.
      */
-    public void onStrongAuthTimeoutExpiredChanged(int userId) { }
+    public void onStrongAuthStateChanged(int userId) { }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 2353205..c430def 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -30,6 +30,11 @@
 import java.util.Date;
 import java.util.LinkedList;
 
+/**
+ * Loader for MTP document.
+ * At the first request, the loader returns only first NUM_INITIAL_ENTRIES. Then it launches
+ * background thread to load the rest documents and caches its result for next requests.
+ */
 class DocumentLoader {
     static final int NUM_INITIAL_ENTRIES = 10;
     static final int NUM_LOADING_ENTRIES = 20;
@@ -37,7 +42,7 @@
 
     private final MtpManager mMtpManager;
     private final ContentResolver mResolver;
-    private final LinkedList<LoaderTask> mTasks = new LinkedList<LoaderTask>();
+    private final TaskList mTaskList = new TaskList();
     private boolean mHasBackgroundThread = false;
 
     DocumentLoader(MtpManager mtpManager, ContentResolver resolver) {
@@ -56,7 +61,7 @@
 
     synchronized Cursor queryChildDocuments(String[] columnNames, Identifier parent)
             throws IOException {
-        LoaderTask task = findTask(parent);
+        LoaderTask task = mTaskList.findTask(parent);
         if (task == null) {
             int parentHandle = parent.mObjectHandle;
             // Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
@@ -70,11 +75,12 @@
                     mMtpManager,
                     parent.mDeviceId,
                     task.getUnloadedObjectHandles(NUM_INITIAL_ENTRIES)));
+        } else {
+            // Once remove the existing task in order to add it to the head of the list.
+            mTaskList.remove(task);
         }
 
-        // Move this task to the head of the list to prioritize it.
-        mTasks.remove(task);
-        mTasks.addFirst(task);
+        mTaskList.addFirst(task);
         if (!task.completed() && !mHasBackgroundThread) {
             mHasBackgroundThread = true;
             new BackgroundLoaderThread().start();
@@ -84,41 +90,11 @@
     }
 
     synchronized void clearCache(int deviceId) {
-        int i = 0;
-        while (i < mTasks.size()) {
-            if (mTasks.get(i).mIdentifier.mDeviceId == deviceId) {
-                mTasks.remove(i);
-            } else {
-                i++;
-            }
-        }
+        mTaskList.clearTaskForDevice(deviceId);
     }
 
     synchronized void clearCache() {
-        int i = 0;
-        while (i < mTasks.size()) {
-            if (mTasks.get(i).completed()) {
-                mTasks.remove(i);
-            } else {
-                i++;
-            }
-        }
-    }
-
-    private LoaderTask findTask(Identifier parent) {
-        for (int i = 0; i < mTasks.size(); i++) {
-            if (mTasks.get(i).mIdentifier.equals(parent))
-                return mTasks.get(i);
-        }
-        return null;
-    }
-
-    private LoaderTask findUncompletedTask() {
-        for (int i = 0; i < mTasks.size(); i++) {
-            if (!mTasks.get(i).completed())
-                return mTasks.get(i);
-        }
-        return null;
+        mTaskList.clearCompletedTask();
     }
 
     private class BackgroundLoaderThread extends Thread {
@@ -130,7 +106,7 @@
                 int deviceId;
                 int[] handles;
                 synchronized (DocumentLoader.this) {
-                    task = findUncompletedTask();
+                    task = mTaskList.findRunningTask();
                     if (task == null) {
                         mHasBackgroundThread = false;
                         return;
@@ -156,13 +132,53 @@
                             task.notify(mResolver);
                         }
                     } else {
-                        mTasks.remove(task);
+                        mTaskList.remove(task);
                     }
                 }
             }
         }
     }
 
+    private static class TaskList extends LinkedList<LoaderTask> {
+        LoaderTask findTask(Identifier parent) {
+            for (int i = 0; i < size(); i++) {
+                if (get(i).mIdentifier.equals(parent))
+                    return get(i);
+            }
+            return null;
+        }
+
+        LoaderTask findRunningTask() {
+            for (int i = 0; i < size(); i++) {
+                if (!get(i).completed())
+                    return get(i);
+            }
+            return null;
+        }
+
+        void clearTaskForDevice(int deviceId) {
+            int i = 0;
+            while (i < size()) {
+                if (get(i).mIdentifier.mDeviceId == deviceId) {
+                    remove(i);
+                } else {
+                    i++;
+                }
+            }
+        }
+
+        void clearCompletedTask() {
+            int i = 0;
+            while (i < size()) {
+                if (get(i).completed()) {
+                    remove(i);
+                } else {
+                    i++;
+                }
+            }
+        }
+    }
+
     private static class LoaderTask {
         final Identifier mIdentifier;
         final int[] mObjectHandles;
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
index 98775b3..7126694 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
@@ -32,6 +32,7 @@
     private final Date mDateModified;
     private final int mSize;
     private final int mThumbSize;
+    private final boolean mReadOnly;
 
     /**
      * Constructor for root document.
@@ -40,9 +41,10 @@
         this(DUMMY_HANDLE_FOR_ROOT,
              0x3001,  // Directory.
              root.mDescription,
-             null,  // Unknown,
+             null,    // Unknown name.
              (int) Math.min(root.mMaxCapacity - root.mFreeSpace, Integer.MAX_VALUE),
-             0);
+             0,       // Total size.
+             true);   // Writable.
     }
 
     MtpDocument(MtpObjectInfo objectInfo) {
@@ -51,7 +53,8 @@
              objectInfo.getName(),
              objectInfo.getDateModified() != 0 ? new Date(objectInfo.getDateModified()) : null,
              objectInfo.getCompressedSize(),
-             objectInfo.getThumbCompressedSize());
+             objectInfo.getThumbCompressedSize(),
+             objectInfo.getProtectionStatus() != 0);
     }
 
     MtpDocument(int objectHandle,
@@ -59,13 +62,15 @@
                 String name,
                 Date dateModified,
                 int size,
-                int thumbSize) {
+                int thumbSize,
+                boolean readOnly) {
         this.mObjectHandle = objectHandle;
         this.mFormat = format;
         this.mName = name;
         this.mDateModified = dateModified;
         this.mSize = size;
         this.mThumbSize = thumbSize;
+        this.mReadOnly = readOnly;
     }
 
     void addToCursor(Identifier rootIdentifier, MatrixCursor.RowBuilder builder) {
@@ -82,7 +87,7 @@
 
         builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId());
         builder.add(Document.COLUMN_DISPLAY_NAME, mName);
-        builder.add(Document.COLUMN_MIME_TYPE, getMimeType());
+        builder.add(Document.COLUMN_MIME_TYPE, formatTypeToMimeType(mFormat));
         builder.add(
                 Document.COLUMN_LAST_MODIFIED,
                 mDateModified != null ? mDateModified.getTime() : null);
@@ -90,9 +95,9 @@
         builder.add(Document.COLUMN_SIZE, mSize);
     }
 
-    private String getMimeType() {
+    static String formatTypeToMimeType(int format) {
         // TODO: Add complete list of mime types.
-        switch (mFormat) {
+        switch (format) {
             case 0x3001:
                 return DocumentsContract.Document.MIME_TYPE_DIR;
             case 0x3009:
@@ -100,7 +105,21 @@
             case 0x3801:
                 return "image/jpeg";
             default:
-                return "";
+                return "application/octet-stream";
+        }
+    }
+
+    static int mimeTypeToFormatType(String mimeType) {
+        // TODO: Add complete list of mime types.
+        switch (mimeType.toLowerCase()) {
+            case Document.MIME_TYPE_DIR:
+                return 0x3001;
+            case "audio/mp3":
+                return 0x3009;
+            case "image/jpeg":
+                return 0x3801;
+            default:
+                return 0x3000;  // Undefined object.
         }
     }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 61b9fc5..031cc07 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -96,7 +96,7 @@
             final Identifier rootIdentifier = new Identifier(root.mDeviceId, root.mStorageId);
             final MatrixCursor.RowBuilder builder = cursor.newRow();
             builder.add(Root.COLUMN_ROOT_ID, rootIdentifier.toRootId());
-            builder.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD);
+            builder.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
             builder.add(Root.COLUMN_TITLE, root.mDescription);
             builder.add(
                     Root.COLUMN_DOCUMENT_ID,
@@ -214,6 +214,24 @@
         mDocumentLoader.clearCache();
     }
 
+    @Override
+    public String createDocument(String parentDocumentId, String mimeType, String displayName)
+            throws FileNotFoundException {
+        try {
+            final Identifier parentId = Identifier.createFromDocumentId(parentDocumentId);
+            final int objectHandle = mMtpManager.createDocument(
+                    parentId.mDeviceId, parentId.mStorageId, parentId.mObjectHandle, mimeType,
+                    displayName);
+            final String documentId =  new Identifier(parentId.mDeviceId, parentId.mStorageId,
+                   objectHandle).toDocumentId();
+            notifyChildDocumentsChange(parentDocumentId);
+            return documentId;
+        } catch (IOException error) {
+            Log.e(TAG, error.getMessage());
+            throw new FileNotFoundException(error.getMessage());
+        }
+    }
+
     void openDevice(int deviceId) throws IOException {
         mMtpManager.openDevice(deviceId);
         mRootScanner.scanNow();
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 3afc173..27ba794 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -21,7 +21,10 @@
 import android.hardware.usb.UsbDeviceConnection;
 import android.hardware.usb.UsbManager;
 import android.mtp.MtpDevice;
+import android.mtp.MtpObjectInfo;
 import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract;
 import android.util.SparseArray;
 
 import java.io.FileNotFoundException;
@@ -134,6 +137,22 @@
         }
     }
 
+    synchronized int createDocument(int deviceId, int storageId, int parentObjectHandle,
+            String mimeType, String name) throws IOException {
+        final MtpDevice device = getDevice(deviceId);
+        final MtpObjectInfo objectInfo = new MtpObjectInfo.Builder()
+                .setName(name)
+                .setStorageId(storageId)
+                .setParent(parentObjectHandle)
+                .setFormat(MtpDocument.mimeTypeToFormatType(mimeType))
+                .build();
+        final MtpObjectInfo result = device.sendObjectInfo(objectInfo);
+        if (result == null) {
+            throw new IOException("Failed to create a document");
+        }
+        return result.getObjectHandle();
+    }
+
     synchronized int getParent(int deviceId, int objectHandle) throws IOException {
         final MtpDevice device = getDevice(deviceId);
         final int result = (int) device.getParent(objectHandle);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index 5504147..1e015bd 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
@@ -91,7 +91,8 @@
                     "file" + objectHandle,
                     new Date(),
                     1024,
-                    0 /* thumbnail size */));
+                    0 /* thumbnail size */,
+                    false /* not read only */));
         }
         manager.setObjectHandles(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, childDocuments);
     }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index c1da59f..f06e2ff 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -210,7 +210,8 @@
                 "image.jpg" /* display name */,
                 new Date(1422716400000L) /* modified date */,
                 1024 * 1024 * 5 /* file size */,
-                1024 * 50 /* thumbnail size */));
+                1024 * 50 /* thumbnail size */,
+                true /* read only */));
         final Cursor cursor = mProvider.queryDocument("0_1_2", null);
         assertEquals(1, cursor.getCount());
 
@@ -257,7 +258,8 @@
                 "image.jpg" /* display name */,
                 new Date(0) /* modified date */,
                 1024 * 1024 * 5 /* file size */,
-                1024 * 50 /* thumbnail size */));
+                1024 * 50 /* thumbnail size */,
+                true /* read only */));
 
         final Cursor cursor = mProvider.queryChildDocuments("0_0_0", null, null);
         assertEquals(1, cursor.getCount());
@@ -302,7 +304,8 @@
                 "image.jpg" /* display name */,
                 new Date(1422716400000L) /* modified date */,
                 1024 * 1024 * 5 /* file size */,
-                1024 * 50 /* thumbnail size */));
+                1024 * 50 /* thumbnail size */,
+                false /* not read only */));
         mMtpManager.setParent(0, 1, 2);
         mProvider.deleteDocument("0_0_1");
         assertEquals(1, mResolver.getChangeCount(
diff --git a/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java b/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
index 096a5c4..f52d755 100644
--- a/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
@@ -54,29 +54,7 @@
     public static boolean setWifiTethering(boolean enable, Context context) {
         final WifiManager wifiManager =
                 (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-        final ContentResolver cr = context.getContentResolver();
-        /**
-         * Disable Wifi if enabling tethering
-         */
-        int wifiState = wifiManager.getWifiState();
-        if (enable && ((wifiState == WifiManager.WIFI_STATE_ENABLING) ||
-                    (wifiState == WifiManager.WIFI_STATE_ENABLED))) {
-            wifiManager.setWifiEnabled(false);
-            Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 1);
-        }
-
-        boolean success = wifiManager.setWifiApEnabled(null, enable);
-        /**
-         *  If needed, restore Wifi on tether disable
-         */
-        if (!enable) {
-            int wifiSavedState = Settings.Global.getInt(cr, Settings.Global.WIFI_SAVED_STATE, 0);
-            if (wifiSavedState == 1) {
-                wifiManager.setWifiEnabled(true);
-                Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 0);
-            }
-        }
-        return success;
+        return wifiManager.setWifiApEnabled(null, enable);
     }
 
     public static boolean isWifiTetherEnabled(Context context) {
diff --git a/packages/SystemUI/res/anim/navbar_fade_in.xml b/packages/SystemUI/res/anim/navbar_fade_in.xml
index e3429e6..7051730 100644
--- a/packages/SystemUI/res/anim/navbar_fade_in.xml
+++ b/packages/SystemUI/res/anim/navbar_fade_in.xml
@@ -19,4 +19,5 @@
     android:fromAlpha="0.0"
     android:toAlpha="1.0"
     android:interpolator="@android:interpolator/linear_out_slow_in"
+    android:startDelay="32"
     android:duration="200"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 918d856..8b3f2d8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1140,4 +1140,9 @@
     <!-- Displayed when user launches an app that was uninstalled  [CHAR LIMIT=NONE] -->
     <string name="activity_not_found">Application is not installed on your device</string>
 
+    <!-- Name of setting to show clock seconds [CHAR LIMIT=40] -->
+    <string name="clock_seconds">Show clock seconds</string>
+    <!-- Description of setting to show clock seconds [CHAR LIMIT=NONE] -->
+    <string name="clock_seconds_desc">Show clock seconds in the status bar. May impact battery life.</string>
+
 </resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 3a41c3c..beb863c 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -72,10 +72,16 @@
         android:summary="@string/show_battery_percentage_summary"
         android:persistent="false" />
 
+    <com.android.systemui.tuner.TunerSwitch
+        android:key="clock_seconds"
+        android:title="@string/clock_seconds"
+        android:summary="@string/clock_seconds_desc" />
+
     <Preference
         android:key="demo_mode"
         android:title="@string/demo_mode" />
 
+    <!-- Warning, this goes last. -->
     <Preference
         android:summary="@string/tuner_persistent_warning"
         android:selectable="false" />
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 328ee35..36efead 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -256,6 +256,8 @@
 
     private void continuePulsing(int reason) {
         if (mHost.isPulsingBlocked()) {
+            mPulsing = false;
+            mWakeLock.release();
             return;
         }
         mHost.pulseWhileDozing(new DozeHost.PulseCallback() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index a28e188..12d5f36 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -532,7 +532,7 @@
             int currentUser = ActivityManager.getCurrentUser();
             if ((mUpdateMonitor.getUserTrustIsManaged(currentUser)
                     || mUpdateMonitor.isUnlockWithFingerprintPossible(currentUser))
-                    && !mTrustManager.hasUserAuthenticatedSinceBoot(currentUser)) {
+                    && !mUpdateMonitor.getStrongAuthTracker().hasUserAuthenticatedSinceBoot()) {
                 return KeyguardSecurityView.PROMPT_REASON_RESTART;
             } else if (mUpdateMonitor.isUnlockWithFingerprintPossible(currentUser)
                     && mUpdateMonitor.hasFingerprintUnlockTimedOut(currentUser)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 947c19c..00ac5f9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents.views;
 
+import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.TaskStackBuilder;
 import android.content.Context;
@@ -31,6 +32,8 @@
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.SparseArray;
+import android.view.AppTransitionAnimationSpec;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowInsets;
@@ -60,6 +63,8 @@
 
     private static final String TAG = "RecentsView";
 
+    private static final boolean ADD_HEADER_BITMAP = true;
+
     /** The RecentsView callbacks */
     public interface RecentsViewCallbacks {
         public void onTaskViewClicked();
@@ -443,62 +448,158 @@
         }
     }
 
-    private void postDrawHeaderThumbnailTransitionRunnable(final TaskView tv, final int offsetX,
-            final int offsetY, final TaskViewTransform transform,
+    private void postDrawHeaderThumbnailTransitionRunnable(final TaskStackView view,
+            final TaskView clickedView, final int offsetX, final int offsetY,
+            final float stackScroll,
             final ActivityOptions.OnAnimationStartedListener animStartedListener) {
         Runnable r = new Runnable() {
             @Override
             public void run() {
-                // Disable any focused state before we draw the header
-                if (tv.isFocusedTask()) {
-                    tv.unsetFocusedTask();
-                }
+                overrideDrawHeaderThumbnailTransition(view, clickedView, offsetX, offsetY,
+                        stackScroll, animStartedListener);
 
-                float scale = tv.getScaleX();
-                int fromHeaderWidth = (int) (tv.mHeaderView.getMeasuredWidth() * scale);
-                int fromHeaderHeight = (int) (tv.mHeaderView.getMeasuredHeight() * scale);
-
-                Bitmap b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
-                        Bitmap.Config.ARGB_8888);
-                if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
-                    b.eraseColor(0xFFff0000);
-                } else {
-                    Canvas c = new Canvas(b);
-                    c.scale(tv.getScaleX(), tv.getScaleY());
-                    tv.mHeaderView.draw(c);
-                    c.setBitmap(null);
-                }
-                b = b.createAshmemBitmap();
-                int[] pts = new int[2];
-                tv.getLocationOnScreen(pts);
-                try {
-                    WindowManagerGlobal.getWindowManagerService()
-                            .overridePendingAppTransitionAspectScaledThumb(b,
-                                    pts[0] + offsetX,
-                                    pts[1] + offsetY,
-                                    transform.rect.width(),
-                                    transform.rect.height(),
-                                    new IRemoteCallback.Stub() {
-                                        @Override
-                                        public void sendResult(Bundle data)
-                                                throws RemoteException {
-                                            post(new Runnable() {
-                                                @Override
-                                                public void run() {
-                                                    if (animStartedListener != null) {
-                                                        animStartedListener.onAnimationStarted();
-                                                    }
-                                                }
-                                            });
-                                        }
-                                    }, true);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Error overriding app transition", e);
-                }
             }
         };
+
         mCb.runAfterPause(r);
     }
+
+    private void overrideDrawHeaderThumbnailTransition(TaskStackView stackView,
+            TaskView clickedTask, int offsetX, int offsetY, float stackScroll,
+            final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+        List<AppTransitionAnimationSpec> specs = getAppTransitionAnimationSpecs(stackView,
+                clickedTask, offsetX, offsetY, stackScroll);
+        if (specs == null) {
+            return;
+        }
+
+        IRemoteCallback.Stub callback = new IRemoteCallback.Stub() {
+            @Override
+            public void sendResult(Bundle data) throws RemoteException {
+                post(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (animStartedListener != null) {
+                            animStartedListener.onAnimationStarted();
+                        }
+                    }
+                });
+            }
+        };
+
+        AppTransitionAnimationSpec[] specsArray =
+                new AppTransitionAnimationSpec[specs.size()];
+        try {
+            WindowManagerGlobal.getWindowManagerService().overridePendingAppTransitionMultiThumb(
+                    specs.toArray(specsArray), callback, true /* scaleUp */);
+
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error overriding app transition", e);
+        }
+    }
+
+    private List<AppTransitionAnimationSpec> getAppTransitionAnimationSpecs(TaskStackView stackView,
+            TaskView clickedTask, int offsetX, int offsetY, float stackScroll) {
+        final int targetStackId = clickedTask.getTask().key.stackId;
+        if (targetStackId != ActivityManager.FREEFORM_WORKSPACE_STACK_ID
+                && targetStackId != ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID) {
+            return null;
+        }
+        // If this is a full screen stack, the transition will be towards the single, full screen
+        // task. We only need the transition spec for this task.
+        List<AppTransitionAnimationSpec> specs = new ArrayList<>();
+        if (targetStackId == ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID) {
+            specs.add(createThumbnailHeaderAnimationSpec(
+                    stackView, offsetX, offsetY, stackScroll, clickedTask,
+                    clickedTask.getTask().key.id, ADD_HEADER_BITMAP));
+            return specs;
+        }
+        // This is a free form stack or full screen stack, so there will be multiple windows
+        // animating from thumbnails. We need transition animation specs for all of them.
+
+        // We will use top and bottom task views as a base for tasks, that aren't visible on the
+        // screen. This is necessary for cascade recents list, where some of the tasks might be
+        // hidden.
+        List<TaskView> taskViews = stackView.getTaskViews();
+        int childCount = taskViews.size();
+        TaskView topChild = taskViews.get(0);
+        TaskView bottomChild = taskViews.get(childCount - 1);
+        SparseArray<TaskView> taskViewsByTaskId = new SparseArray<>();
+        for (int i = 0; i < childCount; i++) {
+            TaskView taskView = taskViews.get(i);
+            taskViewsByTaskId.put(taskView.getTask().key.id, taskView);
+        }
+
+        TaskStack stack = stackView.getStack();
+        // We go through all tasks now and for each generate transition animation spec. If there is
+        // a view associated with a task, we use that view as a base for the animation. If there
+        // isn't, we use bottom or top view, depending on which one would be closer to the task
+        // view if it existed.
+        ArrayList<Task> tasks = stack.getTasks();
+        boolean passedClickedTask = false;
+        for (int i = 0, n = tasks.size(); i < n; i++) {
+            Task task = tasks.get(i);
+            TaskView taskView = taskViewsByTaskId.get(task.key.id);
+            if (taskView != null) {
+                specs.add(createThumbnailHeaderAnimationSpec(stackView, offsetX, offsetY,
+                        stackScroll, taskView, taskView.getTask().key.id, ADD_HEADER_BITMAP));
+                if (taskView == clickedTask) {
+                    passedClickedTask = true;
+                }
+            } else {
+                taskView = passedClickedTask ? bottomChild : topChild;
+                specs.add(createThumbnailHeaderAnimationSpec(stackView, offsetX, offsetY,
+                        stackScroll, taskView, task.key.id, !ADD_HEADER_BITMAP));
+            }
+        }
+
+        return specs;
+    }
+
+    private AppTransitionAnimationSpec createThumbnailHeaderAnimationSpec(TaskStackView stackView,
+            int offsetX, int offsetY, float stackScroll, TaskView tv, int taskId,
+            boolean addHeaderBitmap) {
+        // Disable any focused state before we draw the header
+        // Upfront the processing of the thumbnail
+        if (tv.isFocusedTask()) {
+            tv.unsetFocusedTask();
+        }
+        TaskViewTransform transform = new TaskViewTransform();
+        transform = stackView.getStackAlgorithm().getStackTransform(tv.mTask, stackScroll,
+                transform, null);
+
+        float scale = tv.getScaleX();
+        int fromHeaderWidth = (int) (tv.mHeaderView.getMeasuredWidth() * scale);
+        int fromHeaderHeight = (int) (tv.mHeaderView.getMeasuredHeight() * scale);
+
+        Bitmap b = null;
+        if (addHeaderBitmap) {
+            b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
+                    Bitmap.Config.ARGB_8888);
+
+            if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+                b.eraseColor(0xFFff0000);
+            } else {
+                Canvas c = new Canvas(b);
+                c.scale(tv.getScaleX(), tv.getScaleY());
+                tv.mHeaderView.draw(c);
+                c.setBitmap(null);
+
+            }
+            b = b.createAshmemBitmap();
+        }
+
+        int[] pts = new int[2];
+        tv.getLocationOnScreen(pts);
+
+        final int left = pts[0] + offsetX;
+        final int top = pts[1] + offsetY;
+        final Rect rect = new Rect(left, top, left + transform.rect.width(),
+                top + transform.rect.height());
+
+        return new AppTransitionAnimationSpec(taskId, b, rect);
+    }
+
     /**** TaskStackView.TaskStackCallbacks Implementation ****/
 
     @Override
@@ -521,12 +622,10 @@
             // and then offset to the expected transform rect, but bound this to just
             // outside the display rect (to ensure we don't animate from too far away)
             sourceView = stackView;
-            transform = stackView.getStackAlgorithm().getStackTransform(task, stackScroll, transform, null);
             offsetX = transform.rect.left;
             offsetY = mConfig.displayRect.height();
         } else {
             sourceView = tv.mThumbnailView;
-            transform = stackView.getStackAlgorithm().getStackTransform(task, stackScroll, transform, null);
         }
 
         // Compute the thumbnail to scale up from
@@ -553,10 +652,8 @@
                     }
                 };
             }
-            if (tv != null) {
-                postDrawHeaderThumbnailTransitionRunnable(tv, offsetX, offsetY, transform,
-                        animStartedListener);
-            }
+            postDrawHeaderThumbnailTransitionRunnable(stackView, tv, offsetX, offsetY, stackScroll,
+                    animStartedListener);
             if (mConfig.multiStackEnabled) {
                 opts = ActivityOptions.makeCustomAnimation(sourceView.getContext(),
                         R.anim.recents_from_unknown_enter,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index a55256d..3a96626 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -135,6 +135,7 @@
     protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
     protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024;
     protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025;
+    protected static final int MSG_SHOW_KEYBOARD_SHORTCUTS_MENU = 1026;
 
     protected static final boolean ENABLE_HEADS_UP = true;
     // scores above this threshold should be displayed in heads up mode.
@@ -1066,6 +1067,13 @@
         mHandler.sendEmptyMessage(msg);
     }
 
+    @Override
+    public void showKeyboardShortcutsMenu() {
+        int msg = MSG_SHOW_KEYBOARD_SHORTCUTS_MENU;
+        mHandler.removeMessages(msg);
+        mHandler.sendEmptyMessage(msg);
+    }
+
     /** Jumps to the next affiliated task in the group. */
     public void showNextAffiliatedTask() {
         int msg = MSG_SHOW_NEXT_AFFILIATED_TASK;
@@ -1143,6 +1151,10 @@
         }
     }
 
+    protected void showKeyboardShortcuts() {
+        Toast.makeText(mContext, "Show keyboard shortcuts screen", Toast.LENGTH_LONG).show();
+    }
+
     protected void cancelPreloadingRecents() {
         if (mRecents != null) {
             mRecents.cancelPreloadingRecents();
@@ -1253,6 +1265,9 @@
              case MSG_SHOW_PREV_AFFILIATED_TASK:
                   showRecentsPreviousAffiliatedTask();
                   break;
+             case MSG_SHOW_KEYBOARD_SHORTCUTS_MENU:
+                  showKeyboardShortcuts();
+                  break;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index a1b07b5..d0cd6cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -64,6 +64,7 @@
     private static final int MSG_APP_TRANSITION_STARTING    = 21 << MSG_SHIFT;
     private static final int MSG_ASSIST_DISCLOSURE          = 22 << MSG_SHIFT;
     private static final int MSG_START_ASSIST               = 23 << MSG_SHIFT;
+    private static final int MSG_SHOW_KEYBOARD_SHORTCUTS    = 24 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -98,6 +99,7 @@
         public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
         public void toggleRecentApps();
         public void preloadRecentApps();
+        public void showKeyboardShortcutsMenu();
         public void cancelPreloadRecentApps();
         public void setWindowState(int window, int state);
         public void buzzBeepBlinked();
@@ -224,6 +226,14 @@
         }
     }
 
+    @Override
+    public void showKeyboardShortcutsMenu() {
+        synchronized (mList) {
+            mHandler.removeMessages(MSG_SHOW_KEYBOARD_SHORTCUTS);
+            mHandler.obtainMessage(MSG_SHOW_KEYBOARD_SHORTCUTS).sendToTarget();
+        }
+    }
+
     public void setWindowState(int window, int state) {
         synchronized (mList) {
             // don't coalesce these
@@ -360,6 +370,9 @@
                 case MSG_CANCEL_PRELOAD_RECENT_APPS:
                     mCallbacks.cancelPreloadRecentApps();
                     break;
+                case MSG_SHOW_KEYBOARD_SHORTCUTS:
+                    mCallbacks.showKeyboardShortcutsMenu();
+                    break;
                 case MSG_SET_WINDOW_STATE:
                     mCallbacks.setWindowState(msg.arg1, msg.arg2);
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 4d3e57e..3ff69c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -104,13 +104,11 @@
      * Aborts pulsing immediately.
      */
     public void abortPulsing() {
-        mHandler.removeCallbacks(mPulseIn);
-        abortAnimations();
+        cancelPulsing();
         if (mDozing) {
             mScrimController.setDozeBehindAlpha(1f);
             mScrimController.setDozeInFrontAlpha(1f);
         }
-        mPulseCallback = null;
     }
 
     public void onScreenTurnedOn() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 4da9acd..579889d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -649,7 +649,7 @@
         }
 
         @Override
-        public void onStrongAuthTimeoutExpiredChanged(int userId) {
+        public void onStrongAuthStateChanged(int userId) {
             mLockIcon.update();
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 676f114..cbd23bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -54,7 +54,7 @@
     private KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
             new KeyguardUpdateMonitorCallback() {
                 @Override
-                public void onStrongAuthTimeoutExpiredChanged(int userId) {
+                public void onStrongAuthStateChanged(int userId) {
                     mBouncerPromptReason = mCallback.getBouncerPromptReason();
                 }
             };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
index d74c5b0..cb5c125 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
@@ -20,7 +20,6 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
-import android.app.AppGlobals;
 import android.content.BroadcastReceiver;
 import android.content.ClipData;
 import android.content.ClipDescription;
@@ -29,13 +28,10 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.ActivityInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.graphics.Rect;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.AttributeSet;
@@ -49,6 +45,7 @@
 import android.widget.LinearLayout;
 import android.widget.Toast;
 
+import com.android.internal.content.PackageMonitor;
 import com.android.systemui.R;
 
 import java.util.List;
@@ -75,6 +72,8 @@
     private final PackageManager mPackageManager;
     private final UserManager mUserManager;
     private final LayoutInflater mLayoutInflater;
+    private final AppPackageMonitor mAppPackageMonitor;
+
 
     // This view has two roles:
     // 1) If the drag started outside the pinned apps list, it is a placeholder icon with a null
@@ -106,6 +105,7 @@
         mPackageManager = context.getPackageManager();
         mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
         mLayoutInflater = LayoutInflater.from(context);
+        mAppPackageMonitor = new AppPackageMonitor();
 
         // Dragging an icon removes and adds back the dragged icon. Use the layout transitions to
         // trigger animation. By default all transitions animate, so turn off the unneeded ones.
@@ -121,6 +121,76 @@
         setLayoutTransition(transition);
     }
 
+    // Monitor that catches events like "app uninstalled".
+    private class AppPackageMonitor extends PackageMonitor {
+        @Override
+        public void onPackageRemoved(String packageName, int uid) {
+            postRemoveIfUnlauncheable(packageName, new UserHandle(getChangingUserId()));
+            super.onPackageRemoved(packageName, uid);
+        }
+
+        @Override
+        public void onPackageModified(String packageName) {
+            postRemoveIfUnlauncheable(packageName, new UserHandle(getChangingUserId()));
+            super.onPackageModified(packageName);
+        }
+
+        @Override
+        public void onPackagesAvailable(String[] packages) {
+            if (isReplacing()) {
+                UserHandle user = new UserHandle(getChangingUserId());
+
+                for (String packageName : packages) {
+                    postRemoveIfUnlauncheable(packageName, user);
+                }
+            }
+            super.onPackagesAvailable(packages);
+        }
+
+        @Override
+        public void onPackagesUnavailable(String[] packages) {
+            if (!isReplacing()) {
+                UserHandle user = new UserHandle(getChangingUserId());
+
+                for (String packageName : packages) {
+                    postRemoveIfUnlauncheable(packageName, user);
+                }
+            }
+            super.onPackagesUnavailable(packages);
+        }
+    }
+
+    private void postRemoveIfUnlauncheable(final String packageName, final UserHandle user) {
+        // This method doesn't necessarily get called in the main thread. Redirect the call into
+        // the main thread.
+        post(new Runnable() {
+            @Override
+            public void run() {
+                if (!isAttachedToWindow()) return;
+                removeIfUnlauncheable(packageName, user);
+            }
+        });
+    }
+
+    private void removeIfUnlauncheable(String packageName, UserHandle user) {
+        long appUserSerialNumber = mUserManager.getSerialNumberForUser(user);
+
+        // Remove icons for all apps that match a package that perhaps became unlauncheable.
+        for(int i = sAppsModel.getAppCount() - 1; i >= 0; --i) {
+            AppInfo appInfo = sAppsModel.getApp(i);
+            if (appInfo.getUserSerialNumber() != appUserSerialNumber) continue;
+
+            ComponentName appComponentName = appInfo.getComponentName();
+            if (!appComponentName.getPackageName().equals(packageName)) continue;
+
+            if (sAppsModel.buildAppLaunchIntent(appComponentName, user) != null) continue;
+
+            removeViewAt(i);
+            sAppsModel.removeApp(i);
+            sAppsModel.savePrefs();
+        }
+    }
+
     @Override
     protected void onAttachedToWindow() {
       super.onAttachedToWindow();
@@ -145,12 +215,15 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         mContext.registerReceiver(mBroadcastReceiver, filter);
+
+        mAppPackageMonitor.register(mContext, null, UserHandle.ALL, true);
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         mContext.unregisterReceiver(mBroadcastReceiver);
+        mAppPackageMonitor.unregister();
     }
 
     /**
@@ -470,7 +543,6 @@
             ComponentName component = appInfo.getComponentName();
 
             long appUserSerialNumber = appInfo.getUserSerialNumber();
-
             UserHandle appUser = mUserManager.getUserForSerialNumber(appUserSerialNumber);
             if (appUser == null) {
                 Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
@@ -478,7 +550,12 @@
                         " because its user doesn't exist.");
                 return;
             }
-            int appUserId = appUser.getIdentifier();
+
+            Intent launchIntent = sAppsModel.buildAppLaunchIntent(component, appUser);
+            if (launchIntent == null) {
+                Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+                return;
+            }
 
             // Play a scale-up animation while launching the activity.
             // TODO: Consider playing a different animation, or no animation, if the activity is
@@ -489,54 +566,9 @@
             ActivityOptions opts =
                     ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getWidth(), v.getHeight());
             Bundle optsBundle = opts.toBundle();
-
-            // Launch the activity. This code is based on LauncherAppsService.startActivityAsUser code.
-            Intent launchIntent = new Intent(Intent.ACTION_MAIN);
-            launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
             launchIntent.setSourceBounds(sourceBounds);
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            launchIntent.setPackage(component.getPackageName());
 
-            IPackageManager pm = AppGlobals.getPackageManager();
-            try {
-                ActivityInfo info = pm.getActivityInfo(component, 0, appUserId);
-                if (info == null) {
-                    Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
-                    Log.e(TAG, "Can't start activity " + component + " because it's not installed.");
-                    return;
-                }
-
-                if (!info.exported) {
-                    Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
-                    Log.e(TAG, "Can't start activity " + component + " because it doesn't have 'exported' attribute.");
-                    return;
-                }
-            } catch (RemoteException e) {
-                Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
-                Log.e(TAG, "Failed to get activity info for " + component, e);
-                return;
-            }
-
-            // Check that the component actually has Intent.CATEGORY_LAUCNCHER
-            // as calling startActivityAsUser ignores the category and just
-            // resolves based on the component if present.
-            List<ResolveInfo> apps = getContext().getPackageManager().queryIntentActivitiesAsUser(launchIntent,
-                    0 /* flags */, appUserId);
-            final int size = apps.size();
-            for (int i = 0; i < size; ++i) {
-                ActivityInfo activityInfo = apps.get(i).activityInfo;
-                if (activityInfo.packageName.equals(component.getPackageName()) &&
-                        activityInfo.name.equals(component.getClassName())) {
-                    // Found an activity with category launcher that matches
-                    // this component so ok to launch.
-                    launchIntent.setComponent(component);
-                    mContext.startActivityAsUser(launchIntent, optsBundle, appUser);
-                    return;
-                }
-            }
-
-            Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
-            Log.e(TAG, "Attempt to launch activity without category Intent.CATEGORY_LAUNCHER " + component);
+            mContext.startActivityAsUser(launchIntent, optsBundle, appUser);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
index b8764cf..c4c31fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
@@ -16,16 +16,23 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -94,6 +101,58 @@
         }
     }
 
+    @VisibleForTesting
+    protected IPackageManager getPackageManager() {
+        return AppGlobals.getPackageManager();
+    }
+
+    // Returns a launch intent for a given component, or null if the component is unlauncheable.
+    public Intent buildAppLaunchIntent(ComponentName component, UserHandle appUser) {
+        int appUserId = appUser.getIdentifier();
+
+        // This code is based on LauncherAppsService.startActivityAsUser code.
+        Intent launchIntent = new Intent(Intent.ACTION_MAIN);
+        launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        launchIntent.setPackage(component.getPackageName());
+
+        try {
+            ActivityInfo info = getPackageManager().getActivityInfo(component, 0, appUserId);
+            if (info == null) {
+                Log.e(TAG, "Activity " + component + " is not installed.");
+                return null;
+            }
+
+            if (!info.exported) {
+                Log.e(TAG, "Activity " + component + " doesn't have 'exported' attribute.");
+                return null;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to get activity info for " + component, e);
+            return null;
+        }
+
+        // Check that the component actually has Intent.CATEGORY_LAUNCHER
+        // as calling startActivityAsUser ignores the category and just
+        // resolves based on the component if present.
+        List<ResolveInfo> apps = mContext.getPackageManager().queryIntentActivitiesAsUser(launchIntent,
+                0 /* flags */, appUserId);
+        final int size = apps.size();
+        for (int i = 0; i < size; ++i) {
+            ActivityInfo activityInfo = apps.get(i).activityInfo;
+            if (activityInfo.packageName.equals(component.getPackageName()) &&
+                    activityInfo.name.equals(component.getClassName())) {
+                // Found an activity with category launcher that matches
+                // this component so ok to launch.
+                launchIntent.setComponent(component);
+                return launchIntent;
+            }
+        }
+
+        Log.e(TAG, "Activity doesn't have category Intent.CATEGORY_LAUNCHER " + component);
+        return null;
+    }
+
     /**
      * Reinitializes the model for a new user.
      */
@@ -199,6 +258,10 @@
 
     /** Loads the list of apps from SharedPreferences. */
     private void loadAppsFromPrefs() {
+        UserManager mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+
+        boolean hadUnlauncheableApps = false;
+
         int appCount = mPrefs.getInt(userPrefixed(APP_COUNT_PREF), -1);
         for (int i = 0; i < appCount; i++) {
             String prefValue = mPrefs.getString(prefNameForApp(i), null);
@@ -214,8 +277,15 @@
                 // Couldn't find the saved state. Just skip this item.
                 continue;
             }
-            mApps.add(new AppInfo(componentName, userSerialNumber));
+            UserHandle appUser = mUserManager.getUserForSerialNumber(userSerialNumber);
+            if (appUser != null && buildAppLaunchIntent(componentName, appUser) != null) {
+                mApps.add(new AppInfo(componentName, userSerialNumber));
+            } else {
+                hadUnlauncheableApps = true;
+            }
         }
+
+        if (hadUnlauncheableApps) savePrefs();
     }
 
     /** Adds the first few apps from the owner profile. Used for demo purposes. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 1649acb..7de7a7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -91,7 +91,8 @@
 
     private OnVerticalChangedListener mOnVerticalChangedListener;
     private boolean mIsLayoutRtl;
-    private boolean mLayoutTransitionsEnabled;
+    private boolean mLayoutTransitionsEnabled = true;
+    private boolean mWakeAndUnlocking;
 
     private class NavTransitionListener implements TransitionListener {
         private boolean mBackTransitioning;
@@ -371,13 +372,19 @@
         }
     }
 
-    public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
-        setUseFadingAnimations(wakeAndUnlocking);
-        setLayoutTransitionsEnabled(!wakeAndUnlocking);
+    public void setLayoutTransitionsEnabled(boolean enabled) {
+        mLayoutTransitionsEnabled = enabled;
+        updateLayoutTransitionsEnabled();
     }
 
-    private void setLayoutTransitionsEnabled(boolean enabled) {
-        mLayoutTransitionsEnabled = enabled;
+    public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
+        setUseFadingAnimations(wakeAndUnlocking);
+        mWakeAndUnlocking = wakeAndUnlocking;
+        updateLayoutTransitionsEnabled();
+    }
+
+    private void updateLayoutTransitionsEnabled() {
+        boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
         ViewGroup navButtons = (ViewGroup) mCurrentView.findViewById(R.id.nav_buttons);
         LayoutTransition lt = navButtons.getLayoutTransition();
         if (lt != null) {
@@ -469,7 +476,7 @@
         }
         mCurrentView = mRotatedViews[rot];
         mCurrentView.setVisibility(View.VISIBLE);
-        setLayoutTransitionsEnabled(mLayoutTransitionsEnabled);
+        updateLayoutTransitionsEnabled();
 
         getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index babca34..24ae47d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2425,4 +2425,9 @@
     protected boolean isPanelVisibleBecauseOfHeadsUp() {
         return mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway;
     }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return !mDozing;
+    }
 }
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 4476192..1cdbd97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -156,6 +156,7 @@
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
 import com.android.systemui.statusbar.stack.StackViewState;
 import com.android.systemui.volume.VolumeComponent;
 
@@ -233,7 +234,7 @@
 
     public static final int FADE_KEYGUARD_START_DELAY = 100;
     public static final int FADE_KEYGUARD_DURATION = 300;
-    public static final int FADE_KEYGUARD_DURATION_PULSING = 120;
+    public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
 
     /** Allow some time inbetween the long press for back and recents. */
     private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -3481,14 +3482,6 @@
                 .setStartDelay(0)
                 .setDuration(FADE_KEYGUARD_DURATION_PULSING)
                 .setInterpolator(ScrimController.KEYGUARD_FADE_OUT_INTERPOLATOR)
-                .withLayer()
-                .withEndAction(new Runnable() {
-                    @Override
-                    public void run() {
-                        mNotificationPanel.setAlpha(1f);
-                        hideKeyguard();
-                    }
-                })
                 .start();
     }
 
@@ -3526,11 +3519,24 @@
         setBarState(StatusBarState.SHADE);
         if (mLeaveOpenOnKeyguardHide) {
             mLeaveOpenOnKeyguardHide = false;
-            mNotificationPanel.animateToFullShade(calculateGoingToFullShadeDelay());
+            long delay = calculateGoingToFullShadeDelay();
+            mNotificationPanel.animateToFullShade(delay);
             if (mDraggedDownRow != null) {
                 mDraggedDownRow.setUserLocked(false);
                 mDraggedDownRow = null;
             }
+
+            // Disable layout transitions in navbar for this transition because the load is just
+            // too heavy for the CPU and GPU on any device.
+            if (mNavigationBarView != null) {
+                mNavigationBarView.setLayoutTransitionsEnabled(false);
+                mNavigationBarView.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        mNavigationBarView.setLayoutTransitionsEnabled(true);
+                    }
+                }, delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
+            }
         } else {
             instantCollapseNotificationPanel();
         }
@@ -3542,6 +3548,7 @@
             mQSPanel.refreshAllTiles();
         }
         mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+        mNotificationPanel.setAlpha(1f);
         return staying;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 5b009ee..cc6f396 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -22,7 +22,6 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Color;
-import android.util.Log;
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.animation.DecelerateInterpolator;
@@ -87,6 +86,7 @@
     private float mTopHeadsUpDragAmount;
     private View mDraggedHeadsUpView;
     private boolean mForceHideScrims;
+    private boolean mSkipFirstFrame;
 
     public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
             boolean scrimSrcEnabled) {
@@ -134,14 +134,20 @@
         scheduleUpdate();
     }
 
-    public void animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished) {
+    public void animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished,
+            boolean skipFirstFrame) {
         mWakeAndUnlocking = false;
         mAnimateKeyguardFadingOut = true;
         mDurationOverride = duration;
         mAnimationDelay = delay;
         mAnimateChange = true;
+        mSkipFirstFrame = skipFirstFrame;
         mOnAnimationFinished = onAnimationFinished;
         scheduleUpdate();
+
+        // No need to wait for the next frame to be drawn for this case - onPreDraw will execute
+        // the changes we just scheduled.
+        onPreDraw();
     }
 
     public void abortKeyguardFadingOut() {
@@ -339,6 +345,9 @@
             }
         });
         anim.start();
+        if (mSkipFirstFrame) {
+            anim.setCurrentPlayTime(16);
+        }
         scrim.setTag(TAG_KEY_ANIM, anim);
         scrim.setTag(TAG_KEY_ANIM_TARGET, target);
     }
@@ -354,6 +363,7 @@
         updateScrims();
         mDurationOverride = -1;
         mAnimationDelay = 0;
+        mSkipFirstFrame = false;
 
         // Make sure that we always call the listener even if we didn't start an animation.
         endAnimateKeyguardFadingOut(false /* force */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 448f16d..59ee5c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -74,7 +74,6 @@
     private boolean mLastOccluded;
     private boolean mLastBouncerShowing;
     private boolean mLastBouncerDismissible;
-    private boolean mLastDeferScrimFadeOut;
     private OnDismissAction mAfterKeyguardGoneAction;
     private boolean mDeviceWillWakeUp;
     private boolean mDeferScrimFadeOut;
@@ -184,7 +183,8 @@
         mScreenTurnedOn = true;
         if (mDeferScrimFadeOut) {
             mDeferScrimFadeOut = false;
-            animateScrimControllerKeyguardFadingOut(0, WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS);
+            animateScrimControllerKeyguardFadingOut(0, WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS,
+                    true /* skipFirstFrame */);
             updateStates();
         }
         mPhoneStatusBar.onScreenTurnedOn();
@@ -264,7 +264,8 @@
                     updateStates();
                     mScrimController.animateKeyguardFadingOut(
                             PhoneStatusBar.FADE_KEYGUARD_START_DELAY,
-                            PhoneStatusBar.FADE_KEYGUARD_DURATION, null);
+                            PhoneStatusBar.FADE_KEYGUARD_DURATION, null,
+                            false /* skipFirstFrame */);
                 }
             }, new Runnable() {
                 @Override
@@ -279,10 +280,15 @@
             if (mFingerprintUnlockController.getMode()
                     == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
                 mFingerprintUnlockController.startKeyguardFadingAway();
-                mPhoneStatusBar.setKeyguardFadingAway(startTime, 0, 250);
+                mPhoneStatusBar.setKeyguardFadingAway(startTime, 0, 240);
                 mStatusBarWindowManager.setKeyguardFadingAway(true);
                 mPhoneStatusBar.fadeKeyguardWhilePulsing();
-                animateScrimControllerKeyguardFadingOut(0, 250);
+                animateScrimControllerKeyguardFadingOut(0, 240, new Runnable() {
+                    @Override
+                    public void run() {
+                        mPhoneStatusBar.hideKeyguard();
+                    }
+                }, false /* skipFirstFrame */);
             } else {
                 mFingerprintUnlockController.startKeyguardFadingAway();
                 mPhoneStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
@@ -297,10 +303,12 @@
 
                             // Screen is already on, don't defer with fading out.
                             animateScrimControllerKeyguardFadingOut(0,
-                                    WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS);
+                                    WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS,
+                                    true /* skipFirstFrame */);
                         }
                     } else {
-                        animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration);
+                        animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration,
+                                false /* skipFirstFrame */);
                     }
                 } else {
                     mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
@@ -315,11 +323,21 @@
         }
     }
 
-    private void animateScrimControllerKeyguardFadingOut(long delay, long duration) {
+    private void animateScrimControllerKeyguardFadingOut(long delay, long duration,
+            boolean skipFirstFrame) {
+        animateScrimControllerKeyguardFadingOut(delay, duration, null /* endRunnable */,
+                skipFirstFrame);
+    }
+
+    private void animateScrimControllerKeyguardFadingOut(long delay, long duration,
+            final Runnable endRunnable, boolean skipFirstFrame) {
         Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "Fading out", 0);
         mScrimController.animateKeyguardFadingOut(delay, duration, new Runnable() {
             @Override
             public void run() {
+                if (endRunnable != null) {
+                    endRunnable.run();
+                }
                 mStatusBarWindowManager.setKeyguardFadingAway(false);
                 mPhoneStatusBar.finishKeyguardFadingAway();
                 mFingerprintUnlockController.finishKeyguardFadingAway();
@@ -327,7 +345,7 @@
                         ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
                 Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "Fading out", 0);
             }
-        });
+        }, skipFirstFrame);
     }
 
     private void executeAfterKeyguardGoneAction() {
@@ -401,7 +419,6 @@
         boolean occluded = mOccluded;
         boolean bouncerShowing = mBouncer.isShowing();
         boolean bouncerDismissible = !mBouncer.isFullscreenBouncer();
-        boolean deferScrimFadeOut = mDeferScrimFadeOut;
 
         if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing)
                 || mFirstUpdate) {
@@ -412,11 +429,8 @@
             }
         }
 
-        // Hide navigation bar on Keyguard but not on bouncer and also if we are deferring a scrim
-        // fade out, i.e. we are waiting for the screen to have turned on.
-        boolean navBarVisible = !deferScrimFadeOut && (!(showing && !occluded) || bouncerShowing);
-        boolean lastNavBarVisible = !mLastDeferScrimFadeOut && (!(mLastShowing && !mLastOccluded)
-                || mLastBouncerShowing);
+        boolean navBarVisible = (!(showing && !occluded) || bouncerShowing);
+        boolean lastNavBarVisible = (!(mLastShowing && !mLastOccluded) || mLastBouncerShowing);
         if (navBarVisible != lastNavBarVisible || mFirstUpdate) {
             if (mPhoneStatusBar.getNavigationBarView() != null) {
                 if (navBarVisible) {
@@ -451,7 +465,6 @@
         mFirstUpdate = false;
         mLastShowing = showing;
         mLastOccluded = occluded;
-        mLastDeferScrimFadeOut = deferScrimFadeOut;
         mLastBouncerShowing = bouncerShowing;
         mLastBouncerDismissible = bouncerDismissible;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 091db76..a91cd51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -145,7 +145,7 @@
         }
 
         @Override
-        public void onStrongAuthTimeoutExpiredChanged(int userId) {
+        public void onStrongAuthStateChanged(int userId) {
             update(false /* updateAlways */);
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 61986ad..896bd62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -23,6 +23,8 @@
 import android.content.IntentFilter;
 import android.content.res.TypedArray;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
@@ -30,22 +32,28 @@
 import android.text.style.CharacterStyle;
 import android.text.style.RelativeSizeSpan;
 import android.util.AttributeSet;
+import android.view.Display;
 import android.widget.TextView;
 
 import com.android.systemui.DemoMode;
 import com.android.systemui.R;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import libcore.icu.LocaleData;
 
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Locale;
 import java.util.TimeZone;
 
-import libcore.icu.LocaleData;
-
 /**
  * Digital clock for the status bar.
  */
-public class Clock extends TextView implements DemoMode {
+public class Clock extends TextView implements DemoMode, Tunable {
+
+    public static final String CLOCK_SECONDS = "clock_seconds";
+
     private boolean mAttached;
     private Calendar mCalendar;
     private String mClockFormatString;
@@ -57,6 +65,8 @@
     private static final int AM_PM_STYLE_GONE    = 2;
 
     private final int mAmPmStyle;
+    private boolean mShowSeconds;
+    private Handler mSecondsHandler;
 
     public Clock(Context context) {
         this(context, null);
@@ -77,6 +87,7 @@
         } finally {
             a.recycle();
         }
+        TunerService.get(context).addTunable(this, CLOCK_SECONDS);
     }
 
     @Override
@@ -105,6 +116,7 @@
 
         // Make sure we update to the current time
         updateClock();
+        updateShowSeconds();
     }
 
     @Override
@@ -143,6 +155,35 @@
         setText(getSmallTime());
     }
 
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        mShowSeconds = newValue != null && Integer.parseInt(newValue) != 0;
+        updateShowSeconds();
+    }
+
+    private void updateShowSeconds() {
+        if (mShowSeconds) {
+            // Wait until we have a display to start trying to show seconds.
+            if (mSecondsHandler == null && getDisplay() != null) {
+                mSecondsHandler = new Handler();
+                if (getDisplay().getState() == Display.STATE_ON) {
+                    mSecondsHandler.postAtTime(mSecondTick,
+                            SystemClock.uptimeMillis() / 1000 * 1000 + 1000);
+                }
+                IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
+                filter.addAction(Intent.ACTION_SCREEN_ON);
+                mContext.registerReceiver(mScreenReceiver, filter);
+            }
+        } else {
+            if (mSecondsHandler != null) {
+                mContext.unregisterReceiver(mScreenReceiver);
+                mSecondsHandler.removeCallbacks(mSecondTick);
+                mSecondsHandler = null;
+                updateClock();
+            }
+        }
+    }
+
     private final CharSequence getSmallTime() {
         Context context = getContext();
         boolean is24 = DateFormat.is24HourFormat(context, ActivityManager.getCurrentUser());
@@ -152,7 +193,9 @@
         final char MAGIC2 = '\uEF01';
 
         SimpleDateFormat sdf;
-        String format = is24 ? d.timeFormat_Hm : d.timeFormat_hm;
+        String format = mShowSeconds
+                ? is24 ? d.timeFormat_Hms : d.timeFormat_hms
+                : is24 ? d.timeFormat_Hm : d.timeFormat_hm;
         if (!format.equals(mClockFormatString)) {
             /*
              * Search for an unquoted "a" in the format string, so we can
@@ -244,5 +287,32 @@
             setText(getSmallTime());
         }
     }
+
+    private final BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+                if (mSecondsHandler != null) {
+                    mSecondsHandler.removeCallbacks(mSecondTick);
+                }
+            } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
+                if (mSecondsHandler != null) {
+                    mSecondsHandler.postAtTime(mSecondTick,
+                            SystemClock.uptimeMillis() / 1000 * 1000 + 1000);
+                }
+            }
+        }
+    };
+
+    private final Runnable mSecondTick = new Runnable() {
+        @Override
+        public void run() {
+            if (mCalendar != null) {
+                updateClock();
+            }
+            mSecondsHandler.postAtTime(this, SystemClock.uptimeMillis() / 1000 * 1000 + 1000);
+        }
+    };
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index e5b550e..dcb0d8d 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -38,6 +38,18 @@
     }
 
     @Override
+    protected void onAttachedToActivity() {
+        super.onAttachedToActivity();
+        TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+    }
+
+    @Override
+    protected void onDetachedFromActivity() {
+        TunerService.get(getContext()).removeTunable(this);
+        super.onDetachedFromActivity();
+    }
+
+    @Override
     public void onTuningChanged(String key, String newValue) {
         if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 71b5de5..96ad756 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -15,8 +15,6 @@
  */
 package com.android.systemui.tuner;
 
-import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING;
-
 import android.app.AlertDialog;
 import android.app.FragmentTransaction;
 import android.content.DialogInterface;
@@ -29,7 +27,6 @@
 import android.preference.Preference.OnPreferenceChangeListener;
 import android.preference.Preference.OnPreferenceClickListener;
 import android.preference.PreferenceFragment;
-import android.preference.PreferenceGroup;
 import android.preference.SwitchPreference;
 import android.provider.Settings;
 import android.provider.Settings.System;
@@ -39,8 +36,8 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.tuner.TunerService.Tunable;
+
+import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING;
 
 public class TunerFragment extends PreferenceFragment {
 
@@ -108,7 +105,6 @@
         getContext().getContentResolver().registerContentObserver(
                 System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
 
-        registerPrefs(getPreferenceScreen());
         MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, true);
     }
 
@@ -117,36 +113,9 @@
         super.onPause();
         getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
 
-        unregisterPrefs(getPreferenceScreen());
         MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, false);
     }
 
-    private void registerPrefs(PreferenceGroup group) {
-        TunerService tunerService = TunerService.get(getContext());
-        final int N = group.getPreferenceCount();
-        for (int i = 0; i < N; i++) {
-            Preference pref = group.getPreference(i);
-            if (pref instanceof StatusBarSwitch) {
-                tunerService.addTunable((Tunable) pref, StatusBarIconController.ICON_BLACKLIST);
-            } else if (pref instanceof PreferenceGroup) {
-                registerPrefs((PreferenceGroup) pref);
-            }
-        }
-    }
-
-    private void unregisterPrefs(PreferenceGroup group) {
-        TunerService tunerService = TunerService.get(getContext());
-        final int N = group.getPreferenceCount();
-        for (int i = 0; i < N; i++) {
-            Preference pref = group.getPreference(i);
-            if (pref instanceof Tunable) {
-                tunerService.removeTunable((Tunable) pref);
-            } else if (pref instanceof PreferenceGroup) {
-                registerPrefs((PreferenceGroup) pref);
-            }
-        }
-    }
-
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         menu.add(Menu.NONE, MENU_REMOVE, Menu.NONE, R.string.remove_from_settings);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
new file mode 100644
index 0000000..0740e08
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
@@ -0,0 +1,39 @@
+package com.android.systemui.tuner;
+
+import android.content.Context;
+import android.preference.SwitchPreference;
+import android.provider.Settings;
+import android.util.AttributeSet;
+
+import com.android.systemui.tuner.TunerService.Tunable;
+
+public class TunerSwitch extends SwitchPreference implements Tunable {
+
+    public TunerSwitch(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onAttachedToActivity() {
+        super.onAttachedToActivity();
+        TunerService.get(getContext()).addTunable(this, getKey());
+    }
+
+    @Override
+    protected void onDetachedFromActivity() {
+        TunerService.get(getContext()).removeTunable(this);
+        super.onDetachedFromActivity();
+    }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        setChecked(newValue != null && Integer.parseInt(newValue) != 0);
+    }
+
+    @Override
+    protected boolean persistBoolean(boolean value) {
+        Settings.Secure.putString(getContext().getContentResolver(), getKey(), value ? "1" : "0");
+        return true;
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java
index 62213ab..4d0e28b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java
@@ -16,21 +16,26 @@
 
 package com.android.systemui.statusbar.phone;
 
+import org.mockito.InOrder;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.test.AndroidTestCase;
@@ -45,6 +50,7 @@
 /** Tests for the data model for the navigation bar app icons. */
 public class NavigationBarAppsModelTest extends AndroidTestCase {
     private PackageManager mMockPackageManager;
+    private IPackageManager mMockIPackageManager;
     private SharedPreferences mMockPrefs;
     private SharedPreferences.Editor mMockEdit;
     private UserManager mMockUserManager;
@@ -61,6 +67,7 @@
 
         final Context context = mock(Context.class);
         mMockPackageManager = mock(PackageManager.class);
+        mMockIPackageManager = mock(IPackageManager.class);
         mMockPrefs = mock(SharedPreferences.class);
         mMockEdit = mock(SharedPreferences.Editor.class);
         mMockUserManager = mock(UserManager.class);
@@ -78,8 +85,71 @@
         when(mMockPrefs.edit()).thenReturn(mMockEdit);
 
         when(mMockUserManager.getSerialNumberForUser(new UserHandle(2))).thenReturn(22L);
+        when(mMockUserManager.getUserForSerialNumber(45L)).thenReturn(new UserHandle(4));
+        when(mMockUserManager.getUserForSerialNumber(239L)).thenReturn(new UserHandle(5));
 
-        mModel = new NavigationBarAppsModel(context);
+        mModel = new NavigationBarAppsModel(context) {
+            @Override
+            protected IPackageManager getPackageManager() {
+                return mMockIPackageManager;
+            }
+        };
+    }
+
+    /** Tests buildAppLaunchIntent(). */
+    public void testBuildAppLaunchIntent() {
+        ActivityInfo mockNonExportedActivityInfo = new ActivityInfo();
+        mockNonExportedActivityInfo.exported = false;
+        ActivityInfo mockExportedActivityInfo = new ActivityInfo();
+        mockExportedActivityInfo.exported = true;
+        try {
+            when(mMockIPackageManager.getActivityInfo(
+                    new ComponentName("package1", "class1"), 0, 4)).
+                    thenReturn(mockNonExportedActivityInfo);
+            when(mMockIPackageManager.getActivityInfo(
+                    new ComponentName("package2", "class2"), 0, 5)).
+                    thenThrow(new RemoteException());
+            when(mMockIPackageManager.getActivityInfo(
+                    new ComponentName("package3", "class3"), 0, 6)).
+                    thenReturn(mockExportedActivityInfo);
+            when(mMockIPackageManager.getActivityInfo(
+                    new ComponentName("package4", "class4"), 0, 7)).
+                    thenReturn(mockExportedActivityInfo);
+        } catch (RemoteException e) {
+            fail("RemoteException can't happen in the test, but it happened.");
+        }
+
+        // Assume some installed activities.
+        ActivityInfo ai0 = new ActivityInfo();
+        ai0.packageName = "package0";
+        ai0.name = "class0";
+        ActivityInfo ai1 = new ActivityInfo();
+        ai1.packageName = "package4";
+        ai1.name = "class4";
+        ResolveInfo ri0 = new ResolveInfo();
+        ri0.activityInfo = ai0;
+        ResolveInfo ri1 = new ResolveInfo();
+        ri1.activityInfo = ai1;
+        when(mMockPackageManager
+                .queryIntentActivitiesAsUser(any(Intent.class), eq(0), any(int.class)))
+                .thenReturn(Arrays.asList(ri0, ri1));
+
+        // Unlauncheable (for various reasons) apps.
+        assertEquals(null, mModel.buildAppLaunchIntent(
+                new ComponentName("package0", "class0"), new UserHandle(3)));
+        assertEquals(null, mModel.buildAppLaunchIntent(
+                new ComponentName("package1", "class1"), new UserHandle(4)));
+        assertEquals(null, mModel.buildAppLaunchIntent(
+                new ComponentName("package2", "class2"), new UserHandle(5)));
+        assertEquals(null, mModel.buildAppLaunchIntent(
+                new ComponentName("package3", "class3"), new UserHandle(6)));
+
+        // A launcheable app.
+        Intent intent = mModel.buildAppLaunchIntent(
+                new ComponentName("package4", "class4"), new UserHandle(7));
+        assertNotNull(intent);
+        assertEquals(new ComponentName("package4", "class4"), intent.getComponent());
+        assertEquals("package4", intent.getPackage());
     }
 
     /** Initializes the model from SharedPreferences for a few app activites. */
@@ -93,6 +163,39 @@
         when(mMockPrefs.getString("22|app_2", null)).thenReturn("package2/class2");
         when(mMockPrefs.getLong("22|app_user_2", -1)).thenReturn(239L);
 
+        ActivityInfo mockActivityInfo = new ActivityInfo();
+        mockActivityInfo.exported = true;
+        try {
+            when(mMockIPackageManager.getActivityInfo(
+                    new ComponentName("package0", "class0"), 0, 5)).thenReturn(mockActivityInfo);
+            when(mMockIPackageManager.getActivityInfo(
+                    new ComponentName("package1", "class1"), 0, 4)).thenReturn(mockActivityInfo);
+            when(mMockIPackageManager.getActivityInfo(
+                    new ComponentName("package2", "class2"), 0, 5)).thenReturn(mockActivityInfo);
+        } catch (RemoteException e) {
+            fail("RemoteException can't happen in the test, but it happened.");
+        }
+
+        // Assume some installed activities.
+        ActivityInfo ai0 = new ActivityInfo();
+        ai0.packageName = "package0";
+        ai0.name = "class0";
+        ActivityInfo ai1 = new ActivityInfo();
+        ai1.packageName = "package1";
+        ai1.name = "class1";
+        ActivityInfo ai2 = new ActivityInfo();
+        ai2.packageName = "package2";
+        ai2.name = "class2";
+        ResolveInfo ri0 = new ResolveInfo();
+        ri0.activityInfo = ai0;
+        ResolveInfo ri1 = new ResolveInfo();
+        ri1.activityInfo = ai1;
+        ResolveInfo ri2 = new ResolveInfo();
+        ri2.activityInfo = ai2;
+        when(mMockPackageManager
+                .queryIntentActivitiesAsUser(any(Intent.class), eq(0), any(int.class)))
+                .thenReturn(Arrays.asList(ri0, ri1, ri2));
+
         mModel.setCurrentUser(2);
     }
 
@@ -133,6 +236,15 @@
         assertEquals(22L, mModel.getApp(0).getUserSerialNumber());
         assertEquals("package2/class2", mModel.getApp(1).getComponentName().flattenToString());
         assertEquals(22L, mModel.getApp(1).getUserSerialNumber());
+        InOrder order = inOrder(mMockEdit);
+        order.verify(mMockEdit).apply();
+        order.verify(mMockEdit).putInt("22|app_count", 2);
+        order.verify(mMockEdit).putString("22|app_0", "package1/class1");
+        order.verify(mMockEdit).putLong("22|app_user_0", 22L);
+        order.verify(mMockEdit).putString("22|app_1", "package2/class2");
+        order.verify(mMockEdit).putLong("22|app_user_1", 22L);
+        order.verify(mMockEdit).apply();
+        verifyNoMoreInteractions(mMockEdit);
     }
 
     /** Tests initializing the model if one of the prefs is missing. */
@@ -145,11 +257,72 @@
         // But assume one pref is missing.
         when(mMockPrefs.getString("22|app_1", null)).thenReturn(null);
 
+        ActivityInfo mockActivityInfo = new ActivityInfo();
+        mockActivityInfo.exported = true;
+        try {
+            when(mMockIPackageManager.getActivityInfo(
+                    new ComponentName("package0", "class0"), 0, 5)).thenReturn(mockActivityInfo);
+        } catch (RemoteException e) {
+            fail("RemoteException can't happen in the test, but it happened.");
+        }
+
+        ActivityInfo ai0 = new ActivityInfo();
+        ai0.packageName = "package0";
+        ai0.name = "class0";
+        ResolveInfo ri0 = new ResolveInfo();
+        ri0.activityInfo = ai0;
+        when(mMockPackageManager
+                .queryIntentActivitiesAsUser(any(Intent.class), eq(0), any(int.class)))
+                .thenReturn(Arrays.asList(ri0));
+
         // Initializing the model should load from prefs and skip the missing one.
         mModel.setCurrentUser(2);
         assertEquals(1, mModel.getAppCount());
         assertEquals("package0/class0", mModel.getApp(0).getComponentName().flattenToString());
         assertEquals(239L, mModel.getApp(0).getUserSerialNumber());
+        verifyNoMoreInteractions(mMockEdit);
+    }
+
+    /** Tests initializing the model if one of the apps is unlauncheable. */
+    public void testInitializeWithUnlauncheableApp() {
+        // Assume two apps are nominally stored.
+        when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(2);
+        when(mMockPrefs.getString("22|app_0", null)).thenReturn("package0/class0");
+        when(mMockPrefs.getLong("22|app_user_0", -1)).thenReturn(239L);
+        when(mMockPrefs.getString("22|app_1", null)).thenReturn("package1/class1");
+        when(mMockPrefs.getLong("22|app_user_1", -1)).thenReturn(45L);
+
+        ActivityInfo mockActivityInfo = new ActivityInfo();
+        mockActivityInfo.exported = true;
+        try {
+            when(mMockIPackageManager.getActivityInfo(
+                    new ComponentName("package0", "class0"), 0, 5)).thenReturn(mockActivityInfo);
+        } catch (RemoteException e) {
+            fail("RemoteException can't happen in the test, but it happened.");
+        }
+
+        ActivityInfo ai0 = new ActivityInfo();
+        ai0.packageName = "package0";
+        ai0.name = "class0";
+        ResolveInfo ri0 = new ResolveInfo();
+        ri0.activityInfo = ai0;
+        when(mMockPackageManager
+                .queryIntentActivitiesAsUser(any(Intent.class), eq(0), any(int.class)))
+                .thenReturn(Arrays.asList(ri0));
+
+        // Initializing the model should load from prefs and skip the unlauncheable one.
+        mModel.setCurrentUser(2);
+        assertEquals(1, mModel.getAppCount());
+        assertEquals("package0/class0", mModel.getApp(0).getComponentName().flattenToString());
+        assertEquals(239L, mModel.getApp(0).getUserSerialNumber());
+
+        // Once an unlauncheable app is detected, the model should save all apps excluding the
+        // unlauncheable one.
+        verify(mMockEdit).putInt("22|app_count", 1);
+        verify(mMockEdit).putString("22|app_0", "package0/class0");
+        verify(mMockEdit).putLong("22|app_user_0", 239L);
+        verify(mMockEdit).apply();
+        verifyNoMoreInteractions(mMockEdit);
     }
 
     /** Tests saving the model to SharedPreferences. */
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 34aeb60..f724749 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -401,21 +401,40 @@
         public boolean isSystemRestore;
         public String[] filterSet;
 
-        // Restore a single package
+        /**
+         * Restore a single package; no kill after restore
+         */
         RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
-                long _token, PackageInfo _pkg, int _pmToken) {
+                long _token, PackageInfo _pkg) {
             transport = _transport;
             dirName = _dirName;
             observer = _obs;
             token = _token;
             pkgInfo = _pkg;
-            pmToken = _pmToken;
+            pmToken = 0;
             isSystemRestore = false;
             filterSet = null;
         }
 
-        // Restore everything possible.  This is the form that Setup Wizard or similar
-        // restore UXes use.
+        /**
+         * Restore at install: PM token needed, kill after restore
+         */
+        RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
+                long _token, String _pkgName, int _pmToken) {
+            transport = _transport;
+            dirName = _dirName;
+            observer = _obs;
+            token = _token;
+            pkgInfo = null;
+            pmToken = _pmToken;
+            isSystemRestore = false;
+            filterSet = new String[] { _pkgName };
+        }
+
+        /**
+         * Restore everything possible.  This is the form that Setup Wizard or similar
+         * restore UXes use.
+         */
         RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
                 long _token) {
             transport = _transport;
@@ -428,8 +447,10 @@
             filterSet = null;
         }
 
-        // Restore some set of packages.  Leave this one up to the caller to specify
-        // whether it's to be considered a system-level restore.
+        /**
+         * Restore some set of packages.  Leave this one up to the caller to specify
+         * whether it's to be considered a system-level restore.
+         */
         RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
                 long _token, String[] _filterSet, boolean _isSystemRestore) {
             transport = _transport;
@@ -9137,19 +9158,13 @@
                 // This can throw and so *must* happen before the wakelock is acquired
                 String dirName = transport.transportDirName();
 
-                // We can use a synthetic PackageInfo here because:
-                //   1. We know it's valid, since the Package Manager supplied the name
-                //   2. Only the packageName field will be used by the restore code
-                PackageInfo pkg = new PackageInfo();
-                pkg.packageName = packageName;
-
                 mWakelock.acquire();
                 if (MORE_DEBUG) {
                     Slog.d(TAG, "Restore at install of " + packageName);
                 }
                 Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
                 msg.obj = new RestoreParams(transport, dirName, null,
-                        restoreSet, pkg, token);
+                        restoreSet, packageName, token);
                 mBackupHandler.sendMessage(msg);
             } catch (RemoteException e) {
                 // Binding to the transport broke; back off and proceed with the installation.
@@ -9528,8 +9543,7 @@
                     Slog.d(TAG, "restorePackage() : " + packageName);
                 }
                 Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
-                msg.obj = new RestoreParams(mRestoreTransport, dirName,
-                        observer, token, app, 0);
+                msg.obj = new RestoreParams(mRestoreTransport, dirName, observer, token, app);
                 mBackupHandler.sendMessage(msg);
             } finally {
                 Binder.restoreCallingIdentity(oldId);
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 9427b61..7e4bcdc 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -18,6 +18,7 @@
 
 import android.app.admin.DevicePolicyManager;
 import android.app.backup.BackupManager;
+import android.app.trust.IStrongAuthTracker;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -70,6 +71,7 @@
     private final Context mContext;
 
     private final LockSettingsStorage mStorage;
+    private final LockSettingsStrongAuth mStrongAuth = new LockSettingsStrongAuth();
 
     private LockPatternUtils mLockPatternUtils;
     private boolean mFirstCallToVold;
@@ -93,6 +95,7 @@
         filter.addAction(Intent.ACTION_USER_ADDED);
         filter.addAction(Intent.ACTION_USER_STARTING);
         filter.addAction(Intent.ACTION_USER_REMOVED);
+        filter.addAction(Intent.ACTION_USER_PRESENT);
         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
 
         mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() {
@@ -122,6 +125,8 @@
             } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                 mStorage.prefetchUser(userHandle);
+            } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+                mStrongAuth.reportUnlock(getSendingUserId());
             } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                 if (userHandle > 0) {
@@ -713,6 +718,7 @@
 
     private void removeUser(int userId) {
         mStorage.removeUser(userId);
+        mStrongAuth.removeUser(userId);
 
         final KeyStore ks = KeyStore.getInstance();
         ks.onUserRemoved(userId);
@@ -727,6 +733,24 @@
         }
     }
 
+    @Override
+    public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
+        checkPasswordReadPermission(UserHandle.USER_ALL);
+        mStrongAuth.registerStrongAuthTracker(tracker);
+    }
+
+    @Override
+    public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
+        checkPasswordReadPermission(UserHandle.USER_ALL);
+        mStrongAuth.unregisterStrongAuthTracker(tracker);
+    }
+
+    @Override
+    public void requireStrongAuth(int strongAuthReason, int userId) {
+        checkWritePermission(userId);
+        mStrongAuth.requireStrongAuth(strongAuthReason, userId);
+    }
+
     private static final String[] VALID_SETTINGS = new String[] {
         LockPatternUtils.LOCKOUT_PERMANENT_KEY,
         LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
@@ -797,5 +821,4 @@
         Slog.e(TAG, "Unable to acquire GateKeeperService");
         return null;
     }
-
 }
diff --git a/services/core/java/com/android/server/LockSettingsStrongAuth.java b/services/core/java/com/android/server/LockSettingsStrongAuth.java
new file mode 100644
index 0000000..c023f4a
--- /dev/null
+++ b/services/core/java/com/android/server/LockSettingsStrongAuth.java
@@ -0,0 +1,167 @@
+/*
+ * 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.server;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
+
+import android.app.trust.IStrongAuthTracker;
+import android.os.DeadObjectException;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Slog;
+import android.util.SparseIntArray;
+
+import java.util.ArrayList;
+
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
+
+/**
+ * Keeps track of requests for strong authentication.
+ */
+public class LockSettingsStrongAuth {
+
+    private static final String TAG = "LockSettings";
+
+    private static final int MSG_REQUIRE_STRONG_AUTH = 1;
+    private static final int MSG_REGISTER_TRACKER = 2;
+    private static final int MSG_UNREGISTER_TRACKER = 3;
+    private static final int MSG_REMOVE_USER = 4;
+
+    private final ArrayList<IStrongAuthTracker> mStrongAuthTrackers = new ArrayList<>();
+    private final SparseIntArray mStrongAuthForUser = new SparseIntArray();
+
+    private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) {
+        for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
+            if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) {
+                return;
+            }
+        }
+        mStrongAuthTrackers.add(tracker);
+
+        for (int i = 0; i < mStrongAuthForUser.size(); i++) {
+            int key = mStrongAuthForUser.keyAt(i);
+            int value = mStrongAuthForUser.valueAt(i);
+            try {
+                tracker.onStrongAuthRequiredChanged(value, key);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Exception while adding StrongAuthTracker.", e);
+            }
+        }
+    }
+
+    private void handleRemoveStrongAuthTracker(IStrongAuthTracker tracker) {
+        for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
+            if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) {
+                mStrongAuthTrackers.remove(i);
+                return;
+            }
+        }
+    }
+
+    private void handleRequireStrongAuth(int strongAuthReason, int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            for (int i = 0; i < mStrongAuthForUser.size(); i++) {
+                int key = mStrongAuthForUser.keyAt(i);
+                handleRequireStrongAuthOneUser(strongAuthReason, key);
+            }
+        } else {
+            handleRequireStrongAuthOneUser(strongAuthReason, userId);
+        }
+    }
+
+    private void handleRequireStrongAuthOneUser(int strongAuthReason, int userId) {
+        int oldValue = mStrongAuthForUser.get(userId, LockPatternUtils.StrongAuthTracker.DEFAULT);
+        int newValue = strongAuthReason == STRONG_AUTH_NOT_REQUIRED
+                ? STRONG_AUTH_NOT_REQUIRED
+                : (oldValue | strongAuthReason);
+        if (oldValue != newValue) {
+            mStrongAuthForUser.put(userId, newValue);
+            notifyStrongAuthTrackers(newValue, userId);
+        }
+    }
+
+    private void handleRemoveUser(int userId) {
+        int index = mStrongAuthForUser.indexOfKey(userId);
+        if (index >= 0) {
+            mStrongAuthForUser.removeAt(index);
+            notifyStrongAuthTrackers(StrongAuthTracker.DEFAULT, userId);
+        }
+    }
+
+    private void notifyStrongAuthTrackers(int strongAuthReason, int userId) {
+        for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
+            try {
+                mStrongAuthTrackers.get(i).onStrongAuthRequiredChanged(strongAuthReason, userId);
+            } catch (DeadObjectException e) {
+                Slog.d(TAG, "Removing dead StrongAuthTracker.");
+                mStrongAuthTrackers.remove(i);
+                i--;
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Exception while notifying StrongAuthTracker.", e);
+            }
+        }
+    }
+
+    public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
+        mHandler.obtainMessage(MSG_REGISTER_TRACKER, tracker).sendToTarget();
+    }
+
+    public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
+        mHandler.obtainMessage(MSG_UNREGISTER_TRACKER, tracker).sendToTarget();
+    }
+
+    public void removeUser(int userId) {
+        mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
+    }
+
+    public void requireStrongAuth(int strongAuthReason, int userId) {
+        if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) {
+            mHandler.obtainMessage(MSG_REQUIRE_STRONG_AUTH, strongAuthReason,
+                    userId).sendToTarget();
+        } else {
+            throw new IllegalArgumentException(
+                    "userId must be an explicit user id or USER_ALL");
+        }
+    }
+
+    public void reportUnlock(int userId) {
+        requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId);
+    }
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_REGISTER_TRACKER:
+                    handleAddStrongAuthTracker((IStrongAuthTracker) msg.obj);
+                    break;
+                case MSG_UNREGISTER_TRACKER:
+                    handleRemoveStrongAuthTracker((IStrongAuthTracker) msg.obj);
+                    break;
+                case MSG_REQUIRE_STRONG_AUTH:
+                    handleRequireStrongAuth(msg.arg1, msg.arg2);
+                    break;
+                case MSG_REMOVE_USER:
+                    handleRemoveUser(msg.arg1);
+                    break;
+            }
+        }
+    };
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b6cd477..007b14b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -21,6 +21,7 @@
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.app.ActivityManager.DOCKED_STACK_ID;
 import static android.app.ActivityManager.HOME_STACK_ID;
+import static android.app.ActivityManager.INVALID_STACK_ID;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
 import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -9005,8 +9006,7 @@
         synchronized (this) {
             ActivityStack stack = ActivityRecord.getStackLocked(token);
             if (stack == null) {
-                throw new IllegalArgumentException(
-                        "getActivityStackId: No stack for token=" + token);
+                return INVALID_STACK_ID;
             }
             return stack.mStackId;
         }
@@ -9028,7 +9028,7 @@
                 }
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveActivityToStack: moving r=" + r
                         + " to stackId=" + stackId);
-                mStackSupervisor.moveTaskToStackLocked(r.task.taskId, stackId, ON_TOP, FORCE_FOCUS);
+                mStackSupervisor.moveTaskToStackLocked(r.task.taskId, stackId, ON_TOP, !FORCE_FOCUS);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -10906,7 +10906,7 @@
         synchronized (this) {
             buildAssistBundleLocked(pae, pae.result);
             mPendingAssistExtras.remove(pae);
-            mHandler.removeCallbacks(pae);
+            mUiHandler.removeCallbacks(pae);
         }
         return pae.extras;
     }
@@ -10994,7 +10994,7 @@
                 activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
                         requestType);
                 mPendingAssistExtras.add(pae);
-                mHandler.postDelayed(pae, timeout);
+                mUiHandler.postDelayed(pae, timeout);
             } catch (RemoteException e) {
                 Slog.w(TAG, "getAssistContextExtras failed: crash calling " + activity);
                 return null;
@@ -11051,7 +11051,7 @@
         synchronized (this) {
             buildAssistBundleLocked(pae, extras);
             boolean exists = mPendingAssistExtras.remove(pae);
-            mHandler.removeCallbacks(pae);
+            mUiHandler.removeCallbacks(pae);
             if (!exists) {
                 // Timed out.
                 return;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 356565f..fcd596f 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -248,6 +248,8 @@
     /** Run all ActivityStacks through this */
     final ActivityStackSupervisor mStackSupervisor;
 
+    private final LaunchingTaskPositioner mTaskPositioner;
+
     static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
     static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
     static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
@@ -363,6 +365,33 @@
         mStackId = activityContainer.mStackId;
         mCurrentUser = mService.mCurrentUserId;
         mRecentTasks = recentTasks;
+        mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID
+                ? new LaunchingTaskPositioner() : null;
+    }
+
+    void attachDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) {
+        mDisplayId = activityDisplay.mDisplayId;
+        mStacks = activityDisplay.mStacks;
+        mBounds = mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId, onTop);
+        mFullscreen = mBounds == null;
+        if (mTaskPositioner != null) {
+            mTaskPositioner.setDisplay(activityDisplay.mDisplay);
+            mTaskPositioner.configure(mBounds);
+        }
+    }
+
+    void detachDisplay() {
+        mDisplayId = Display.INVALID_DISPLAY;
+        mStacks = null;
+        if (mTaskPositioner != null) {
+            mTaskPositioner.reset();
+        }
+        mWindowManager.detachStack(mStackId);
+    }
+
+    void setBounds(Rect bounds) {
+        mBounds = mFullscreen ? null : new Rect(bounds);
+        mTaskPositioner.configure(bounds);
     }
 
     boolean okToShowLocked(ActivityRecord r) {
@@ -2223,7 +2252,7 @@
                                 + task, new RuntimeException("here").fillInStackTrace());
                         task.addActivityToTop(r);
                         r.putInHistory();
-                        addAppToken(r, task);
+                        addConfigOverride(r, task);
                         if (VALIDATE_TOKENS) {
                             validateAppTokensLocked();
                         }
@@ -2283,7 +2312,7 @@
                         : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
                 mNoAnimActivities.remove(r);
             }
-            addAppToken(r, task);
+            addConfigOverride(r, task);
             boolean doShow = true;
             if (newTask) {
                 // Even though this activity is starting fresh, we still need
@@ -2332,7 +2361,7 @@
         } else {
             // If this is the first activity, don't do any fancy animations,
             // because there is nothing for it to animate on top of.
-            addAppToken(r, task);
+            addConfigOverride(r, task);
             ActivityOptions.abort(options);
             options = null;
         }
@@ -4513,6 +4542,9 @@
             boolean toTop) {
         TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
                 voiceInteractor);
+        if (mTaskPositioner != null) {
+            mTaskPositioner.updateDefaultBounds(task, mTaskHistory);
+        }
         addTask(task, toTop, false);
         return task;
     }
@@ -4548,7 +4580,7 @@
         }
     }
 
-    void addAppToken(ActivityRecord r, TaskRecord task) {
+    void addConfigOverride(ActivityRecord r, TaskRecord task) {
         final Rect bounds = task.getLaunchBounds();
         final Configuration config =
                 mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 12b848b..c86056b 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2977,7 +2977,7 @@
 
             }
         }
-        stack.mBounds = stack.mFullscreen ? null : new Rect(bounds);
+        stack.setBounds(bounds);
 
         if (r != null) {
             final boolean updated = stack.ensureActivityConfigurationLocked(r, 0);
@@ -3017,7 +3017,6 @@
         // Place the task in the right stack if it isn't there already based on the requested
         // bounds.
         int stackId = task.stack.mStackId;
-        final boolean wasFrontStack = isFrontStack(task.stack);
         if (bounds == null && stackId != FULLSCREEN_WORKSPACE_STACK_ID) {
             stackId = FULLSCREEN_WORKSPACE_STACK_ID;
         } else if (bounds != null
@@ -3027,12 +3026,7 @@
         if (stackId != task.stack.mStackId) {
             final String reason = "resizeTask";
             final ActivityStack stack =
-                    moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, reason);
-            if (wasFrontStack) {
-                // Since the stack was previously in front,
-                // move the stack in which we are placing the task to the front.
-                stack.moveToFront(reason);
-            }
+                    moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason);
         }
 
         final Configuration overrideConfig = mWindowManager.resizeTask(task.taskId, bounds);
@@ -3112,7 +3106,7 @@
                 "Added restored task=" + task + " to stack=" + stack);
         final ArrayList<ActivityRecord> activities = task.mActivities;
         for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-            stack.addAppToken(activities.get(activityNdx), task);
+            stack.addConfigOverride(activities.get(activityNdx), task);
         }
         return true;
     }
@@ -3126,17 +3120,36 @@
      * @param task Task to move.
      * @param stackId Id of stack to move task to.
      * @param toTop True if the task should be placed at the top of the stack.
+     * @param forceFocus if focus should be moved to the new stack
      * @param reason Reason the task is been moved.
      * @return The stack the task was moved to.
      */
     private ActivityStack moveTaskToStackUncheckedLocked(
-            TaskRecord task, int stackId, boolean toTop, String reason) {
+            TaskRecord task, int stackId, boolean toTop, boolean forceFocus, String reason) {
+        final ActivityRecord r = task.getTopActivity();
+        final boolean wasFocused = isFrontStack(task.stack) && (topRunningActivityLocked() == r);
+        final boolean wasResumed = wasFocused && (task.stack.mResumedActivity == r);
+
         final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, toTop);
         mWindowManager.moveTaskToStack(task.taskId, stack.mStackId, toTop);
         if (task.stack != null) {
             task.stack.removeTask(task, reason, MOVING);
         }
         stack.addTask(task, toTop, MOVING);
+
+        // If the task had focus before (or we're requested to move focus),
+        // move focus to the new stack.
+        if (forceFocus || wasFocused) {
+            // If the task owns the last resumed activity, transfer that together,
+            // so that we don't resume the same activity again in the new stack.
+            // Apps may depend on onResume()/onPause() being called in pairs.
+            if (wasResumed) {
+                stack.mResumedActivity = r;
+            }
+            // move the stack in which we are placing the task to the front.
+            stack.moveToFront(reason);
+        }
+
         return stack;
     }
 
@@ -3147,10 +3160,8 @@
             return;
         }
         final String reason = "moveTaskToStack";
-        final ActivityRecord top = task.topRunningActivityLocked(null);
-        final boolean adjustFocus = forceFocus || mService.mFocusedActivity == top;
         final ActivityStack stack =
-                moveTaskToStackUncheckedLocked(task, stackId, toTop, reason);
+                moveTaskToStackUncheckedLocked(task, stackId, toTop, forceFocus, reason);
 
         // Make sure the task has the appropriate bounds/size for the stack it is in.
         if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
@@ -3162,14 +3173,6 @@
             resizeTaskLocked(task, stack.mBounds);
         }
 
-        if (top != null && adjustFocus) {
-            if (mService.mFocusedActivity != top) {
-                mService.setFocusedActivityLocked(top, reason);
-            } else {
-                setFocusedStack(top, reason);
-            }
-        }
-
         // The task might have already been running and its visibility needs to be synchronized with
         // the visibility of the stack / windows.
         ensureActivitiesVisibleLocked(null, 0);
@@ -4387,13 +4390,8 @@
             if (DEBUG_STACK) Slog.d(TAG_STACK, "attachToDisplayLocked: " + this
                     + " to display=" + activityDisplay + " onTop=" + onTop);
             mActivityDisplay = activityDisplay;
-            mStack.mDisplayId = activityDisplay.mDisplayId;
-            mStack.mStacks = activityDisplay.mStacks;
-
+            mStack.attachDisplay(activityDisplay, onTop);
             activityDisplay.attachActivities(mStack, onTop);
-            mStack.mBounds =
-                    mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId, onTop);
-            mStack.mFullscreen = mStack.mBounds == null;
         }
 
         @Override
@@ -4465,9 +4463,7 @@
             if (mActivityDisplay != null) {
                 mActivityDisplay.detachActivitiesLocked(mStack);
                 mActivityDisplay = null;
-                mStack.mDisplayId = -1;
-                mStack.mStacks = null;
-                mWindowManager.detachStack(mStackId);
+                mStack.detachDisplay();
             }
         }
 
diff --git a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
new file mode 100644
index 0000000..3005c86
--- /dev/null
+++ b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
@@ -0,0 +1,142 @@
+/*
+ * 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.server.am;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.view.Display;
+
+import java.util.ArrayList;
+
+/**
+ * Determines where a launching task should be positioned and sized on the display.
+ */
+class LaunchingTaskPositioner {
+    // Determines how close window frames/corners have to be to call them colliding.
+    private static final int BOUNDS_CONFLICT_MIN_DISTANCE = 4;
+
+    // Task will receive dimensions based on available dimensions divided by this.
+    private static final int WINDOW_SIZE_DENOMINATOR = 2;
+
+    // Task will receive margins based on available dimensions divided by this.
+    private static final int MARGIN_SIZE_DENOMINATOR = 4;
+
+    // If task bounds collide with some other, we will step and try again until we find a good
+    // position. The step will be determined by using dimensions and dividing it by this.
+    private static final int STEP_DENOMINATOR = 16;
+
+    // We always want to step by at least this.
+    private static final int MINIMAL_STEP = 1;
+
+    private boolean mDefaultStartBoundsConfigurationSet = false;
+    private final Rect mAvailableRect = new Rect();
+    private int mDefaultFreeformStartX;
+    private int mDefaultFreeformStartY;
+    private int mDefaultFreeformWidth;
+    private int mDefaultFreeformHeight;
+    private int mDefaultFreeformStepHorizontal;
+    private int mDefaultFreeformStepVertical;
+    private int mDisplayWidth;
+    private int mDisplayHeight;
+
+    void setDisplay(Display display) {
+        Point size = new Point();
+        display.getSize(size);
+        mDisplayWidth = size.x;
+        mDisplayHeight = size.y;
+    }
+
+    void configure(Rect stackBounds) {
+        if (stackBounds == null) {
+            mAvailableRect.set(0, 0, mDisplayWidth, mDisplayHeight);
+        } else {
+            mAvailableRect.set(stackBounds);
+        }
+        int width = mAvailableRect.width();
+        int height = mAvailableRect.height();
+        mDefaultFreeformStartX = mAvailableRect.left + width / MARGIN_SIZE_DENOMINATOR;
+        mDefaultFreeformStartY = mAvailableRect.top + height / MARGIN_SIZE_DENOMINATOR;
+        mDefaultFreeformWidth = width / WINDOW_SIZE_DENOMINATOR;
+        mDefaultFreeformHeight = height / WINDOW_SIZE_DENOMINATOR;
+        mDefaultFreeformStepHorizontal = Math.max(width / STEP_DENOMINATOR, MINIMAL_STEP);
+        mDefaultFreeformStepVertical = Math.max(height / STEP_DENOMINATOR, MINIMAL_STEP);
+        mDefaultStartBoundsConfigurationSet = true;
+    }
+
+    /**
+     * Tries to set task's bound in a way that it won't collide with any other task. By colliding
+     * we mean that two tasks have left-top corner very close to each other, so one might get
+     * obfuscated by the other one.
+     *
+     * @param task Task for which we want to find bounds that won't collide with other.
+     * @param tasks Existing tasks with which we don't want to collide.
+     */
+    void updateDefaultBounds(TaskRecord task, ArrayList<TaskRecord> tasks) {
+        if (!mDefaultStartBoundsConfigurationSet) {
+            return;
+        }
+        int startX = mDefaultFreeformStartX;
+        int startY = mDefaultFreeformStartY;
+        final int right = mAvailableRect.right;
+        final int bottom = mAvailableRect.bottom;
+        boolean restarted = false;
+        while (boundsConflict(startX, startY, tasks)) {
+            // Unfortunately there is already a task at that spot, so we need to look for some
+            // other place.
+            startX += mDefaultFreeformStepHorizontal;
+            startY += mDefaultFreeformStepVertical;
+            if (startX + mDefaultFreeformWidth > right
+                    || startY + mDefaultFreeformHeight > bottom) {
+                // We don't want the task to go outside of the display, because it won't look
+                // nice. Let's restart from the top instead, because there should be some space
+                // there.
+                startX = mAvailableRect.left;
+                startY = mAvailableRect.top;
+                restarted = true;
+            }
+            if (restarted
+                    && (startX > mDefaultFreeformStartX || startY > mDefaultFreeformStartY)) {
+                // If we restarted and crossed the initial position, let's not struggle anymore.
+                // The user already must have ton of tasks visible, we can just smack the new
+                // one in the center.
+                startX = mDefaultFreeformStartX;
+                startY = mDefaultFreeformStartY;
+                break;
+            }
+        }
+        task.setInitialBounds(startX, startY, startX + mDefaultFreeformWidth,
+                startY + mDefaultFreeformHeight);
+    }
+
+    private boolean boundsConflict(int startX, int startY, ArrayList<TaskRecord> tasks) {
+        for (int i = tasks.size() - 1; i >= 0; i--) {
+            TaskRecord task = tasks.get(i);
+            if (!task.mActivities.isEmpty()) {
+                Rect bounds = task.mBounds;
+                if (bounds != null && (Math.abs(bounds.left - startX) < BOUNDS_CONFLICT_MIN_DISTANCE
+                        || Math.abs(bounds.top - startY) < BOUNDS_CONFLICT_MIN_DISTANCE)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    void reset() {
+        mDefaultStartBoundsConfigurationSet = false;
+    }
+}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index ed935a1..ff412d1 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1217,6 +1217,14 @@
         return mLastNonFullscreenBounds;
     }
 
+    void setInitialBounds(int left, int top, int right, int bottom) {
+        if (mBounds == null) {
+            mBounds = new Rect();
+        }
+        mBounds.set(left, top, right, bottom);
+        mLastNonFullscreenBounds = mBounds;
+    }
+
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("userId="); pw.print(userId);
                 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 40956c1..19d8538 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -67,7 +67,7 @@
     public void addSystemProvider(SystemConditionProviderService service) {
         mSystemConditionProviders.add(service);
         service.attachBase(mContext);
-        registerService(service.asInterface(), service.getComponent(), UserHandle.USER_OWNER);
+        registerService(service.asInterface(), service.getComponent(), UserHandle.USER_SYSTEM);
     }
 
     public Iterable<SystemConditionProviderService> getSystemProviders() {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4351798..0c884f15 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -716,7 +716,7 @@
                             final IPackageManager pm = AppGlobals.getPackageManager();
                             final int enabled = pm.getApplicationEnabledSetting(pkgName,
                                     changeUserId != UserHandle.USER_ALL ? changeUserId :
-                                    UserHandle.USER_OWNER);
+                                    UserHandle.USER_SYSTEM);
                             if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                                     || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
                                 cancelNotifications = false;
@@ -1420,7 +1420,7 @@
                             if (!r.isSeen()) {
                                 if (DBG) Slog.d(TAG, "Marking notification as seen " + keys[i]);
                                 mAppUsageStats.reportEvent(r.sbn.getPackageName(),
-                                        userId == UserHandle.USER_ALL ? UserHandle.USER_OWNER
+                                        userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM
                                                 : userId,
                                         UsageEvents.Event.USER_INTERACTION);
                                 r.setSeen();
@@ -1701,7 +1701,8 @@
         @Override
         public byte[] getBackupPayload(int user) {
             if (DBG) Slog.d(TAG, "getBackupPayload u=" + user);
-            if (user != UserHandle.USER_OWNER) {
+            //TODO: http://b/22388012
+            if (user != UserHandle.USER_SYSTEM) {
                 Slog.w(TAG, "getBackupPayload: cannot backup policy for user " + user);
                 return null;
             }
@@ -1723,7 +1724,8 @@
                 Slog.w(TAG, "applyRestore: no payload to restore for user " + user);
                 return;
             }
-            if (user != UserHandle.USER_OWNER) {
+            //TODO: http://b/22388012
+            if (user != UserHandle.USER_SYSTEM) {
                 Slog.w(TAG, "applyRestore: cannot restore policy for user " + user);
                 return;
             }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index a089518..66381f5 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -148,7 +148,8 @@
                     if (!TextUtils.isEmpty(name)) {
                         if (forRestore) {
                             try {
-                                uid = pm.getPackageUid(name, UserHandle.USER_OWNER);
+                                //TODO: http://b/22388012
+                                uid = pm.getPackageUid(name, UserHandle.USER_SYSTEM);
                             } catch (NameNotFoundException e) {
                                 // noop
                             }
@@ -213,7 +214,8 @@
         final int N = mRecords.size();
         for (int i = 0; i < N; i++) {
             final Record r = mRecords.valueAt(i);
-            if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_OWNER) {
+            //TODO: http://b/22388012
+            if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) {
                 continue;
             }
             out.startTag(null, TAG_PACKAGE);
@@ -437,7 +439,8 @@
             final Record r = mRestoredWithoutUids.get(pkg);
             if (r != null) {
                 try {
-                    r.uid = pm.getPackageUid(r.pkg, UserHandle.USER_OWNER);
+                    //TODO: http://b/22388012
+                    r.uid = pm.getPackageUid(r.pkg, UserHandle.USER_SYSTEM);
                     mRestoredWithoutUids.remove(pkg);
                     mRecords.put(recordKey(r.pkg, r.uid), r);
                     updated = true;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 57d7758..edd274b 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -85,7 +85,7 @@
     private final Metrics mMetrics = new Metrics();
 
     private int mZenMode;
-    private int mUser = UserHandle.USER_OWNER;
+    private int mUser = UserHandle.USER_SYSTEM;
     private ZenModeConfig mConfig;
     private AudioManagerInternal mAudioManager;
     private boolean mEffectsSuppressed;
@@ -99,7 +99,7 @@
         appendDefaultScheduleRules(mDefaultConfig);
         appendDefaultEventRules(mDefaultConfig);
         mConfig = mDefaultConfig;
-        mConfigs.put(UserHandle.USER_OWNER, mConfig);
+        mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
         mSettingsObserver = new SettingsObserver(mHandler);
         mSettingsObserver.observe();
         mFiltering = new ZenModeFiltering(mContext);
@@ -152,7 +152,7 @@
     }
 
     public void onUserSwitched(int user) {
-        if (mUser == user || user < UserHandle.USER_OWNER) return;
+        if (mUser == user || user < UserHandle.USER_SYSTEM) return;
         mUser = user;
         if (DEBUG) Log.d(TAG, "onUserSwitched u=" + user);
         ZenModeConfig config = mConfigs.get(user);
@@ -165,7 +165,7 @@
     }
 
     public void onUserRemoved(int user) {
-        if (user < UserHandle.USER_OWNER) return;
+        if (user < UserHandle.USER_SYSTEM) return;
         if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user);
         mConfigs.remove(user);
     }
@@ -265,7 +265,8 @@
         final ZenModeConfig config = ZenModeConfig.readXml(parser, mConfigMigration);
         if (config != null) {
             if (forRestore) {
-                if (config.user != UserHandle.USER_OWNER) {
+                //TODO: http://b/22388012
+                if (config.user != UserHandle.USER_SYSTEM) {
                     return;
                 }
                 config.manualRule = null;  // don't restore the manual rule
@@ -285,7 +286,8 @@
     public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
         final int N = mConfigs.size();
         for (int i = 0; i < N; i++) {
-            if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_OWNER) {
+            //TODO: http://b/22388012
+            if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_SYSTEM) {
                 continue;
             }
             mConfigs.valueAt(i).writeXml(out);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 153bd3b..a559116 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -71,7 +71,7 @@
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDWR;
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
-import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER;
+import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
 import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
 import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
 import static com.android.internal.util.ArrayUtils.appendInt;
@@ -4949,18 +4949,25 @@
     private ResolveInfo createForwardingResolveInfo(IntentFilter filter,
             int sourceUserId, int targetUserId) {
         ResolveInfo forwardingResolveInfo = new ResolveInfo();
+        long ident = Binder.clearCallingIdentity();
+        boolean targetIsProfile;
+        try {
+            targetIsProfile = sUserManager.getUserInfo(targetUserId).isManagedProfile();
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
         String className;
-        if (targetUserId == UserHandle.USER_OWNER) {
-            className = FORWARD_INTENT_TO_USER_OWNER;
-        } else {
+        if (targetIsProfile) {
             className = FORWARD_INTENT_TO_MANAGED_PROFILE;
+        } else {
+            className = FORWARD_INTENT_TO_PARENT;
         }
         ComponentName forwardingActivityComponentName = new ComponentName(
                 mAndroidApplication.packageName, className);
         ActivityInfo forwardingActivityInfo = getActivityInfo(forwardingActivityComponentName, 0,
                 sourceUserId);
-        if (targetUserId == UserHandle.USER_OWNER) {
-            forwardingActivityInfo.showUserIcon = UserHandle.USER_OWNER;
+        if (!targetIsProfile) {
+            forwardingActivityInfo.showUserIcon = targetUserId;
             forwardingResolveInfo.noResourceId = true;
         }
         forwardingResolveInfo.activityInfo = forwardingActivityInfo;
@@ -6112,7 +6119,7 @@
             }
             // Give priority to system apps that listen for pre boot complete.
             Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
-            ArraySet<String> pkgNames = getPackageNamesForIntent(intent);
+            ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
             for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
                 PackageParser.Package pkg = it.next();
                 if (pkgNames.contains(pkg.packageName)) {
@@ -6147,7 +6154,7 @@
             }
             // Give priority to apps that listen for boot complete.
             intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
-            pkgNames = getPackageNamesForIntent(intent);
+            pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
             for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
                 PackageParser.Package pkg = it.next();
                 if (pkgNames.contains(pkg.packageName)) {
@@ -6218,11 +6225,11 @@
         }
     }
 
-    private ArraySet<String> getPackageNamesForIntent(Intent intent) {
+    private ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
         List<ResolveInfo> ris = null;
         try {
             ris = AppGlobals.getPackageManager().queryIntentReceivers(
-                    intent, null, 0, UserHandle.USER_OWNER);
+                    intent, null, 0, userId);
         } catch (RemoteException e) {
         }
         ArraySet<String> pkgNames = new ArraySet<String>();
@@ -11845,8 +11852,9 @@
         String pkgName = pkg.packageName;
 
         if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
+        // TODO: b/23350563
         final boolean dataDirExists = Environment
-                .getDataUserPackageDirectory(volumeUuid, UserHandle.USER_OWNER, pkgName).exists();
+                .getDataUserPackageDirectory(volumeUuid, UserHandle.USER_SYSTEM, pkgName).exists();
 
         synchronized(mPackages) {
             if (mSettings.mRenamedPackages.containsKey(pkgName)) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 08f0f09..4bfcb90 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -133,7 +133,7 @@
 
     private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
 
-    // Maximum number of managed profiles permitted is 1. This cannot be increased
+    // Maximum number of managed profiles permitted per user is 1. This cannot be increased
     // without first making sure that the rest of the framework is prepared for it.
     private static final int MAX_MANAGED_PROFILES = 1;
 
@@ -419,9 +419,10 @@
         return ui;
     }
 
+    /** Called by PackageManagerService */
     public boolean exists(int userId) {
         synchronized (mPackagesLock) {
-            return ArrayUtils.contains(mUserIds, userId);
+            return mUsers.get(userId) != null;
         }
     }
 
@@ -626,7 +627,7 @@
     }
 
     @Override
-    public boolean canAddMoreManagedProfiles() {
+    public boolean canAddMoreManagedProfiles(int userId) {
         checkManageUsersPermission("check if more managed profiles can be added.");
         if (ActivityManager.isLowRamDeviceStatic()) {
             return false;
@@ -635,10 +636,14 @@
                 PackageManager.FEATURE_MANAGED_USERS)) {
             return false;
         }
+        // Limit number of managed profiles that can be created
+        int managedProfilesCount = getProfiles(userId, true).size() - 1;
+        if (managedProfilesCount >= MAX_MANAGED_PROFILES) {
+            return false;
+        }
         synchronized(mPackagesLock) {
-            // Limit number of managed profiles that can be created
-            if (numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true)
-                    >= MAX_MANAGED_PROFILES) {
+            UserInfo userInfo = getUserInfoLocked(userId);
+            if (!userInfo.canHaveProfile()) {
                 return false;
             }
             int usersCount = getAliveUsersExcludingGuestsCountLocked();
@@ -1237,10 +1242,6 @@
     @Override
     public UserInfo createProfileForUser(String name, int flags, int userId) {
         checkManageUsersPermission("Only the system can create users");
-        if (userId != UserHandle.USER_OWNER) {
-            Slog.w(LOG_TAG, "Only user owner can have profiles");
-            return null;
-        }
         return createUserInternal(name, flags, userId);
     }
 
@@ -1272,7 +1273,8 @@
                         parent = getUserInfoLocked(parentId);
                         if (parent == null) return null;
                     }
-                    if (isManagedProfile && !canAddMoreManagedProfiles()) {
+                    if (isManagedProfile && !canAddMoreManagedProfiles(parentId)) {
+                        Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
                         return null;
                     }
                     if (!isGuest && !isManagedProfile && isUserLimitReachedLocked()) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 45bbf37..e0da33f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2835,6 +2835,12 @@
                     }
                 }
             }
+        } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
+            if (down) {
+                if (repeatCount == 0) {
+                    showKeyboardShortcutsMenu();
+                }
+            }
         } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
             if (down) {
                 if (repeatCount == 0) {
@@ -3255,6 +3261,17 @@
         }
     }
 
+    private void showKeyboardShortcutsMenu() {
+        try {
+            IStatusBarService statusbar = getStatusBarService();
+            if (statusbar != null) {
+                statusbar.showKeyboardShortcutsMenu();
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "RemoteException when showing keyboard shortcuts menu", e);
+        }
+    }
+
     private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
         try {
@@ -6113,6 +6130,7 @@
         }
         startedWakingUp();
         screenTurningOn(null);
+        screenTurnedOn();
     }
 
     ProgressDialog mBootMsgDialog = null;
diff --git a/services/core/java/com/android/server/policy/StatusBarController.java b/services/core/java/com/android/server/policy/StatusBarController.java
index d1b50da..da23f45 100644
--- a/services/core/java/com/android/server/policy/StatusBarController.java
+++ b/services/core/java/com/android/server/policy/StatusBarController.java
@@ -122,7 +122,7 @@
      *
      * @return the desired start time of the status bar transition, in uptime millis
      */
-    private long calculateStatusBarTransitionStartTime(Animation openAnimation,
+    private static long calculateStatusBarTransitionStartTime(Animation openAnimation,
             Animation closeAnimation) {
         if (openAnimation != null && closeAnimation != null) {
             TranslateAnimation openTranslateAnimation = findTranslateAnimation(openAnimation);
@@ -151,7 +151,7 @@
      *
      * @return the found animation, {@code null} otherwise
      */
-    private TranslateAnimation findTranslateAnimation(Animation animation) {
+    private static TranslateAnimation findTranslateAnimation(Animation animation) {
         if (animation instanceof TranslateAnimation) {
             return (TranslateAnimation) animation;
         } else if (animation instanceof AnimationSet) {
@@ -170,7 +170,7 @@
      * Binary searches for a {@code t} such that there exists a {@code -0.01 < eps < 0.01} for which
      * {@code interpolator(t + eps) > 0.99}.
      */
-    private float findAlmostThereFraction(Interpolator interpolator) {
+    private static float findAlmostThereFraction(Interpolator interpolator) {
         float val = 0.5f;
         float adj = 0.25f;
         while (adj >= 0.01f) {
diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index c71b48f..8b3c036 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -24,10 +24,12 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.text.TextUtils;
 import android.util.Slog;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * A special helper class used by the WindowManager
@@ -52,8 +54,9 @@
     private SensorManager mSensorManager;
     private boolean mEnabled;
     private int mRate;
+    private String mSensorType;
     private Sensor mSensor;
-    private SensorEventListenerImpl mSensorEventListener;
+    private OrientationJudge mOrientationJudge;
     private int mCurrentRotation = -1;
 
     private final Object mLock = new Object();
@@ -67,7 +70,7 @@
     public WindowOrientationListener(Context context, Handler handler) {
         this(context, handler, SensorManager.SENSOR_DELAY_UI);
     }
-    
+
     /**
      * Creates a new WindowOrientationListener.
      * 
@@ -84,11 +87,31 @@
         mHandler = handler;
         mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
         mRate = rate;
-        mSensor = mSensorManager.getDefaultSensor(USE_GRAVITY_SENSOR
-                ? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER);
-        if (mSensor != null) {
-            // Create listener only if sensors do exist
-            mSensorEventListener = new SensorEventListenerImpl(context);
+
+        mSensorType = context.getResources().getString(
+                com.android.internal.R.string.config_orientationSensorType);
+        if (!TextUtils.isEmpty(mSensorType)) {
+            List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+            final int N = sensors.size();
+            for (int i = 0; i < N; i++) {
+                Sensor sensor = sensors.get(i);
+                if (mSensorType.equals(sensor.getStringType())) {
+                    mSensor = sensor;
+                    break;
+                }
+            }
+            if (mSensor != null) {
+                mOrientationJudge = new OrientationSensorJudge();
+            }
+        }
+
+        if (mOrientationJudge == null) {
+            mSensor = mSensorManager.getDefaultSensor(USE_GRAVITY_SENSOR
+                    ? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER);
+            if (mSensor != null) {
+                // Create listener only if sensors do exist
+                mOrientationJudge = new AccelSensorJudge(context);
+            }
         }
     }
 
@@ -106,8 +129,8 @@
                 if (LOG) {
                     Slog.d(TAG, "WindowOrientationListener enabled");
                 }
-                mSensorEventListener.resetLocked();
-                mSensorManager.registerListener(mSensorEventListener, mSensor, mRate, mHandler);
+                mOrientationJudge.resetLocked();
+                mSensorManager.registerListener(mOrientationJudge, mSensor, mRate, mHandler);
                 mEnabled = true;
             }
         }
@@ -126,7 +149,7 @@
                 if (LOG) {
                     Slog.d(TAG, "WindowOrientationListener disabled");
                 }
-                mSensorManager.unregisterListener(mSensorEventListener);
+                mSensorManager.unregisterListener(mOrientationJudge);
                 mEnabled = false;
             }
         }
@@ -134,8 +157,8 @@
 
     public void onTouchStart() {
         synchronized (mLock) {
-            if (mSensorEventListener != null) {
-                mSensorEventListener.onTouchStartLocked();
+            if (mOrientationJudge != null) {
+                mOrientationJudge.onTouchStartLocked();
             }
         }
     }
@@ -144,8 +167,8 @@
         long whenElapsedNanos = SystemClock.elapsedRealtimeNanos();
 
         synchronized (mLock) {
-            if (mSensorEventListener != null) {
-                mSensorEventListener.onTouchEndLocked(whenElapsedNanos);
+            if (mOrientationJudge != null) {
+                mOrientationJudge.onTouchEndLocked(whenElapsedNanos);
             }
         }
     }
@@ -172,7 +195,7 @@
     public int getProposedRotation() {
         synchronized (mLock) {
             if (mEnabled) {
-                return mSensorEventListener.getProposedRotationLocked();
+                return mOrientationJudge.getProposedRotationLocked();
             }
             return -1;
         }
@@ -205,15 +228,77 @@
             prefix += "  ";
             pw.println(prefix + "mEnabled=" + mEnabled);
             pw.println(prefix + "mCurrentRotation=" + mCurrentRotation);
+            pw.println(prefix + "mSensorType=" + mSensorType);
             pw.println(prefix + "mSensor=" + mSensor);
             pw.println(prefix + "mRate=" + mRate);
 
-            if (mSensorEventListener != null) {
-                mSensorEventListener.dumpLocked(pw, prefix);
+            if (mOrientationJudge != null) {
+                mOrientationJudge.dumpLocked(pw, prefix);
             }
         }
     }
 
+    abstract class OrientationJudge implements SensorEventListener {
+        // Number of nanoseconds per millisecond.
+        protected static final long NANOS_PER_MS = 1000000;
+
+        // Number of milliseconds per nano second.
+        protected static final float MILLIS_PER_NANO = 0.000001f;
+
+        // The minimum amount of time that must have elapsed since the screen was last touched
+        // before the proposed rotation can change.
+        protected static final long PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS =
+                500 * NANOS_PER_MS;
+
+        /**
+         * Gets the proposed rotation.
+         *
+         * This method only returns a rotation if the orientation listener is certain
+         * of its proposal.  If the rotation is indeterminate, returns -1.
+         *
+         * Should only be called when holding WindowOrientationListener lock.
+         *
+         * @return The proposed rotation, or -1 if unknown.
+         */
+        public abstract int getProposedRotationLocked();
+
+        /**
+         * Notifies the orientation judge that the screen is being touched.
+         *
+         * Should only be called when holding WindowOrientationListener lock.
+         */
+        public abstract void onTouchStartLocked();
+
+        /**
+         * Notifies the orientation judge that the screen is no longer being touched.
+         *
+         * Should only be called when holding WindowOrientationListener lock.
+         *
+         * @param whenElapsedNanos Given in the elapsed realtime nanos time base.
+         */
+        public abstract void onTouchEndLocked(long whenElapsedNanos);
+
+        /**
+         * Resets the state of the judge.
+         *
+         * Should only be called when holding WindowOrientationListener lock.
+         */
+        public abstract void resetLocked();
+
+        /**
+         * Dumps internal state of the orientation judge.
+         *
+         * Should only be called when holding WindowOrientationListener lock.
+         */
+        public abstract void dumpLocked(PrintWriter pw, String prefix);
+
+        @Override
+        public abstract void onAccuracyChanged(Sensor sensor, int accuracy);
+
+        @Override
+        public abstract void onSensorChanged(SensorEvent event);
+    }
+
     /**
      * This class filters the raw accelerometer data and tries to detect actual changes in
      * orientation. This is a very ill-defined problem so there are a lot of tweakable parameters,
@@ -252,13 +337,10 @@
      * See http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization for
      * signal processing background.
      */
-    final class SensorEventListenerImpl implements SensorEventListener {
+    final class AccelSensorJudge extends OrientationJudge {
         // We work with all angles in degrees in this class.
         private static final float RADIANS_TO_DEGREES = (float) (180 / Math.PI);
 
-        // Number of nanoseconds per millisecond.
-        private static final long NANOS_PER_MS = 1000000;
-
         // Indices into SensorEvent.values for the accelerometer sensor.
         private static final int ACCELEROMETER_DATA_X = 0;
         private static final int ACCELEROMETER_DATA_Y = 1;
@@ -286,11 +368,6 @@
         private static final long PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS =
                 500 * NANOS_PER_MS;
 
-        // The minimum amount of time that must have elapsed since the screen was last touched
-        // before the proposed rotation can change.
-        private static final long PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS =
-                500 * NANOS_PER_MS;
-
         // If the tilt angle remains greater than the specified angle for a minimum of
         // the specified time, then the device is deemed to be lying flat
         // (just chillin' on a table).
@@ -434,7 +511,7 @@
         private long[] mTiltHistoryTimestampNanos = new long[TILT_HISTORY_SIZE];
         private int mTiltHistoryIndex;
 
-        public SensorEventListenerImpl(Context context) {
+        public AccelSensorJudge(Context context) {
             // Load tilt tolerance configuration.
             int[] tiltTolerance = context.getResources().getIntArray(
                     com.android.internal.R.array.config_autoRotationTiltTolerance);
@@ -455,11 +532,15 @@
             }
         }
 
+        @Override
         public int getProposedRotationLocked() {
             return mProposedRotation;
         }
 
+        @Override
         public void dumpLocked(PrintWriter pw, String prefix) {
+            pw.println(prefix + "AccelSensorJudge");
+            prefix += "  ";
             pw.println(prefix + "mProposedRotation=" + mProposedRotation);
             pw.println(prefix + "mPredictedRotation=" + mPredictedRotation);
             pw.println(prefix + "mLastFilteredX=" + mLastFilteredX);
@@ -689,6 +770,33 @@
             }
         }
 
+        @Override
+        public void onTouchStartLocked() {
+            mTouched = true;
+        }
+
+        @Override
+        public void onTouchEndLocked(long whenElapsedNanos) {
+            mTouched = false;
+            mTouchEndedTimestampNanos = whenElapsedNanos;
+        }
+
+        @Override
+        public void resetLocked() {
+            mLastFilteredTimestampNanos = Long.MIN_VALUE;
+            mProposedRotation = -1;
+            mFlatTimestampNanos = Long.MIN_VALUE;
+            mFlat = false;
+            mSwingTimestampNanos = Long.MIN_VALUE;
+            mSwinging = false;
+            mAccelerationTimestampNanos = Long.MIN_VALUE;
+            mAccelerating = false;
+            mOverhead = false;
+            clearPredictedRotationLocked();
+            clearTiltHistoryLocked();
+        }
+
+
         /**
          * Returns true if the tilt angle is acceptable for a given predicted rotation.
          */
@@ -787,20 +895,6 @@
             return true;
         }
 
-        private void resetLocked() {
-            mLastFilteredTimestampNanos = Long.MIN_VALUE;
-            mProposedRotation = -1;
-            mFlatTimestampNanos = Long.MIN_VALUE;
-            mFlat = false;
-            mSwingTimestampNanos = Long.MIN_VALUE;
-            mSwinging = false;
-            mAccelerationTimestampNanos = Long.MIN_VALUE;
-            mAccelerating = false;
-            mOverhead = false;
-            clearPredictedRotationLocked();
-            clearTiltHistoryLocked();
-        }
-
         private void clearPredictedRotationLocked() {
             mPredictedRotation = -1;
             mPredictedRotationTimestampNanos = Long.MIN_VALUE;
@@ -869,14 +963,138 @@
         private float remainingMS(long now, long until) {
             return now >= until ? 0 : (until - now) * 0.000001f;
         }
+    }
 
-        private void onTouchStartLocked() {
-            mTouched = true;
+    final class OrientationSensorJudge extends OrientationJudge {
+        private boolean mTouching;
+        private long mTouchEndedTimestampNanos = Long.MIN_VALUE;
+        private int mProposedRotation = -1;
+        private int mDesiredRotation = -1;
+        private boolean mRotationEvaluationScheduled;
+
+        @Override
+        public int getProposedRotationLocked() {
+            return mProposedRotation;
         }
 
-        private void onTouchEndLocked(long whenElapsedNanos) {
-            mTouched = false;
+        @Override
+        public void onTouchStartLocked() {
+            mTouching = true;
+        }
+
+        @Override
+        public void onTouchEndLocked(long whenElapsedNanos) {
+            mTouching = false;
             mTouchEndedTimestampNanos = whenElapsedNanos;
+            if (mDesiredRotation != mProposedRotation) {
+                final long now = SystemClock.elapsedRealtimeNanos();
+                scheduleRotationEvaluationIfNecessaryLocked(now);
+            }
         }
+
+
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            synchronized (mLock) {
+                mDesiredRotation = (int) event.values[0];
+                evaluateRotationChangeLocked();
+            }
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) { }
+
+        @Override
+        public void dumpLocked(PrintWriter pw, String prefix) {
+            pw.println(prefix + "OrientationSensorJudge");
+            prefix += "  ";
+            pw.println(prefix + "mDesiredRotation=" + mDesiredRotation);
+            pw.println(prefix + "mProposedRotation=" + mProposedRotation);
+            pw.println(prefix + "mTouching=" + mTouching);
+            pw.println(prefix + "mTouchEndedTimestampNanos=" + mTouchEndedTimestampNanos);
+        }
+
+        @Override
+        public void resetLocked() {
+            mProposedRotation = -1;
+            mDesiredRotation = -1;
+            mTouching = false;
+            mTouchEndedTimestampNanos = Long.MIN_VALUE;
+            unscheduleRotationEvaluationLocked();
+        }
+
+        public void evaluateRotationChangeLocked() {
+            unscheduleRotationEvaluationLocked();
+            if (mDesiredRotation == mProposedRotation) {
+                return;
+            }
+            final long now = SystemClock.elapsedRealtimeNanos();
+            if (isDesiredRotationAcceptableLocked(now)) {
+                mProposedRotation = mDesiredRotation;
+                onProposedRotationChanged(mProposedRotation);
+            } else {
+                scheduleRotationEvaluationIfNecessaryLocked(now);
+            }
+        }
+
+        private boolean isDesiredRotationAcceptableLocked(long now) {
+            if (mTouching) {
+                return false;
+            }
+            if (now < mTouchEndedTimestampNanos + PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS) {
+                return false;
+            }
+            return true;
+        }
+
+        private void scheduleRotationEvaluationIfNecessaryLocked(long now) {
+            if (mRotationEvaluationScheduled || mDesiredRotation == mProposedRotation) {
+                if (LOG) {
+                    Slog.d(TAG, "scheduleRotationEvaluationLocked: " +
+                            "ignoring, an evaluation is already scheduled or is unnecessary.");
+                }
+                return;
+            }
+            if (mTouching) {
+                if (LOG) {
+                    Slog.d(TAG, "scheduleRotationEvaluationLocked: " +
+                            "ignoring, user is still touching the screen.");
+                }
+                return;
+            }
+            long timeOfNextPossibleRotationNanos =
+                mTouchEndedTimestampNanos + PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS;
+            if (now >= timeOfNextPossibleRotationNanos) {
+                if (LOG) {
+                    Slog.d(TAG, "scheduleRotationEvaluationLocked: " +
+                            "ignoring, already past the next possible time of rotation.");
+                }
+                return;
+            }
+            // Use a delay instead of an absolute time since handlers are in uptime millis and we
+            // use elapsed realtime.
+            final long delayMs =
+                    (long) Math.ceil((timeOfNextPossibleRotationNanos - now) * MILLIS_PER_NANO);
+            mHandler.postDelayed(mRotationEvaluator, delayMs);
+            mRotationEvaluationScheduled = true;
+        }
+
+        private void unscheduleRotationEvaluationLocked() {
+            if (!mRotationEvaluationScheduled) {
+                return;
+            }
+            mHandler.removeCallbacks(mRotationEvaluator);
+            mRotationEvaluationScheduled = false;
+        }
+
+        private Runnable mRotationEvaluator = new Runnable() {
+            @Override
+            public void run() {
+                synchronized (mLock) {
+                    mRotationEvaluationScheduled = false;
+                    evaluateRotationChangeLocked();
+                }
+            }
+        };
     }
 }
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 5d52307..6b45941 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -32,6 +32,14 @@
     private static final String TAG = "KeyguardServiceDelegate";
     private static final boolean DEBUG = true;
 
+    private static final int SCREEN_STATE_OFF = 0;
+    private static final int SCREEN_STATE_TURNING_ON = 1;
+    private static final int SCREEN_STATE_ON = 2;
+
+    private static final int INTERACTIVE_STATE_SLEEP = 0;
+    private static final int INTERACTIVE_STATE_AWAKE = 1;
+    private static final int INTERACTIVE_STATE_GOING_TO_SLEEP = 2;
+
     protected KeyguardServiceWrapper mKeyguardService;
     private final Context mContext;
     private final View mScrim; // shown if keyguard crashes
@@ -61,6 +69,8 @@
         public int offReason;
         public int currentUser;
         public boolean bootCompleted;
+        public int screenState;
+        public int interactiveState;
     };
 
     public interface DrawnListener {
@@ -144,10 +154,17 @@
                 // If the system is ready, it means keyguard crashed and restarted.
                 mKeyguardService.onSystemReady();
                 // This is used to hide the scrim once keyguard displays.
-                mKeyguardService.onStartedWakingUp();
-                mKeyguardService.onScreenTurningOn(
-                        new KeyguardShowDelegate(mDrawnListenerWhenConnect));
-                mKeyguardService.onScreenTurnedOn();
+                if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
+                    mKeyguardService.onStartedWakingUp();
+                }
+                if (mKeyguardState.screenState == SCREEN_STATE_ON
+                        || mKeyguardState.screenState == SCREEN_STATE_TURNING_ON) {
+                    mKeyguardService.onScreenTurningOn(
+                            new KeyguardShowDelegate(mDrawnListenerWhenConnect));
+                }
+                if (mKeyguardState.screenState == SCREEN_STATE_ON) {
+                    mKeyguardService.onScreenTurnedOn();
+                }
                 mDrawnListenerWhenConnect = null;
             }
             if (mKeyguardState.bootCompleted) {
@@ -231,6 +248,7 @@
             if (DEBUG) Log.v(TAG, "onStartedWakingUp()");
             mKeyguardService.onStartedWakingUp();
         }
+        mKeyguardState.interactiveState = INTERACTIVE_STATE_AWAKE;
     }
 
     public void onScreenTurnedOff() {
@@ -238,6 +256,7 @@
             if (DEBUG) Log.v(TAG, "onScreenTurnedOff()");
             mKeyguardService.onScreenTurnedOff();
         }
+        mKeyguardState.screenState = SCREEN_STATE_OFF;
     }
 
     public void onScreenTurningOn(final DrawnListener drawnListener) {
@@ -252,6 +271,7 @@
             mDrawnListenerWhenConnect = drawnListener;
             showScrim();
         }
+        mKeyguardState.screenState = SCREEN_STATE_TURNING_ON;
     }
 
     public void onScreenTurnedOn() {
@@ -259,6 +279,7 @@
             if (DEBUG) Log.v(TAG, "onScreenTurnedOn()");
             mKeyguardService.onScreenTurnedOn();
         }
+        mKeyguardState.screenState = SCREEN_STATE_ON;
     }
 
     public void onStartedGoingToSleep(int why) {
@@ -266,12 +287,14 @@
             mKeyguardService.onStartedGoingToSleep(why);
         }
         mKeyguardState.offReason = why;
+        mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP;
     }
 
     public void onFinishedGoingToSleep(int why) {
         if (mKeyguardService != null) {
             mKeyguardService.onFinishedGoingToSleep(why);
         }
+        mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP;
     }
 
     public void setKeyguardEnabled(boolean enabled) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 2a817ea..8663254 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -494,6 +494,15 @@
     }
 
     @Override
+    public void showKeyboardShortcutsMenu() {
+        if (mBar != null) {
+            try {
+                mBar.showKeyboardShortcutsMenu();
+            } catch (RemoteException ex) {}
+        }
+    }
+
+    @Override
     public void setCurrentUser(int newUserId) {
         if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId);
         mCurrentUserId = newUserId;
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index b9e8851..f9d29ac 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -19,6 +19,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
 import com.android.server.SystemService;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -59,6 +60,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
 import android.util.Xml;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
@@ -96,16 +98,15 @@
     private static final int MSG_UNREGISTER_LISTENER = 2;
     private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
     private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
-    private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
     private static final int MSG_KEYGUARD_SHOWING_CHANGED = 6;
     private static final int MSG_START_USER = 7;
     private static final int MSG_CLEANUP_USER = 8;
     private static final int MSG_SWITCH_USER = 9;
 
-    private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
-    private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
+    private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<>();
+    private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>();
     private final Receiver mReceiver = new Receiver();
-    private final SparseBooleanArray mUserHasAuthenticated = new SparseBooleanArray();
+
     /* package */ final TrustArchive mArchive = new TrustArchive();
     private final Context mContext;
     private final LockPatternUtils mLockPatternUtils;
@@ -118,9 +119,6 @@
     @GuardedBy("mDeviceLockedForUser")
     private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
 
-    @GuardedBy("mUserHasAuthenticatedSinceBoot")
-    private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
-
     private boolean mTrustAgentsCanRun = false;
     private int mCurrentUser = UserHandle.USER_SYSTEM;
 
@@ -146,6 +144,7 @@
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
             mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
             mReceiver.register(mContext);
+            mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             mTrustAgentsCanRun = true;
             refreshAgentList(UserHandle.USER_ALL);
@@ -230,7 +229,7 @@
             if (!userInfo.supportsSwitchToByUser()) continue;
             if (!mActivityManager.isUserRunning(userInfo.id)) continue;
             if (!lockPatternUtils.isSecure(userInfo.id)) continue;
-            if (!getUserHasAuthenticated(userInfo.id)) continue;
+            if (!mStrongAuthTracker.isTrustAllowedForUser(userInfo.id)) continue;
             DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
             int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
             final boolean disableTrustAgents =
@@ -509,7 +508,7 @@
     // Agent dispatch and aggregation
 
     private boolean aggregateIsTrusted(int userId) {
-        if (!getUserHasAuthenticated(userId)) {
+        if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
             return false;
         }
         for (int i = 0; i < mActiveAgents.size(); i++) {
@@ -524,7 +523,7 @@
     }
 
     private boolean aggregateIsTrustManaged(int userId) {
-        if (!getUserHasAuthenticated(userId)) {
+        if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
             return false;
         }
         for (int i = 0; i < mActiveAgents.size(); i++) {
@@ -545,54 +544,6 @@
                 info.agent.onUnlockAttempt(successful);
             }
         }
-
-        if (successful) {
-            updateUserHasAuthenticated(userId);
-        }
-    }
-
-    private void updateUserHasAuthenticated(int userId) {
-        boolean changed = setUserHasAuthenticated(userId);
-        if (changed) {
-            refreshAgentList(userId);
-        }
-    }
-
-    private boolean getUserHasAuthenticated(int userId) {
-        return mUserHasAuthenticated.get(userId);
-    }
-
-    /**
-     * @return whether the value has changed
-     */
-    private boolean setUserHasAuthenticated(int userId) {
-        if (!mUserHasAuthenticated.get(userId)) {
-            mUserHasAuthenticated.put(userId, true);
-            synchronized (mUserHasAuthenticatedSinceBoot) {
-                mUserHasAuthenticatedSinceBoot.put(userId, true);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    private void clearUserHasAuthenticated(int userId) {
-        if (userId == UserHandle.USER_ALL) {
-            mUserHasAuthenticated.clear();
-        } else {
-            mUserHasAuthenticated.put(userId, false);
-        }
-    }
-
-    private boolean getUserHasAuthenticatedSinceBoot(int userId) {
-        synchronized (mUserHasAuthenticatedSinceBoot) {
-            return mUserHasAuthenticatedSinceBoot.get(userId);
-        }
-    }
-
-    private void requireCredentialEntry(int userId) {
-        clearUserHasAuthenticated(userId);
-        refreshAgentList(userId);
     }
 
     // Listeners
@@ -681,17 +632,6 @@
         }
 
         @Override
-        public void reportRequireCredentialEntry(int userId) throws RemoteException {
-            enforceReportPermission();
-            if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_SYSTEM) {
-                mHandler.obtainMessage(MSG_REQUIRE_CREDENTIAL_ENTRY, userId, 0).sendToTarget();
-            } else {
-                throw new IllegalArgumentException(
-                        "userId must be an explicit user id or USER_ALL");
-            }
-        }
-
-        @Override
         public void reportKeyguardShowingChanged() throws RemoteException {
             enforceReportPermission();
             // coalesce refresh messages.
@@ -734,18 +674,6 @@
             }
         }
 
-        @Override
-        public boolean hasUserAuthenticatedSinceBoot(int userId) throws RemoteException {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, null);
-            long token = Binder.clearCallingIdentity();
-            try {
-                return getUserHasAuthenticatedSinceBoot(userId);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
         private void enforceReportPermission() {
             mContext.enforceCallingOrSelfPermission(
                     Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
@@ -794,9 +722,8 @@
             fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
             fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
             fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
-            fout.print(", hasAuthenticated=" + dumpBool(getUserHasAuthenticated(user.id)));
-            fout.print(", hasAuthenticatedSinceBoot="
-                    + dumpBool(getUserHasAuthenticatedSinceBoot(user.id)));
+            fout.print(", strongAuthRequired=" + dumpHex(
+                    mStrongAuthTracker.getStrongAuthForUser(user.id)));
             fout.println();
             fout.println("   Enabled agents:");
             boolean duplicateSimpleNames = false;
@@ -831,6 +758,10 @@
         private String dumpBool(boolean b) {
             return b ? "1" : "0";
         }
+
+        private String dumpHex(int i) {
+            return "0x" + Integer.toHexString(i);
+        }
     };
 
     private int resolveProfileParent(int userId) {
@@ -864,9 +795,6 @@
                     // This is also called when the security mode of a user changes.
                     refreshDeviceLockedForUser(UserHandle.USER_ALL);
                     break;
-                case MSG_REQUIRE_CREDENTIAL_ENTRY:
-                    requireCredentialEntry(msg.arg1);
-                    break;
                 case MSG_KEYGUARD_SHOWING_CHANGED:
                     refreshDeviceLockedForUser(mCurrentUser);
                     break;
@@ -900,6 +828,13 @@
         }
     };
 
+    private final StrongAuthTracker mStrongAuthTracker = new StrongAuthTracker() {
+        @Override
+        public void onStrongAuthRequiredChanged(int userId) {
+            refreshAgentList(userId);
+        }
+    };
+
     private class Receiver extends BroadcastReceiver {
 
         @Override
@@ -908,8 +843,6 @@
             if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
                 refreshAgentList(getSendingUserId());
                 updateDevicePolicyFeatures();
-            } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
-                updateUserHasAuthenticated(getSendingUserId());
             } else if (Intent.ACTION_USER_ADDED.equals(action)) {
                 int userId = getUserId(intent);
                 if (userId > 0) {
@@ -918,7 +851,6 @@
             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
                 int userId = getUserId(intent);
                 if (userId > 0) {
-                    mUserHasAuthenticated.delete(userId);
                     synchronized (mUserIsTrusted) {
                         mUserIsTrusted.delete(userId);
                     }
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index dfdb29c..d1145d0 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -26,6 +26,8 @@
 import android.os.IBinder;
 import android.os.IRemoteCallback;
 import android.util.Slog;
+import android.util.SparseArray;
+import android.view.AppTransitionAnimationSpec;
 import android.view.WindowManager;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
@@ -153,22 +155,25 @@
     private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN = 3;
 
     private String mNextAppTransitionPackage;
-    private Bitmap mNextAppTransitionThumbnail;
     // Used for thumbnail transitions. True if we're scaling up, false if scaling down
     private boolean mNextAppTransitionScaleUp;
     private IRemoteCallback mNextAppTransitionCallback;
     private int mNextAppTransitionEnter;
     private int mNextAppTransitionExit;
     private int mNextAppTransitionInPlace;
-    private int mNextAppTransitionStartX;
-    private int mNextAppTransitionStartY;
-    private int mNextAppTransitionStartWidth;
-    private int mNextAppTransitionStartHeight;
+
+    // Keyed by task id.
+    private final SparseArray<AppTransitionAnimationSpec> mNextAppTransitionAnimationsSpecs
+            = new SparseArray<>();
+    private AppTransitionAnimationSpec mDefaultNextAppTransitionAnimationSpec;
+
     private Rect mNextAppTransitionInsets = new Rect();
 
     private Rect mTmpFromClipRect = new Rect();
     private Rect mTmpToClipRect = new Rect();
 
+    private final Rect mTmpStartRect = new Rect();
+
     private final static int APP_STATE_IDLE = 0;
     private final static int APP_STATE_READY = 1;
     private final static int APP_STATE_RUNNING = 2;
@@ -276,8 +281,9 @@
         mAppTransitionState = APP_STATE_TIMEOUT;
     }
 
-    Bitmap getNextAppTransitionThumbnail() {
-        return mNextAppTransitionThumbnail;
+    Bitmap getAppTransitionThumbnailHeader(int taskId) {
+        AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId);
+        return spec != null ? spec.bitmap : null;
     }
 
     /** Returns whether the next thumbnail transition is aspect scaled up. */
@@ -291,14 +297,6 @@
         return mNextAppTransitionScaleUp;
     }
 
-    int getStartingX() {
-        return mNextAppTransitionStartX;
-    }
-
-    int getStartingY() {
-        return mNextAppTransitionStartY;
-    }
-
     boolean prepare() {
         if (!isRunning()) {
             mAppTransitionState = APP_STATE_IDLE;
@@ -321,7 +319,7 @@
     void clear() {
         mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
         mNextAppTransitionPackage = null;
-        mNextAppTransitionThumbnail = null;
+        mNextAppTransitionAnimationsSpecs.clear();
     }
 
     void freeze() {
@@ -459,16 +457,17 @@
         return -startPos / denom;
     }
 
-    private Animation createScaleUpAnimationLocked(int transit, boolean enter,
-                                                   int appWidth, int appHeight) {
+    private Animation createScaleUpAnimationLocked(
+            int transit, boolean enter, int appWidth, int appHeight) {
         Animation a = null;
+        getDefaultNextAppTransitionStartRect(mTmpStartRect);
         if (enter) {
             // Entering app zooms out from the center of the initial rect.
-            float scaleW = mNextAppTransitionStartWidth / (float) appWidth;
-            float scaleH = mNextAppTransitionStartHeight / (float) appHeight;
+            float scaleW = mTmpStartRect.width() / (float) appWidth;
+            float scaleH = mTmpStartRect.height() / (float) appHeight;
             Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
-                    computePivot(mNextAppTransitionStartX, scaleW),
-                    computePivot(mNextAppTransitionStartY, scaleH));
+                    computePivot(mTmpStartRect.left, scaleW),
+                    computePivot(mTmpStartRect.right, scaleH));
             scale.setInterpolator(mDecelerateInterpolator);
 
             Animation alpha = new AlphaAnimation(0, 1);
@@ -512,6 +511,32 @@
         return a;
     }
 
+    private void getDefaultNextAppTransitionStartRect(Rect rect) {
+        if (mDefaultNextAppTransitionAnimationSpec == null ||
+                mDefaultNextAppTransitionAnimationSpec.rect == null) {
+            Slog.wtf(TAG, "Starting rect for app requested, but none available", new Throwable());
+            rect.setEmpty();
+        } else {
+            rect.set(mDefaultNextAppTransitionAnimationSpec.rect);
+        }
+    }
+
+    void getNextAppTransitionStartRect(int taskId, Rect rect) {
+        AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId);
+        if (spec == null || spec.rect == null) {
+            Slog.wtf(TAG, "Starting rect for task: " + taskId + " requested, but not available",
+                    new Throwable());
+            rect.setEmpty();
+        } else {
+            rect.set(spec.rect);
+        }
+    }
+
+    private void putDefaultNextAppTransitionCoordinates(int left, int top, int width, int height) {
+        mDefaultNextAppTransitionAnimationSpec = new AppTransitionAnimationSpec(-1 /* taskId */,
+                null /* bitmap */, new Rect(left, top, left + width, top + height));
+    }
+
     private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame) {
         final Animation anim;
         if (enter) {
@@ -519,28 +544,27 @@
 
             final int appWidth = appFrame.width();
             final int appHeight = appFrame.height();
+            getDefaultNextAppTransitionStartRect(mTmpStartRect);
 
             float t = 0f;
             if (appHeight > 0) {
-                t = (float) mNextAppTransitionStartY / appHeight;
+                t = (float) mTmpStartRect.left / appHeight;
             }
             int translationY = mClipRevealTranslationY
                     + (int)(appHeight / 7f * t);
 
-            int centerX = mNextAppTransitionStartX + mNextAppTransitionStartWidth / 2;
-            int centerY = mNextAppTransitionStartY + mNextAppTransitionStartHeight / 2;
+            int centerX = mTmpStartRect.centerX();
+            int centerY = mTmpStartRect.centerY();
+            int halfWidth = mTmpStartRect.width() / 2;
+            int halfHeight = mTmpStartRect.height() / 2;
 
             // Clip third of the from size of launch icon, expand to full width/height
             Animation clipAnimLR = new ClipRectLRAnimation(
-                    centerX - mNextAppTransitionStartWidth / 2,
-                    centerX + mNextAppTransitionStartWidth / 2,
-                    0, appWidth);
+                    centerX - halfWidth, centerX + halfWidth, 0, appWidth);
             clipAnimLR.setInterpolator(mClipHorizontalInterpolator);
             clipAnimLR.setDuration((long) (DEFAULT_APP_TRANSITION_DURATION / 2.5f));
-            Animation clipAnimTB = new ClipRectTBAnimation(
-                    centerY - mNextAppTransitionStartHeight / 2 - translationY,
-                    centerY + mNextAppTransitionStartHeight / 2 - translationY,
-                    0, appHeight);
+            Animation clipAnimTB = new ClipRectTBAnimation(centerY - halfHeight - translationY,
+                    centerY + halfHeight/ 2 - translationY, 0, appHeight);
             clipAnimTB.setInterpolator(mTouchResponseInterpolator);
             clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION);
 
@@ -649,31 +673,32 @@
 
     /**
      * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
-     * when a thumbnail is specified with the activity options.
+     * when a thumbnail is specified with the pending animation override.
      */
-    Animation createThumbnailAspectScaleAnimationLocked(Rect appRect) {
+    Animation createThumbnailAspectScaleAnimationLocked(Rect appRect, Bitmap thumbnailHeader,
+            final int taskId) {
         Animation a;
-        final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+        final int thumbWidthI = thumbnailHeader.getWidth();
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
-        final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+        final int thumbHeightI = thumbnailHeader.getHeight();
         final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
         final int appWidth = appRect.width();
 
         float scaleW = appWidth / thumbWidth;
         float unscaledHeight = thumbHeight * scaleW;
-        float unscaledStartY = mNextAppTransitionStartY - (unscaledHeight - thumbHeight) / 2f;
+        getNextAppTransitionStartRect(taskId, mTmpStartRect);
+        float unscaledStartY = mTmpStartRect.top - (unscaledHeight - thumbHeight) / 2f;
         if (mNextAppTransitionScaleUp) {
             // Animation up from the thumbnail to the full screen
             Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
-                    mNextAppTransitionStartX + (thumbWidth / 2f),
-                    mNextAppTransitionStartY + (thumbHeight / 2f));
+                    mTmpStartRect.left + (thumbWidth / 2f), mTmpStartRect.top + (thumbHeight / 2f));
             scale.setInterpolator(mTouchResponseInterpolator);
             scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
             Animation alpha = new AlphaAnimation(1, 0);
             alpha.setInterpolator(mThumbnailFadeOutInterpolator);
             alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
             final float toX = appRect.left + appRect.width() / 2 -
-                    (mNextAppTransitionStartX + thumbWidth / 2);
+                    (mTmpStartRect.left + thumbWidth / 2);
             final float toY = appRect.top + mNextAppTransitionInsets.top + -unscaledStartY;
             Animation translate = new TranslateAnimation(0, toX, 0, toY);
             translate.setInterpolator(mTouchResponseInterpolator);
@@ -688,8 +713,7 @@
         } else {
             // Animation down from the full screen to the thumbnail
             Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f,
-                    mNextAppTransitionStartX + (thumbWidth / 2f),
-                    mNextAppTransitionStartY + (thumbHeight / 2f));
+                    mTmpStartRect.left + (thumbWidth / 2f), mTmpStartRect.top + (thumbHeight / 2f));
             scale.setInterpolator(mTouchResponseInterpolator);
             scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
             Animation alpha = new AlphaAnimation(0f, 1f);
@@ -718,11 +742,13 @@
      */
     Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState,
             int appWidth, int appHeight, int orientation, int transit, Rect containingFrame,
-            Rect contentInsets, @Nullable Rect surfaceInsets, boolean resizedWindow) {
+            Rect contentInsets, @Nullable Rect surfaceInsets, boolean resizedWindow,
+            int taskId) {
         Animation a;
-        final int thumbWidthI = mNextAppTransitionStartWidth;
+        getDefaultNextAppTransitionStartRect(mTmpStartRect);
+        final int thumbWidthI = mTmpStartRect.width();
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
-        final int thumbHeightI = mNextAppTransitionStartHeight;
+        final int thumbHeightI = mTmpStartRect.height();
         final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
 
         // Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
@@ -733,7 +759,7 @@
             case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
                 if (resizedWindow) {
                     a = createAspectScaledThumbnailEnterNonFullscreenAnimationLocked(
-                            containingFrame, surfaceInsets);
+                            containingFrame, surfaceInsets, taskId);
                 } else {
                     // App window scaling up to become full screen
                     if (orientation == Configuration.ORIENTATION_PORTRAIT) {
@@ -759,8 +785,8 @@
                     mNextAppTransitionInsets.set(contentInsets);
 
                     Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
-                            computePivot(mNextAppTransitionStartX, scale),
-                            computePivot(mNextAppTransitionStartY, scale));
+                            computePivot(mTmpStartRect.left, scale),
+                            computePivot(mTmpStartRect.top, scale));
                     Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
                     Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
 
@@ -819,8 +845,8 @@
                 mNextAppTransitionInsets.set(contentInsets);
 
                 Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
-                        computePivot(mNextAppTransitionStartX, scale),
-                        computePivot(mNextAppTransitionStartY, scale));
+                        computePivot(mTmpStartRect.left, scale),
+                        computePivot(mTmpStartRect.top, scale));
                 Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
                 Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
 
@@ -844,11 +870,12 @@
     }
 
     private Animation createAspectScaledThumbnailEnterNonFullscreenAnimationLocked(
-            Rect containingFrame, @Nullable Rect surfaceInsets) {
+            Rect containingFrame, @Nullable Rect surfaceInsets, int taskId) {
+        getNextAppTransitionStartRect(taskId, mTmpStartRect);
         float width = containingFrame.width();
         float height = containingFrame.height();
-        float scaleWidth = mNextAppTransitionStartWidth / width;
-        float scaleHeight = mNextAppTransitionStartHeight / height;
+        float scaleWidth = mTmpStartRect.width() / width;
+        float scaleHeight = mTmpStartRect.height() / height;
         AnimationSet set = new AnimationSet(true);
         int surfaceInsetsHorizontal = surfaceInsets == null
                 ? 0 : surfaceInsets.left + surfaceInsets.right;
@@ -858,9 +885,9 @@
         // we need to account for surface insets that will be used to enlarge the surface.
         ScaleAnimation scale = new ScaleAnimation(scaleWidth, 1, scaleHeight, 1,
                 (width + surfaceInsetsHorizontal) / 2, (height + surfaceInsetsVertical) / 2);
-        int fromX = mNextAppTransitionStartX + mNextAppTransitionStartWidth / 2
+        int fromX = mTmpStartRect.left + mTmpStartRect.width() / 2
                 - (containingFrame.left + containingFrame.width() / 2);
-        int fromY = mNextAppTransitionStartY + mNextAppTransitionStartHeight / 2
+        int fromY = mTmpStartRect.top + mTmpStartRect.height() / 2
                 - (containingFrame.top + containingFrame.height() / 2);
         TranslateAnimation translation = new TranslateAnimation(fromX, 0, fromY, 0);
         set.addAnimation(scale);
@@ -870,13 +897,15 @@
 
     /**
      * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
-     * when a thumbnail is specified with the activity options.
+     * when a thumbnail is specified with the pending animation override.
      */
-    Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
+    Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit,
+            Bitmap thumbnailHeader) {
         Animation a;
-        final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+        getDefaultNextAppTransitionStartRect(mTmpStartRect);
+        final int thumbWidthI = thumbnailHeader.getWidth();
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
-        final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+        final int thumbHeightI = thumbnailHeader.getHeight();
         final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
 
         if (mNextAppTransitionScaleUp) {
@@ -884,8 +913,8 @@
             float scaleW = appWidth / thumbWidth;
             float scaleH = appHeight / thumbHeight;
             Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
-                    computePivot(mNextAppTransitionStartX, 1 / scaleW),
-                    computePivot(mNextAppTransitionStartY, 1 / scaleH));
+                    computePivot(mTmpStartRect.left, 1 / scaleW),
+                    computePivot(mTmpStartRect.top, 1 / scaleH));
             scale.setInterpolator(mDecelerateInterpolator);
 
             Animation alpha = new AlphaAnimation(1, 0);
@@ -901,8 +930,8 @@
             float scaleW = appWidth / thumbWidth;
             float scaleH = appHeight / thumbHeight;
             a = new ScaleAnimation(scaleW, 1, scaleH, 1,
-                    computePivot(mNextAppTransitionStartX, 1 / scaleW),
-                    computePivot(mNextAppTransitionStartY, 1 / scaleH));
+                    computePivot(mTmpStartRect.left, 1 / scaleW),
+                    computePivot(mTmpStartRect.top, 1 / scaleH));
         }
 
         return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
@@ -913,11 +942,13 @@
      * leaving, and the activity that is entering.
      */
     Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
-            int appHeight, int transit) {
+            int appHeight, int transit, int taskId) {
+        Bitmap thumbnailHeader = getAppTransitionThumbnailHeader(taskId);
         Animation a;
-        final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+        getDefaultNextAppTransitionStartRect(mTmpStartRect);
+        final int thumbWidthI = thumbnailHeader != null ? thumbnailHeader.getWidth() : appWidth;
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
-        final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+        final int thumbHeightI = thumbnailHeader != null ? thumbnailHeader.getHeight() : appHeight;
         final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
 
         switch (thumbTransitState) {
@@ -926,8 +957,8 @@
                 float scaleW = thumbWidth / appWidth;
                 float scaleH = thumbHeight / appHeight;
                 a = new ScaleAnimation(scaleW, 1, scaleH, 1,
-                        computePivot(mNextAppTransitionStartX, scaleW),
-                        computePivot(mNextAppTransitionStartY, scaleH));
+                        computePivot(mTmpStartRect.left, scaleW),
+                        computePivot(mTmpStartRect.top, scaleH));
                 break;
             }
             case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
@@ -954,8 +985,8 @@
                 float scaleW = thumbWidth / appWidth;
                 float scaleH = thumbHeight / appHeight;
                 Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
-                        computePivot(mNextAppTransitionStartX, scaleW),
-                        computePivot(mNextAppTransitionStartY, scaleH));
+                        computePivot(mTmpStartRect.left, scaleW),
+                        computePivot(mTmpStartRect.top, scaleH));
 
                 Animation alpha = new AlphaAnimation(1, 0);
 
@@ -987,7 +1018,7 @@
     Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
             int appWidth, int appHeight, int orientation, Rect containingFrame, Rect contentInsets,
             @Nullable Rect surfaceInsets, Rect appFrame, boolean isVoiceInteraction,
-            boolean resizedWindow) {
+            boolean resizedWindow, int taskId) {
         Animation a;
         if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
                 || transit == TRANSIT_TASK_OPEN
@@ -1042,7 +1073,7 @@
             mNextAppTransitionScaleUp =
                     (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
             a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
-                    appWidth, appHeight, transit);
+                    appWidth, appHeight, transit, taskId);
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
                 String animName = mNextAppTransitionScaleUp ?
                         "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
@@ -1057,7 +1088,7 @@
                     (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
             a = createAspectScaledThumbnailEnterExitAnimationLocked(
                     getThumbnailTransitionState(enter), appWidth, appHeight, orientation, transit,
-                    containingFrame, contentInsets, surfaceInsets, resizedWindow);
+                    containingFrame, contentInsets, surfaceInsets, resizedWindow, taskId);
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
                 String animName = mNextAppTransitionScaleUp ?
                         "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN";
@@ -1147,7 +1178,7 @@
         if (isTransitionSet()) {
             mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
             mNextAppTransitionPackage = packageName;
-            mNextAppTransitionThumbnail = null;
+            mNextAppTransitionAnimationsSpecs.clear();
             mNextAppTransitionEnter = enterAnim;
             mNextAppTransitionExit = exitAnim;
             postAnimationCallback();
@@ -1158,15 +1189,13 @@
     }
 
     void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
-                                                    int startHeight) {
+            int startHeight) {
         if (isTransitionSet()) {
             mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP;
             mNextAppTransitionPackage = null;
-            mNextAppTransitionThumbnail = null;
-            mNextAppTransitionStartX = startX;
-            mNextAppTransitionStartY = startY;
-            mNextAppTransitionStartWidth = startWidth;
-            mNextAppTransitionStartHeight = startHeight;
+            mNextAppTransitionAnimationsSpecs.clear();
+            putDefaultNextAppTransitionCoordinates(startX, startY, startX + startWidth,
+                    startY + startHeight);
             postAnimationCallback();
             mNextAppTransitionCallback = null;
         }
@@ -1176,10 +1205,7 @@
                                                 int startWidth, int startHeight) {
         if (isTransitionSet()) {
             mNextAppTransitionType = NEXT_TRANSIT_TYPE_CLIP_REVEAL;
-            mNextAppTransitionStartX = startX;
-            mNextAppTransitionStartY = startY;
-            mNextAppTransitionStartWidth = startWidth;
-            mNextAppTransitionStartHeight = startHeight;
+            putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight);
             postAnimationCallback();
             mNextAppTransitionCallback = null;
         }
@@ -1191,10 +1217,9 @@
             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP
                     : NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN;
             mNextAppTransitionPackage = null;
-            mNextAppTransitionThumbnail = srcThumb;
+            mNextAppTransitionAnimationsSpecs.clear();
             mNextAppTransitionScaleUp = scaleUp;
-            mNextAppTransitionStartX = startX;
-            mNextAppTransitionStartY = startY;
+            putDefaultNextAppTransitionCoordinates(startX, startY, 0 ,0);
             postAnimationCallback();
             mNextAppTransitionCallback = startedCallback;
         } else {
@@ -1208,12 +1233,9 @@
             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
                     : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
             mNextAppTransitionPackage = null;
-            mNextAppTransitionThumbnail = srcThumb;
+            mNextAppTransitionAnimationsSpecs.clear();
             mNextAppTransitionScaleUp = scaleUp;
-            mNextAppTransitionStartX = startX;
-            mNextAppTransitionStartY = startY;
-            mNextAppTransitionStartWidth = targetWidth;
-            mNextAppTransitionStartHeight = targetHeight;
+            putDefaultNextAppTransitionCoordinates(startX, startY, targetWidth, targetHeight);
             postAnimationCallback();
             mNextAppTransitionCallback = startedCallback;
         } else {
@@ -1221,6 +1243,27 @@
         }
     }
 
+    public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
+            IRemoteCallback callback, boolean scaleUp) {
+        if (isTransitionSet()) {
+            mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
+                    : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
+            mNextAppTransitionPackage = null;
+            mNextAppTransitionAnimationsSpecs.clear();
+            mNextAppTransitionScaleUp = scaleUp;
+            for (int i = 0; i < specs.length; i++) {
+                AppTransitionAnimationSpec spec = specs[i];
+                if (spec != null) {
+                    mNextAppTransitionAnimationsSpecs.put(spec.taskId, spec);
+                }
+            }
+            postAnimationCallback();
+            mNextAppTransitionCallback = callback;
+        } else {
+            postAnimationCallback();
+        }
+    }
+
     void overrideInPlaceAppTransition(String packageName, int anim) {
         if (isTransitionSet()) {
             mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE;
@@ -1350,33 +1393,30 @@
                 pw.print(prefix); pw.print("mNextAppTransitionInPlace=0x");
                         pw.print(Integer.toHexString(mNextAppTransitionInPlace));
                 break;
-            case NEXT_TRANSIT_TYPE_SCALE_UP:
+            case NEXT_TRANSIT_TYPE_SCALE_UP: {
+                getDefaultNextAppTransitionStartRect(mTmpStartRect);
                 pw.print(prefix); pw.print("mNextAppTransitionStartX=");
-                        pw.print(mNextAppTransitionStartX);
+                        pw.print(mTmpStartRect.left);
                         pw.print(" mNextAppTransitionStartY=");
-                        pw.println(mNextAppTransitionStartY);
+                        pw.println(mTmpStartRect.top);
                 pw.print(prefix); pw.print("mNextAppTransitionStartWidth=");
-                        pw.print(mNextAppTransitionStartWidth);
+                        pw.print(mTmpStartRect.width());
                         pw.print(" mNextAppTransitionStartHeight=");
-                        pw.println(mNextAppTransitionStartHeight);
+                        pw.println(mTmpStartRect.height());
                 break;
+            }
             case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
             case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
             case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
-            case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
-                pw.print(prefix); pw.print("mNextAppTransitionThumbnail=");
-                        pw.print(mNextAppTransitionThumbnail);
-                        pw.print(" mNextAppTransitionStartX=");
-                        pw.print(mNextAppTransitionStartX);
-                        pw.print(" mNextAppTransitionStartY=");
-                        pw.println(mNextAppTransitionStartY);
-                pw.print(prefix); pw.print("mNextAppTransitionStartWidth=");
-                        pw.print(mNextAppTransitionStartWidth);
-                        pw.print(" mNextAppTransitionStartHeight=");
-                        pw.println(mNextAppTransitionStartHeight);
+            case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN: {
+                pw.print(prefix); pw.print("mDefaultNextAppTransitionAnimationSpec=");
+                        pw.println(mDefaultNextAppTransitionAnimationSpec);
+                pw.print(prefix); pw.print("mNextAppTransitionAnimationsSpecs=");
+                        pw.println(mNextAppTransitionAnimationsSpecs);
                 pw.print(prefix); pw.print("mNextAppTransitionScaleUp=");
                         pw.println(mNextAppTransitionScaleUp);
                 break;
+            }
         }
         if (mNextAppTransitionCallback != null) {
             pw.print(prefix); pw.print("mNextAppTransitionCallback=");
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index df7b23d..2828cd0 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -193,6 +193,7 @@
         final int windowCount = mAppToken.allAppWindows.size();
         final int adj = animLayerAdjustment;
         thumbnailLayer = -1;
+        final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
         for (int i = 0; i < windowCount; i++) {
             final WindowState w = mAppToken.allAppWindows.get(i);
             final WindowStateAnimator winAnimator = w.mWinAnimator;
@@ -204,9 +205,7 @@
             if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
                 mService.setInputMethodAnimLayerAdjustment(adj);
             }
-            if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) {
-                mService.setWallpaperAnimLayerAdjustmentLocked(adj);
-            }
+            wallpaperController.setAnimLayerAdjustment(w, adj);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 222945c..e87dcde 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.input.InputWindowHandle;
 import com.android.server.wm.WindowManagerService.DragInputEventReceiver;
@@ -413,7 +414,7 @@
                 continue;
             }
 
-            child.getTaskBounds(mTmpRect);
+            child.getTaskBounds(mTmpRect, !BOUNDS_FOR_TOUCH);
             if (!mTmpRect.contains(x, y)) {
                 // outside of this window's activity stack == don't tell about drags
                 continue;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 21e92c9..b3244ff 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
 import android.app.ActivityManagerNative;
 import android.graphics.Rect;
 import android.os.RemoteException;
@@ -177,7 +178,7 @@
         if (modal && child.mAppToken != null) {
             // Limit the outer touch to the activity stack region.
             flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-            child.getTaskBounds(mTmpRect);
+            child.getTaskBounds(mTmpRect, BOUNDS_FOR_TOUCH);
             inputWindowHandle.touchableRegion.set(mTmpRect);
         } else {
             // Not modal or full screen modal
@@ -260,6 +261,7 @@
 
         // Add all windows on the default display.
         final int numDisplays = mService.mDisplayContents.size();
+        final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
             WindowList windows = mService.mDisplayContents.valueAt(displayNdx).getWindowList();
             for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
@@ -287,7 +289,7 @@
                             != 0) {
                     disableWallpaperTouchEvents = true;
                 }
-                final boolean hasWallpaper = (child == mService.mWallpaperTarget)
+                final boolean hasWallpaper = wallpaperController.isWallpaperTarget(child)
                         && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0
                         && !disableWallpaperTouchEvents;
                 final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 75bb10a..12f61f9 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -403,7 +403,7 @@
         synchronized(mService.mWindowMap) {
             long ident = Binder.clearCallingIdentity();
             try {
-                mService.setWindowWallpaperPositionLocked(
+                mService.mWallpaperControllerLocked.setWindowWallpaperPosition(
                         mService.windowForClientLocked(this, window, true),
                         x, y, xStep, yStep);
             } finally {
@@ -413,14 +413,16 @@
     }
 
     public void wallpaperOffsetsComplete(IBinder window) {
-        mService.wallpaperOffsetsComplete(window);
+        synchronized (mService.mWindowMap) {
+            mService.mWallpaperControllerLocked.wallpaperOffsetsComplete(window);
+        }
     }
 
     public void setWallpaperDisplayOffset(IBinder window, int x, int y) {
         synchronized(mService.mWindowMap) {
             long ident = Binder.clearCallingIdentity();
             try {
-                mService.setWindowWallpaperDisplayOffsetLocked(
+                mService.mWallpaperControllerLocked.setWindowWallpaperDisplayOffset(
                         mService.windowForClientLocked(this, window, true), x, y);
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -433,7 +435,7 @@
         synchronized(mService.mWindowMap) {
             long ident = Binder.clearCallingIdentity();
             try {
-                return mService.sendWindowWallpaperCommandLocked(
+                return mService.mWallpaperControllerLocked.sendWindowWallpaperCommand(
                         mService.windowForClientLocked(this, window, true),
                         action, x, y, z, extras, sync);
             } finally {
@@ -443,7 +445,9 @@
     }
 
     public void wallpaperCommandComplete(IBinder window, Bundle result) {
-        mService.wallpaperCommandComplete(window, result);
+        synchronized (mService.mWindowMap) {
+            mService.mWallpaperControllerLocked.wallpaperCommandComplete(window);
+        }
     }
 
     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
new file mode 100644
index 0000000..d0962f4
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -0,0 +1,916 @@
+/*
+ * 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.server.wm;
+
+import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.server.wm.WindowManagerService.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerService.DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.WindowManagerService.DEBUG_LAYERS;
+import static com.android.server.wm.WindowManagerService.DEBUG_WINDOW_MOVEMENT;
+import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerService.DEBUG_WALLPAPER;
+import static com.android.server.wm.WindowManagerService.DEBUG_WALLPAPER_LIGHT;
+import static com.android.server.wm.WindowManagerService.H.WALLPAPER_DRAW_PENDING_TIMEOUT;
+import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
+import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
+
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.view.DisplayInfo;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Controls wallpaper windows visibility, ordering, and so on.
+ * NOTE: All methods in this class must be called with the window manager service lock held.
+ */
+class WallpaperController {
+    private static final String TAG = com.android.server.wm.WindowManagerService.TAG;
+    final private WindowManagerService mService;
+
+    private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<>();
+
+    // If non-null, this is the currently visible window that is associated
+    // with the wallpaper.
+    private WindowState mWallpaperTarget = null;
+    // If non-null, we are in the middle of animating from one wallpaper target
+    // to another, and this is the lower one in Z-order.
+    private WindowState mLowerWallpaperTarget = null;
+    // If non-null, we are in the middle of animating from one wallpaper target
+    // to another, and this is the higher one in Z-order.
+    private WindowState mUpperWallpaperTarget = null;
+
+    private int mWallpaperAnimLayerAdjustment;
+
+    private float mLastWallpaperX = -1;
+    private float mLastWallpaperY = -1;
+    private float mLastWallpaperXStep = -1;
+    private float mLastWallpaperYStep = -1;
+    private int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
+    private int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
+
+    // This is set when we are waiting for a wallpaper to tell us it is done
+    // changing its scroll position.
+    WindowState mWaitingOnWallpaper;
+
+    // The last time we had a timeout when waiting for a wallpaper.
+    private long mLastWallpaperTimeoutTime;
+    // We give a wallpaper up to 150ms to finish scrolling.
+    private static final long WALLPAPER_TIMEOUT = 150;
+    // Time we wait after a timeout before trying to wait again.
+    private static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
+
+    // Set to the wallpaper window we would like to hide once the transition animations are done.
+    // This is useful in cases where we don't want the wallpaper to be hidden when the close app
+    // is a wallpaper target and is done animating out, but the opening app isn't a wallpaper
+    // target and isn't done animating in.
+    private WindowState mDeferredHideWallpaper = null;
+
+    // We give a wallpaper up to 500ms to finish drawing before playing app transitions.
+    private static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500;
+    private static final int WALLPAPER_DRAW_NORMAL = 0;
+    private static final int WALLPAPER_DRAW_PENDING = 1;
+    private static final int WALLPAPER_DRAW_TIMEOUT = 2;
+    private int mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
+
+    private final FindWallpaperTargetResult mFindResults = new FindWallpaperTargetResult();
+
+    public WallpaperController(WindowManagerService service) {
+        mService = service;
+    }
+
+    WindowState getWallpaperTarget() {
+        return mWallpaperTarget;
+    }
+
+    WindowState getLowerWallpaperTarget() {
+        return mLowerWallpaperTarget;
+    }
+
+    WindowState getUpperWallpaperTarget() {
+        return mUpperWallpaperTarget;
+    }
+
+    boolean isWallpaperTarget(WindowState win) {
+        return win == mWallpaperTarget;
+    }
+
+    boolean isBelowWallpaperTarget(WindowState win) {
+        return mWallpaperTarget != null && mWallpaperTarget.mLayer >= win.mBaseLayer;
+    }
+
+    boolean isWallpaperVisible() {
+        return isWallpaperVisible(mWallpaperTarget);
+    }
+
+    private boolean isWallpaperVisible(WindowState wallpaperTarget) {
+        if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
+                + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
+                + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
+                ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
+                + " upper=" + mUpperWallpaperTarget
+                + " lower=" + mLowerWallpaperTarget);
+        return (wallpaperTarget != null
+                && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
+                && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
+                || mUpperWallpaperTarget != null
+                || mLowerWallpaperTarget != null;
+    }
+
+    boolean isWallpaperTargetAnimating() {
+        return mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
+                && !mWallpaperTarget.mWinAnimator.isDummyAnimation();
+    }
+
+    void updateWallpaperVisibility() {
+        final boolean visible = isWallpaperVisible(mWallpaperTarget);
+        final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
+        if (displayContent == null) {
+            return;
+        }
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
+
+        for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+            WindowToken token = mWallpaperTokens.get(curTokenNdx);
+            if (token.hidden == visible) {
+                token.hidden = !visible;
+                // Need to do a layout to ensure the wallpaper now has the
+                // correct size.
+                displayContent.layoutNeeded = true;
+            }
+
+            final WindowList windows = token.windows;
+            for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+                WindowState wallpaper = windows.get(wallpaperNdx);
+                if (visible) {
+                    updateWallpaperOffset(wallpaper, dw, dh, false);
+                }
+
+                dispatchWallpaperVisibility(wallpaper, visible);
+            }
+        }
+    }
+
+    void hideDeferredWallpapersIfNeeded() {
+        if (mDeferredHideWallpaper != null) {
+            hideWallpapers(mDeferredHideWallpaper);
+            mDeferredHideWallpaper = null;
+        }
+    }
+
+    void hideWallpapers(final WindowState winGoingAway) {
+        if (mWallpaperTarget != null
+                && (mWallpaperTarget != winGoingAway || mLowerWallpaperTarget != null)) {
+            return;
+        }
+        if (mService.mAppTransition.isRunning()) {
+            // Defer hiding the wallpaper when app transition is running until the animations
+            // are done.
+            mDeferredHideWallpaper = winGoingAway;
+            return;
+        }
+
+        final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
+        for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
+            final WindowToken token = mWallpaperTokens.get(i);
+            for (int j = token.windows.size() - 1; j >= 0; j--) {
+                final WindowState wallpaper = token.windows.get(j);
+                final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
+                if (!winAnimator.mLastHidden || wasDeferred) {
+                    winAnimator.hide();
+                    dispatchWallpaperVisibility(wallpaper, false);
+                    final DisplayContent displayContent = wallpaper.getDisplayContent();
+                    if (displayContent != null) {
+                        displayContent.pendingLayoutChanges |=
+                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                    }
+                }
+            }
+            if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
+                    + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
+                    + mLowerWallpaperTarget + "\n" + Debug.getCallers(5, "  "));
+            token.hidden = true;
+        }
+    }
+
+    /**
+     * Check wallpaper for visibility change and notify window if so.
+     * @param wallpaper The wallpaper to test and notify.
+     * @param visible Current visibility.
+     */
+    void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
+        // Only send notification if the visibility actually changed and we are not trying to hide
+        // the wallpaper when we are deferring hiding of the wallpaper.
+        if (wallpaper.mWallpaperVisible != visible
+                && (mDeferredHideWallpaper == null || visible)) {
+            wallpaper.mWallpaperVisible = visible;
+            try {
+                if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                        "Updating vis of wallpaper " + wallpaper
+                                + ": " + visible + " from:\n" + Debug.getCallers(4, "  "));
+                wallpaper.mClient.dispatchAppVisibility(visible);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    boolean updateWallpaperOffset(WindowState wallpaperWin, int dw, int dh, boolean sync) {
+        boolean rawChanged = false;
+        float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
+        float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
+        int availw = wallpaperWin.mFrame.right - wallpaperWin.mFrame.left - dw;
+        int offset = availw > 0 ? -(int)(availw * wpx + .5f) : 0;
+        if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+            offset += mLastWallpaperDisplayOffsetX;
+        }
+        boolean changed = wallpaperWin.mXOffset != offset;
+        if (changed) {
+            if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " x: " + offset);
+            wallpaperWin.mXOffset = offset;
+        }
+        if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
+            wallpaperWin.mWallpaperX = wpx;
+            wallpaperWin.mWallpaperXStep = wpxs;
+            rawChanged = true;
+        }
+
+        float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
+        float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
+        int availh = wallpaperWin.mFrame.bottom - wallpaperWin.mFrame.top - dh;
+        offset = availh > 0 ? -(int)(availh * wpy + .5f) : 0;
+        if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+            offset += mLastWallpaperDisplayOffsetY;
+        }
+        if (wallpaperWin.mYOffset != offset) {
+            if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " + wallpaperWin + " y: " + offset);
+            changed = true;
+            wallpaperWin.mYOffset = offset;
+        }
+        if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
+            wallpaperWin.mWallpaperY = wpy;
+            wallpaperWin.mWallpaperYStep = wpys;
+            rawChanged = true;
+        }
+
+        if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
+                WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
+            try {
+                if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
+                        + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
+                        + " y=" + wallpaperWin.mWallpaperY);
+                if (sync) {
+                    mWaitingOnWallpaper = wallpaperWin;
+                }
+                wallpaperWin.mClient.dispatchWallpaperOffsets(
+                        wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
+                        wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
+                if (sync) {
+                    if (mWaitingOnWallpaper != null) {
+                        long start = SystemClock.uptimeMillis();
+                        if ((mLastWallpaperTimeoutTime + WALLPAPER_TIMEOUT_RECOVERY)
+                                < start) {
+                            try {
+                                if (DEBUG_WALLPAPER) Slog.v(TAG,
+                                        "Waiting for offset complete...");
+                                mService.mWindowMap.wait(WALLPAPER_TIMEOUT);
+                            } catch (InterruptedException e) {
+                            }
+                            if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
+                            if ((start + WALLPAPER_TIMEOUT) < SystemClock.uptimeMillis()) {
+                                Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
+                                        + wallpaperWin);
+                                mLastWallpaperTimeoutTime = start;
+                            }
+                        }
+                        mWaitingOnWallpaper = null;
+                    }
+                }
+            } catch (RemoteException e) {
+            }
+        }
+
+        return changed;
+    }
+
+    void setWindowWallpaperPosition(
+            WindowState window, float x, float y, float xStep, float yStep) {
+        if (window.mWallpaperX != x || window.mWallpaperY != y)  {
+            window.mWallpaperX = x;
+            window.mWallpaperY = y;
+            window.mWallpaperXStep = xStep;
+            window.mWallpaperYStep = yStep;
+            updateWallpaperOffsetLocked(window, true);
+        }
+    }
+
+    void setWindowWallpaperDisplayOffset(WindowState window, int x, int y) {
+        if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y)  {
+            window.mWallpaperDisplayOffsetX = x;
+            window.mWallpaperDisplayOffsetY = y;
+            updateWallpaperOffsetLocked(window, true);
+        }
+    }
+
+    Bundle sendWindowWallpaperCommand(
+            WindowState window, String action, int x, int y, int z, Bundle extras, boolean sync) {
+        if (window == mWallpaperTarget
+                || window == mLowerWallpaperTarget
+                || window == mUpperWallpaperTarget) {
+            boolean doWait = sync;
+            for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+                final WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
+                for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+                    WindowState wallpaper = windows.get(wallpaperNdx);
+                    try {
+                        wallpaper.mClient.dispatchWallpaperCommand(action,
+                                x, y, z, extras, sync);
+                        // We only want to be synchronous with one wallpaper.
+                        sync = false;
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+
+            if (doWait) {
+                // TODO: Need to wait for result.
+            }
+        }
+
+        return null;
+    }
+
+    void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
+        final DisplayContent displayContent = changingTarget.getDisplayContent();
+        if (displayContent == null) {
+            return;
+        }
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
+
+        WindowState target = mWallpaperTarget;
+        if (target != null) {
+            if (target.mWallpaperX >= 0) {
+                mLastWallpaperX = target.mWallpaperX;
+            } else if (changingTarget.mWallpaperX >= 0) {
+                mLastWallpaperX = changingTarget.mWallpaperX;
+            }
+            if (target.mWallpaperY >= 0) {
+                mLastWallpaperY = target.mWallpaperY;
+            } else if (changingTarget.mWallpaperY >= 0) {
+                mLastWallpaperY = changingTarget.mWallpaperY;
+            }
+            if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+                mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
+            } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+                mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
+            }
+            if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+                mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
+            } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+                mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
+            }
+            if (target.mWallpaperXStep >= 0) {
+                mLastWallpaperXStep = target.mWallpaperXStep;
+            } else if (changingTarget.mWallpaperXStep >= 0) {
+                mLastWallpaperXStep = changingTarget.mWallpaperXStep;
+            }
+            if (target.mWallpaperYStep >= 0) {
+                mLastWallpaperYStep = target.mWallpaperYStep;
+            } else if (changingTarget.mWallpaperYStep >= 0) {
+                mLastWallpaperYStep = changingTarget.mWallpaperYStep;
+            }
+        }
+
+        for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+            WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
+            for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+                WindowState wallpaper = windows.get(wallpaperNdx);
+                if (updateWallpaperOffset(wallpaper, dw, dh, sync)) {
+                    WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
+                    winAnimator.computeShownFrameLocked();
+                    // No need to lay out the windows - we can just set the wallpaper position
+                    // directly.
+                    winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
+                    // We only want to be synchronous with one wallpaper.
+                    sync = false;
+                }
+            }
+        }
+    }
+
+    void clearLastWallpaperTimeoutTime() {
+        mLastWallpaperTimeoutTime = 0;
+    }
+
+    void wallpaperCommandComplete(IBinder window) {
+        if (mWaitingOnWallpaper != null &&
+                mWaitingOnWallpaper.mClient.asBinder() == window) {
+            mWaitingOnWallpaper = null;
+            mService.mWindowMap.notifyAll();
+        }
+    }
+
+    void wallpaperOffsetsComplete(IBinder window) {
+        if (mWaitingOnWallpaper != null &&
+                mWaitingOnWallpaper.mClient.asBinder() == window) {
+            mWaitingOnWallpaper = null;
+            mService.mWindowMap.notifyAll();
+        }
+    }
+
+    int getAnimLayerAdjustment() {
+        return mWallpaperAnimLayerAdjustment;
+    }
+
+    void setAnimLayerAdjustment(WindowState win, int adj) {
+        if (win != mWallpaperTarget || mLowerWallpaperTarget != null) {
+            return;
+        }
+
+        if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Setting wallpaper layer adj to " + adj);
+        mWallpaperAnimLayerAdjustment = adj;
+        for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
+            WindowList windows = mWallpaperTokens.get(i).windows;
+            for (int j = windows.size() - 1; j >= 0; j--) {
+                WindowState wallpaper = windows.get(j);
+                wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
+                if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
+                        + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
+            }
+        }
+    }
+
+    private void findWallpaperTarget(WindowList windows, FindWallpaperTargetResult result) {
+
+        final WindowAnimator winAnimator = mService.mAnimator;
+        result.reset();
+        WindowState w = null;
+        int windowDetachedI = -1;
+        boolean resetTopWallpaper = false;
+        boolean inFreeformSpace = false;
+        for (int i = windows.size() - 1; i >= 0; i--) {
+            w = windows.get(i);
+            if ((w.mAttrs.type == TYPE_WALLPAPER)) {
+                if (result.topWallpaper == null || resetTopWallpaper) {
+                    result.setTopWallpaper(w, i);
+                    resetTopWallpaper = false;
+                }
+                continue;
+            }
+            resetTopWallpaper = true;
+            if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
+                // If this window's app token is hidden and not animating,
+                // it is of no interest to us.
+                if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
+                    if (DEBUG_WALLPAPER) Slog.v(TAG,
+                            "Skipping hidden and not animating token: " + w);
+                    continue;
+                }
+            }
+            if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
+                    + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
+
+            if (!inFreeformSpace) {
+                TaskStack stack = w.getStack();
+                inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
+            }
+
+            // If the app is executing an animation because the keyguard is going away,
+            // keep the wallpaper during the animation so it doesn't flicker out.
+            final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0
+                    || (w.mAppToken != null && w.mWinAnimator.mKeyguardGoingAwayAnimation);
+            if (hasWallpaper && w.isOnScreen()
+                    && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
+                if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w);
+                result.setWallpaperTarget(w, i);
+                if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
+                    // The current wallpaper target is animating, so we'll look behind it for
+                    // another possible target and figure out what is going on later.
+                    if (DEBUG_WALLPAPER) Slog.v(TAG,
+                            "Win " + w + ": token animating, looking behind.");
+                    continue;
+                }
+                break;
+            } else if (w == winAnimator.mWindowDetachedWallpaper) {
+                windowDetachedI = i;
+            }
+        }
+
+        if (result.wallpaperTarget == null && windowDetachedI >= 0) {
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                    "Found animating detached wallpaper activity: #" + windowDetachedI + "=" + w);
+            result.setWallpaperTarget(w, windowDetachedI);
+        }
+        if (result.wallpaperTarget == null && inFreeformSpace) {
+            // In freeform mode we set the wallpaper as its own target, so we don't need an
+            // additional window to make it visible.
+            result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
+        }
+    }
+
+    private boolean updateWallpaperWindowsTarget(
+            WindowList windows, FindWallpaperTargetResult result) {
+
+        boolean targetChanged = false;
+        WindowState wallpaperTarget = result.wallpaperTarget;
+        int wallpaperTargetIndex = result.wallpaperTargetIndex;
+
+        if (mWallpaperTarget != wallpaperTarget
+                && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != wallpaperTarget)) {
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                    "New wallpaper target: " + wallpaperTarget + " oldTarget: " + mWallpaperTarget);
+
+            mLowerWallpaperTarget = null;
+            mUpperWallpaperTarget = null;
+
+            WindowState oldW = mWallpaperTarget;
+            mWallpaperTarget = wallpaperTarget;
+            targetChanged = true;
+
+            // Now what is happening...  if the current and new targets are animating,
+            // then we are in our super special mode!
+            if (wallpaperTarget != null && oldW != null) {
+                boolean oldAnim = oldW.isAnimatingLw();
+                boolean foundAnim = wallpaperTarget.isAnimatingLw();
+                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                        "New animation: " + foundAnim + " old animation: " + oldAnim);
+                if (foundAnim && oldAnim) {
+                    int oldI = windows.indexOf(oldW);
+                    if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                            "New i: " + wallpaperTargetIndex + " old i: " + oldI);
+                    if (oldI >= 0) {
+                        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                                "Animating wallpapers: old#" + oldI + "=" + oldW + "; new#"
+                                + wallpaperTargetIndex + "=" + wallpaperTarget);
+
+                        // Set the new target correctly.
+                        if (wallpaperTarget.mAppToken != null
+                                && wallpaperTarget.mAppToken.hiddenRequested) {
+                            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                                    "Old wallpaper still the target.");
+                            mWallpaperTarget = oldW;
+                            wallpaperTarget = oldW;
+                            wallpaperTargetIndex = oldI;
+                        }
+                        // Now set the upper and lower wallpaper targets correctly,
+                        // and make sure that we are positioning the wallpaper below the lower.
+                        else if (wallpaperTargetIndex > oldI) {
+                            // The new target is on top of the old one.
+                            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                                    "Found target above old target.");
+                            mUpperWallpaperTarget = wallpaperTarget;
+                            mLowerWallpaperTarget = oldW;
+                            wallpaperTarget = oldW;
+                            wallpaperTargetIndex = oldI;
+                        } else {
+                            // The new target is below the old one.
+                            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                                    "Found target below old target.");
+                            mUpperWallpaperTarget = oldW;
+                            mLowerWallpaperTarget = wallpaperTarget;
+                        }
+                    }
+                }
+            }
+
+        } else if (mLowerWallpaperTarget != null) {
+            // Is it time to stop animating?
+            if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
+                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "No longer animating wallpaper targets!");
+                mLowerWallpaperTarget = null;
+                mUpperWallpaperTarget = null;
+                mWallpaperTarget = wallpaperTarget;
+                targetChanged = true;
+            }
+        }
+
+        result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
+        return targetChanged;
+    }
+
+    boolean updateWallpaperWindowsTargetByLayer(
+            WindowList windows, FindWallpaperTargetResult result) {
+
+        WindowState wallpaperTarget = result.wallpaperTarget;
+        int wallpaperTargetIndex = result.wallpaperTargetIndex;
+        boolean visible = wallpaperTarget != null;
+
+        if (visible) {
+            // The window is visible to the compositor...but is it visible to the user?
+            // That is what the wallpaper cares about.
+            visible = isWallpaperVisible(wallpaperTarget);
+            if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
+
+            // If the wallpaper target is animating, we may need to copy its layer adjustment.
+            // Only do this if we are not transferring between two wallpaper targets.
+            mWallpaperAnimLayerAdjustment =
+                    (mLowerWallpaperTarget == null && wallpaperTarget.mAppToken != null)
+                            ? wallpaperTarget.mAppToken.mAppAnimator.animLayerAdjustment : 0;
+
+            final int maxLayer = (mService.mPolicy.getMaxWallpaperLayer() * TYPE_LAYER_MULTIPLIER)
+                    + TYPE_LAYER_OFFSET;
+
+            // Now w is the window we are supposed to be behind...  but we
+            // need to be sure to also be behind any of its attached windows,
+            // AND any starting window associated with it, AND below the
+            // maximum layer the policy allows for wallpapers.
+            while (wallpaperTargetIndex > 0) {
+                WindowState wb = windows.get(wallpaperTargetIndex - 1);
+                if (wb.mBaseLayer < maxLayer &&
+                        wb.mAttachedWindow != wallpaperTarget &&
+                        (wallpaperTarget.mAttachedWindow == null ||
+                                wb.mAttachedWindow != wallpaperTarget.mAttachedWindow) &&
+                        (wb.mAttrs.type != TYPE_APPLICATION_STARTING
+                                || wallpaperTarget.mToken == null
+                                || wb.mToken != wallpaperTarget.mToken)) {
+                    // This window is not related to the previous one in any
+                    // interesting way, so stop here.
+                    break;
+                }
+                wallpaperTarget = wb;
+                wallpaperTargetIndex--;
+            }
+        } else {
+            if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
+        }
+
+        result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
+        return visible;
+    }
+
+    boolean updateWallpaperWindowsPlacement(WindowList windows,
+            WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible) {
+
+        // TODO(multidisplay): Wallpapers on main screen only.
+        final DisplayInfo displayInfo = mService.getDefaultDisplayContentLocked().getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
+
+        // Start stepping backwards from here, ensuring that our wallpaper windows
+        // are correctly placed.
+        boolean changed = false;
+        for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+            WindowToken token = mWallpaperTokens.get(curTokenNdx);
+            if (token.hidden == visible) {
+                if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
+                        "Wallpaper token " + token + " hidden=" + !visible);
+                token.hidden = !visible;
+                // Need to do a layout to ensure the wallpaper now has the correct size.
+                mService.getDefaultDisplayContentLocked().layoutNeeded = true;
+            }
+
+            final WindowList tokenWindows = token.windows;
+            for (int wallpaperNdx = tokenWindows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+                WindowState wallpaper = tokenWindows.get(wallpaperNdx);
+
+                if (visible) {
+                    updateWallpaperOffset(wallpaper, dw, dh, false);
+                }
+
+                // First, make sure the client has the current visibility state.
+                dispatchWallpaperVisibility(wallpaper, visible);
+
+                wallpaper.mWinAnimator.mAnimLayer =
+                        wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
+                if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
+                        + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
+
+                // First, if this window is at the current index, then all is well.
+                if (wallpaper == wallpaperTarget) {
+                    wallpaperTargetIndex--;
+                    wallpaperTarget = wallpaperTargetIndex > 0
+                            ? windows.get(wallpaperTargetIndex - 1) : null;
+                    continue;
+                }
+
+                // The window didn't match...  the current wallpaper window,
+                // wherever it is, is in the wrong place, so make sure it is not in the list.
+                int oldIndex = windows.indexOf(wallpaper);
+                if (oldIndex >= 0) {
+                    if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
+                            "Wallpaper removing at " + oldIndex + ": " + wallpaper);
+                    windows.remove(oldIndex);
+                    mService.mWindowsChanged = true;
+                    if (oldIndex < wallpaperTargetIndex) {
+                        wallpaperTargetIndex--;
+                    }
+                }
+
+                // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
+                // layer. For keyguard over wallpaper put the wallpaper under the keyguard.
+                int insertionIndex = 0;
+                if (visible && wallpaperTarget != null) {
+                    final int type = wallpaperTarget.mAttrs.type;
+                    final int privateFlags = wallpaperTarget.mAttrs.privateFlags;
+                    if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
+                            || type == TYPE_KEYGUARD_SCRIM) {
+                        insertionIndex = windows.indexOf(wallpaperTarget);
+                    }
+                }
+                if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
+                        "Moving wallpaper " + wallpaper
+                        + " from " + oldIndex + " to " + insertionIndex);
+
+                windows.add(insertionIndex, wallpaper);
+                mService.mWindowsChanged = true;
+                changed = true;
+            }
+        }
+
+        return changed;
+    }
+
+    boolean adjustWallpaperWindows() {
+        mService.mInnerFields.mWallpaperMayChange = false;
+
+        final WindowList windows = mService.getDefaultWindowListLocked();
+        // First find top-most window that has asked to be on top of the wallpaper;
+        // all wallpapers go behind it.
+        findWallpaperTarget(windows, mFindResults);
+        final boolean targetChanged = updateWallpaperWindowsTarget(windows, mFindResults);
+        final boolean visible = updateWallpaperWindowsTargetByLayer(windows, mFindResults);
+        WindowState wallpaperTarget = mFindResults.wallpaperTarget;
+        int wallpaperTargetIndex = mFindResults.wallpaperTargetIndex;
+
+        if (wallpaperTarget == null && mFindResults.topWallpaper != null) {
+            // There is no wallpaper target, so it goes at the bottom.
+            // We will assume it is the same place as last time, if known.
+            wallpaperTarget = mFindResults.topWallpaper;
+            wallpaperTargetIndex = mFindResults.topWallpaperIndex + 1;
+        } else {
+            // Okay i is the position immediately above the wallpaper.
+            // Look at what is below it for later.
+            wallpaperTarget = wallpaperTargetIndex > 0
+                    ? windows.get(wallpaperTargetIndex - 1) : null;
+        }
+
+        if (visible) {
+            if (mWallpaperTarget.mWallpaperX >= 0) {
+                mLastWallpaperX = mWallpaperTarget.mWallpaperX;
+                mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
+            }
+            if (mWallpaperTarget.mWallpaperY >= 0) {
+                mLastWallpaperY = mWallpaperTarget.mWallpaperY;
+                mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
+            }
+            if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+                mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
+            }
+            if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+                mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
+            }
+        }
+
+        final boolean changed = updateWallpaperWindowsPlacement(
+                windows, wallpaperTarget, wallpaperTargetIndex, visible);
+
+        if (targetChanged && DEBUG_WALLPAPER_LIGHT)  Slog.d(TAG, "New wallpaper: target="
+                + mWallpaperTarget + " lower=" + mLowerWallpaperTarget + " upper="
+                + mUpperWallpaperTarget);
+
+        return changed;
+    }
+
+    boolean processWallpaperDrawPendingTimeout() {
+        if (mWallpaperDrawState == WALLPAPER_DRAW_PENDING) {
+            mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
+            if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
+                    "*** WALLPAPER DRAW TIMEOUT");
+            return true;
+        }
+        return false;
+    }
+
+    boolean wallpaperTransitionReady() {
+        boolean transitionReady = true;
+        boolean wallpaperReady = true;
+        for (int curTokenIndex = mWallpaperTokens.size() - 1;
+                curTokenIndex >= 0 && wallpaperReady; curTokenIndex--) {
+            WindowToken token = mWallpaperTokens.get(curTokenIndex);
+            for (int curWallpaperIndex = token.windows.size() - 1; curWallpaperIndex >= 0;
+                    curWallpaperIndex--) {
+                WindowState wallpaper = token.windows.get(curWallpaperIndex);
+                if (wallpaper.mWallpaperVisible && !wallpaper.isDrawnLw()) {
+                    // We've told this wallpaper to be visible, but it is not drawn yet
+                    wallpaperReady = false;
+                    if (mWallpaperDrawState != WALLPAPER_DRAW_TIMEOUT) {
+                        // wait for this wallpaper until it is drawn or timeout
+                        transitionReady = false;
+                    }
+                    if (mWallpaperDrawState == WALLPAPER_DRAW_NORMAL) {
+                        mWallpaperDrawState = WALLPAPER_DRAW_PENDING;
+                        mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
+                        mService.mH.sendEmptyMessageDelayed(WALLPAPER_DRAW_PENDING_TIMEOUT,
+                                WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION);
+                    }
+                    if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
+                            "Wallpaper should be visible but has not been drawn yet. " +
+                                    "mWallpaperDrawState=" + mWallpaperDrawState);
+                    break;
+                }
+            }
+        }
+        if (wallpaperReady) {
+            mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
+            mService.mH.removeMessages(WALLPAPER_DRAW_PENDING_TIMEOUT);
+        }
+
+        return transitionReady;
+    }
+
+    void addWallpaperToken(WindowToken token) {
+        mWallpaperTokens.add(token);
+    }
+
+    void removeWallpaperToken(WindowToken token) {
+        mWallpaperTokens.remove(token);
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget);
+        if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
+            pw.print(prefix); pw.print("mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
+            pw.print(prefix); pw.print("mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
+        }
+        pw.print(prefix); pw.print("mLastWallpaperX="); pw.print(mLastWallpaperX);
+        pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
+        if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
+                || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+            pw.print(prefix);
+            pw.print("mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
+            pw.print(" mLastWallpaperDisplayOffsetY="); pw.println(mLastWallpaperDisplayOffsetY);
+        }
+    }
+
+    void dumpTokens(PrintWriter pw, String prefix, boolean dumpAll) {
+        if (!mWallpaperTokens.isEmpty()) {
+            pw.println();
+            pw.print(prefix); pw.println("Wallpaper tokens:");
+            for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
+                WindowToken token = mWallpaperTokens.get(i);
+                pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
+                pw.print(' '); pw.print(token);
+                if (dumpAll) {
+                    pw.println(':');
+                    token.dump(pw, "    ");
+                } else {
+                    pw.println();
+                }
+            }
+        }
+    }
+
+    /** Helper class for storing the results of a wallpaper target find operation. */
+    final private static class FindWallpaperTargetResult {
+        int topWallpaperIndex = 0;
+        WindowState topWallpaper = null;
+        int wallpaperTargetIndex = 0;
+        WindowState wallpaperTarget = null;
+
+        void setTopWallpaper(WindowState win, int index) {
+            topWallpaper = win;
+            topWallpaperIndex = index;
+        }
+
+        void setWallpaperTarget(WindowState win, int index) {
+            wallpaperTarget = win;
+            wallpaperTargetIndex = index;
+        }
+
+        void reset() {
+            topWallpaperIndex = 0;
+            topWallpaper = null;
+            wallpaperTargetIndex = 0;
+            wallpaperTarget = null;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 7578256..e6a1be1 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -258,6 +258,7 @@
         boolean startingInUnForceHiding = false;
         ArrayList<WindowStateAnimator> unForceHiding = null;
         WindowState wallpaper = null;
+        final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
         for (int i = windows.size() - 1; i >= 0; i--) {
             WindowState win = windows.get(i);
             WindowStateAnimator winAnimator = win.mWinAnimator;
@@ -294,7 +295,8 @@
                             ", nowAnimating=" + nowAnimating);
                 }
 
-                if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
+                if (wasAnimating && !winAnimator.mAnimating
+                        && wallpaperController.isWallpaperTarget(win)) {
                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                     setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 355b09b..a200678 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -78,6 +78,7 @@
 import android.util.SparseIntArray;
 import android.util.TimeUtils;
 import android.util.TypedValue;
+import android.view.AppTransitionAnimationSpec;
 import android.view.Choreographer;
 import android.view.Display;
 import android.view.DisplayInfo;
@@ -113,6 +114,7 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 
+import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
 import com.android.internal.app.IAssistScreenshotReceiver;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.FastPrintWriter;
@@ -176,7 +178,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
@@ -443,6 +444,7 @@
 
     final float[] mTmpFloats = new float[9];
     final Rect mTmpContentRect = new Rect();
+    private final Rect mTmpStartRect = new Rect();
 
     boolean mDisplayReady;
     boolean mSafeMode;
@@ -579,48 +581,10 @@
         }
     }
 
-    private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
+    WallpaperController mWallpaperControllerLocked;
 
-    // If non-null, this is the currently visible window that is associated
-    // with the wallpaper.
-    WindowState mWallpaperTarget = null;
-    // If non-null, we are in the middle of animating from one wallpaper target
-    // to another, and this is the lower one in Z-order.
-    WindowState mLowerWallpaperTarget = null;
-    // If non-null, we are in the middle of animating from one wallpaper target
-    // to another, and this is the higher one in Z-order.
-    WindowState mUpperWallpaperTarget = null;
-    int mWallpaperAnimLayerAdjustment;
-    float mLastWallpaperX = -1;
-    float mLastWallpaperY = -1;
-    float mLastWallpaperXStep = -1;
-    float mLastWallpaperYStep = -1;
-    int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
-    int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
-    // This is set when we are waiting for a wallpaper to tell us it is done
-    // changing its scroll position.
-    WindowState mWaitingOnWallpaper;
-    // The last time we had a timeout when waiting for a wallpaper.
-    long mLastWallpaperTimeoutTime;
-    // We give a wallpaper up to 150ms to finish scrolling.
-    static final long WALLPAPER_TIMEOUT = 150;
-    // Time we wait after a timeout before trying to wait again.
-    static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
     boolean mAnimateWallpaperWithTarget;
 
-    // We give a wallpaper up to 500ms to finish drawing before playing app transitions.
-    static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500;
-    static final int WALLPAPER_DRAW_NORMAL = 0;
-    static final int WALLPAPER_DRAW_PENDING = 1;
-    static final int WALLPAPER_DRAW_TIMEOUT = 2;
-    int mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
-
-    // Set to the wallpaper window we would like to hide once the transition animations are done.
-    // This is useful in cases where we don't want the wallpaper to be hidden when the close app
-    // is a wallpaper target and is done animating out, but the opening app isn't a wallpaper
-    // target and isn't done animating in.
-    WindowState mDeferredHideWallpaper = null;
-
     AppWindowToken mFocusedApp = null;
 
     PowerManager mPowerManager;
@@ -634,6 +598,7 @@
     final InputManagerService mInputManager;
     final DisplayManagerInternal mDisplayManagerInternal;
     final DisplayManager mDisplayManager;
+    final Display[] mDisplays;
 
     // Who is holding the screen on.
     Session mHoldingScreenOn;
@@ -804,7 +769,7 @@
 
     private ViewServer mViewServer;
     private final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
-    private boolean mWindowsChanged = false;
+    boolean mWindowsChanged = false;
 
     public interface WindowChangeListener {
         public void windowsChanged();
@@ -907,8 +872,8 @@
 
         mFxSession = new SurfaceSession();
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
-        Display[] displays = mDisplayManager.getDisplays();
-        for (Display display : displays) {
+        mDisplays = mDisplayManager.getDisplays();
+        for (Display display : mDisplays) {
             createDisplayContentLocked(display);
         }
 
@@ -988,6 +953,8 @@
 
         updateCircularDisplayMaskIfNeeded();
         showEmulatorDisplayOverlayIfNeeded();
+
+        mWallpaperControllerLocked = new WallpaperController(this);
     }
 
     public InputMonitor getInputMonitor() {
@@ -1767,578 +1734,6 @@
         return true;
     }
 
-    private boolean isWallpaperVisible(WindowState wallpaperTarget) {
-        if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
-                + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
-                + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
-                        ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
-                + " upper=" + mUpperWallpaperTarget
-                + " lower=" + mLowerWallpaperTarget);
-        return (wallpaperTarget != null
-                        && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
-                                && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
-                || mUpperWallpaperTarget != null
-                || mLowerWallpaperTarget != null;
-    }
-
-    void hideWallpapersLocked(final WindowState winGoingAway) {
-        if (mWallpaperTarget != null
-                && (mWallpaperTarget != winGoingAway || mLowerWallpaperTarget != null)) {
-            return;
-        }
-        if (mAppTransition.isRunning()) {
-            // Defer hiding the wallpaper when app transition is running until the animations
-            // are done.
-            mDeferredHideWallpaper = winGoingAway;
-            return;
-        }
-
-        final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
-        for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
-            final WindowToken token = mWallpaperTokens.get(i);
-            for (int j = token.windows.size() - 1; j >= 0; j--) {
-                final WindowState wallpaper = token.windows.get(j);
-                final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
-                if (!winAnimator.mLastHidden || wasDeferred) {
-                    winAnimator.hide();
-                    dispatchWallpaperVisibility(wallpaper, false);
-                    final DisplayContent displayContent = wallpaper.getDisplayContent();
-                    if (displayContent != null) {
-                        displayContent.pendingLayoutChanges |=
-                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-                    }
-                }
-            }
-            if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
-                    + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
-                    + mLowerWallpaperTarget + "\n" + Debug.getCallers(5, "  "));
-            token.hidden = true;
-        }
-    }
-
-    boolean adjustWallpaperWindowsLocked() {
-        mInnerFields.mWallpaperMayChange = false;
-        boolean targetChanged = false;
-
-        // TODO(multidisplay): Wallpapers on main screen only.
-        final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
-        final int dw = displayInfo.logicalWidth;
-        final int dh = displayInfo.logicalHeight;
-
-        // First find top-most window that has asked to be on top of the
-        // wallpaper; all wallpapers go behind it.
-        final WindowList windows = getDefaultWindowListLocked();
-        int N = windows.size();
-        WindowState w = null;
-        WindowState foundW = null;
-        int foundI = 0;
-        WindowState topCurW = null;
-        int topCurI = 0;
-        int windowDetachedI = -1;
-        int i = N;
-        while (i > 0) {
-            i--;
-            w = windows.get(i);
-            if ((w.mAttrs.type == TYPE_WALLPAPER)) {
-                if (topCurW == null) {
-                    topCurW = w;
-                    topCurI = i;
-                }
-                continue;
-            }
-            topCurW = null;
-            if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
-                // If this window's app token is hidden and not animating,
-                // it is of no interest to us.
-                if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
-                    if (DEBUG_WALLPAPER) Slog.v(TAG,
-                            "Skipping hidden and not animating token: " + w);
-                    continue;
-                }
-            }
-            if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
-                    + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
-
-            // If the app is executing an animation because the keyguard is going away, keep the
-            // wallpaper during the animation so it doesn't flicker out.
-            final boolean hasWallpaper = (w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
-                    || (w.mAppToken != null
-                            && w.mWinAnimator.mKeyguardGoingAwayAnimation);
-            if (hasWallpaper && w.isOnScreen()
-                    && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
-                if (DEBUG_WALLPAPER) Slog.v(TAG,
-                        "Found wallpaper target: #" + i + "=" + w);
-                foundW = w;
-                foundI = i;
-                if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
-                    // The current wallpaper target is animating, so we'll
-                    // look behind it for another possible target and figure
-                    // out what is going on below.
-                    if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
-                            + ": token animating, looking behind.");
-                    continue;
-                }
-                break;
-            } else if (w == mAnimator.mWindowDetachedWallpaper) {
-                windowDetachedI = i;
-            }
-        }
-
-        if (foundW == null && windowDetachedI >= 0) {
-            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
-                    "Found animating detached wallpaper activity: #" + i + "=" + w);
-            foundW = w;
-            foundI = windowDetachedI;
-        }
-
-        if (mWallpaperTarget != foundW
-                && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) {
-            if (DEBUG_WALLPAPER_LIGHT) {
-                Slog.v(TAG, "New wallpaper target: " + foundW
-                        + " oldTarget: " + mWallpaperTarget);
-            }
-
-            mLowerWallpaperTarget = null;
-            mUpperWallpaperTarget = null;
-
-            WindowState oldW = mWallpaperTarget;
-            mWallpaperTarget = foundW;
-            targetChanged = true;
-
-            // Now what is happening...  if the current and new targets are
-            // animating, then we are in our super special mode!
-            if (foundW != null && oldW != null) {
-                boolean oldAnim = oldW.isAnimatingLw();
-                boolean foundAnim = foundW.isAnimatingLw();
-                if (DEBUG_WALLPAPER_LIGHT) {
-                    Slog.v(TAG, "New animation: " + foundAnim
-                            + " old animation: " + oldAnim);
-                }
-                if (foundAnim && oldAnim) {
-                    int oldI = windows.indexOf(oldW);
-                    if (DEBUG_WALLPAPER_LIGHT) {
-                        Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
-                    }
-                    if (oldI >= 0) {
-                        if (DEBUG_WALLPAPER_LIGHT) {
-                            Slog.v(TAG, "Animating wallpapers: old#" + oldI
-                                    + "=" + oldW + "; new#" + foundI
-                                    + "=" + foundW);
-                        }
-
-                        // Set the new target correctly.
-                        if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
-                            if (DEBUG_WALLPAPER_LIGHT) {
-                                Slog.v(TAG, "Old wallpaper still the target.");
-                            }
-                            mWallpaperTarget = oldW;
-                            foundW = oldW;
-                            foundI = oldI;
-                        }
-                        // Now set the upper and lower wallpaper targets
-                        // correctly, and make sure that we are positioning
-                        // the wallpaper below the lower.
-                        else if (foundI > oldI) {
-                            // The new target is on top of the old one.
-                            if (DEBUG_WALLPAPER_LIGHT) {
-                                Slog.v(TAG, "Found target above old target.");
-                            }
-                            mUpperWallpaperTarget = foundW;
-                            mLowerWallpaperTarget = oldW;
-                            foundW = oldW;
-                            foundI = oldI;
-                        } else {
-                            // The new target is below the old one.
-                            if (DEBUG_WALLPAPER_LIGHT) {
-                                Slog.v(TAG, "Found target below old target.");
-                            }
-                            mUpperWallpaperTarget = oldW;
-                            mLowerWallpaperTarget = foundW;
-                        }
-                    }
-                }
-            }
-
-        } else if (mLowerWallpaperTarget != null) {
-            // Is it time to stop animating?
-            if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
-                if (DEBUG_WALLPAPER_LIGHT) {
-                    Slog.v(TAG, "No longer animating wallpaper targets!");
-                }
-                mLowerWallpaperTarget = null;
-                mUpperWallpaperTarget = null;
-                mWallpaperTarget = foundW;
-                targetChanged = true;
-            }
-        }
-
-        boolean visible = foundW != null;
-        if (visible) {
-            // The window is visible to the compositor...  but is it visible
-            // to the user?  That is what the wallpaper cares about.
-            visible = isWallpaperVisible(foundW);
-            if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
-
-            // If the wallpaper target is animating, we may need to copy
-            // its layer adjustment.  Only do this if we are not transfering
-            // between two wallpaper targets.
-            mWallpaperAnimLayerAdjustment =
-                    (mLowerWallpaperTarget == null && foundW.mAppToken != null)
-                    ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
-
-            final int maxLayer = mPolicy.getMaxWallpaperLayer()
-                    * TYPE_LAYER_MULTIPLIER
-                    + TYPE_LAYER_OFFSET;
-
-            // Now w is the window we are supposed to be behind...  but we
-            // need to be sure to also be behind any of its attached windows,
-            // AND any starting window associated with it, AND below the
-            // maximum layer the policy allows for wallpapers.
-            while (foundI > 0) {
-                WindowState wb = windows.get(foundI - 1);
-                if (wb.mBaseLayer < maxLayer &&
-                        wb.mAttachedWindow != foundW &&
-                        (foundW.mAttachedWindow == null ||
-                                wb.mAttachedWindow != foundW.mAttachedWindow) &&
-                        (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
-                                foundW.mToken == null || wb.mToken != foundW.mToken)) {
-                    // This window is not related to the previous one in any
-                    // interesting way, so stop here.
-                    break;
-                }
-                foundW = wb;
-                foundI--;
-            }
-        } else {
-            if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
-        }
-
-        if (foundW == null && topCurW != null) {
-            // There is no wallpaper target, so it goes at the bottom.
-            // We will assume it is the same place as last time, if known.
-            foundW = topCurW;
-            foundI = topCurI+1;
-        } else {
-            // Okay i is the position immediately above the wallpaper.  Look at
-            // what is below it for later.
-            foundW = foundI > 0 ? windows.get(foundI - 1) : null;
-        }
-
-        if (visible) {
-            if (mWallpaperTarget.mWallpaperX >= 0) {
-                mLastWallpaperX = mWallpaperTarget.mWallpaperX;
-                mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
-            }
-            if (mWallpaperTarget.mWallpaperY >= 0) {
-                mLastWallpaperY = mWallpaperTarget.mWallpaperY;
-                mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
-            }
-            if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
-                mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
-            }
-            if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
-                mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
-            }
-        }
-
-        // Start stepping backwards from here, ensuring that our wallpaper windows
-        // are correctly placed.
-        boolean changed = false;
-        for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            WindowToken token = mWallpaperTokens.get(curTokenNdx);
-            if (token.hidden == visible) {
-                if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
-                        "Wallpaper token " + token + " hidden=" + !visible);
-                token.hidden = !visible;
-                // Need to do a layout to ensure the wallpaper now has the correct size.
-                getDefaultDisplayContentLocked().layoutNeeded = true;
-            }
-
-            final WindowList tokenWindows = token.windows;
-            for (int wallpaperNdx = tokenWindows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-                WindowState wallpaper = tokenWindows.get(wallpaperNdx);
-
-                if (visible) {
-                    updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
-                }
-
-                // First, make sure the client has the current visibility state.
-                dispatchWallpaperVisibility(wallpaper, visible);
-
-                wallpaper.mWinAnimator.mAnimLayer =
-                        wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
-                if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
-                        + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
-
-                // First, if this window is at the current index, then all is well.
-                if (wallpaper == foundW) {
-                    foundI--;
-                    foundW = foundI > 0 ? windows.get(foundI - 1) : null;
-                    continue;
-                }
-
-                // The window didn't match...  the current wallpaper window,
-                // wherever it is, is in the wrong place, so make sure it is
-                // not in the list.
-                int oldIndex = windows.indexOf(wallpaper);
-                if (oldIndex >= 0) {
-                    if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
-                            + oldIndex + ": " + wallpaper);
-                    windows.remove(oldIndex);
-                    mWindowsChanged = true;
-                    if (oldIndex < foundI) {
-                        foundI--;
-                    }
-                }
-
-                // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
-                // layer. For keyguard over wallpaper put the wallpaper under the keyguard.
-                int insertionIndex = 0;
-                if (visible && foundW != null) {
-                    final int type = foundW.mAttrs.type;
-                    final int privateFlags = foundW.mAttrs.privateFlags;
-                    if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
-                            || type == TYPE_KEYGUARD_SCRIM) {
-                        insertionIndex = windows.indexOf(foundW);
-                    }
-                }
-                if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
-                    Slog.v(TAG, "Moving wallpaper " + wallpaper
-                            + " from " + oldIndex + " to " + insertionIndex);
-                }
-
-                windows.add(insertionIndex, wallpaper);
-                mWindowsChanged = true;
-                changed = true;
-            }
-        }
-
-        if (targetChanged && DEBUG_WALLPAPER_LIGHT)  Slog.d(TAG, "New wallpaper: target="
-                + mWallpaperTarget + " lower=" + mLowerWallpaperTarget + " upper="
-                + mUpperWallpaperTarget);
-
-        return changed;
-    }
-
-    void setWallpaperAnimLayerAdjustmentLocked(int adj) {
-        if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Setting wallpaper layer adj to " + adj);
-        mWallpaperAnimLayerAdjustment = adj;
-        for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
-            for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-                WindowState wallpaper = windows.get(wallpaperNdx);
-                wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
-                if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
-                        + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
-            }
-        }
-    }
-
-    boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
-            boolean sync) {
-        boolean changed = false;
-        boolean rawChanged = false;
-        float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
-        float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
-        int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
-        int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
-        if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
-            offset += mLastWallpaperDisplayOffsetX;
-        }
-        changed = wallpaperWin.mXOffset != offset;
-        if (changed) {
-            if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
-                    + wallpaperWin + " x: " + offset);
-            wallpaperWin.mXOffset = offset;
-        }
-        if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
-            wallpaperWin.mWallpaperX = wpx;
-            wallpaperWin.mWallpaperXStep = wpxs;
-            rawChanged = true;
-        }
-
-        float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
-        float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
-        int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
-        offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
-        if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
-            offset += mLastWallpaperDisplayOffsetY;
-        }
-        if (wallpaperWin.mYOffset != offset) {
-            if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
-                    + wallpaperWin + " y: " + offset);
-            changed = true;
-            wallpaperWin.mYOffset = offset;
-        }
-        if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
-            wallpaperWin.mWallpaperY = wpy;
-            wallpaperWin.mWallpaperYStep = wpys;
-            rawChanged = true;
-        }
-
-        if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
-                    WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
-            try {
-                if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
-                        + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
-                        + " y=" + wallpaperWin.mWallpaperY);
-                if (sync) {
-                    mWaitingOnWallpaper = wallpaperWin;
-                }
-                wallpaperWin.mClient.dispatchWallpaperOffsets(
-                        wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
-                        wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
-                if (sync) {
-                    if (mWaitingOnWallpaper != null) {
-                        long start = SystemClock.uptimeMillis();
-                        if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
-                                < start) {
-                            try {
-                                if (DEBUG_WALLPAPER) Slog.v(TAG,
-                                        "Waiting for offset complete...");
-                                mWindowMap.wait(WALLPAPER_TIMEOUT);
-                            } catch (InterruptedException e) {
-                            }
-                            if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
-                            if ((start+WALLPAPER_TIMEOUT)
-                                    < SystemClock.uptimeMillis()) {
-                                Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
-                                        + wallpaperWin);
-                                mLastWallpaperTimeoutTime = start;
-                            }
-                        }
-                        mWaitingOnWallpaper = null;
-                    }
-                }
-            } catch (RemoteException e) {
-            }
-        }
-
-        return changed;
-    }
-
-    void wallpaperOffsetsComplete(IBinder window) {
-        synchronized (mWindowMap) {
-            if (mWaitingOnWallpaper != null &&
-                    mWaitingOnWallpaper.mClient.asBinder() == window) {
-                mWaitingOnWallpaper = null;
-                mWindowMap.notifyAll();
-            }
-        }
-    }
-
-    void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
-        final DisplayContent displayContent = changingTarget.getDisplayContent();
-        if (displayContent == null) {
-            return;
-        }
-        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-        final int dw = displayInfo.logicalWidth;
-        final int dh = displayInfo.logicalHeight;
-
-        WindowState target = mWallpaperTarget;
-        if (target != null) {
-            if (target.mWallpaperX >= 0) {
-                mLastWallpaperX = target.mWallpaperX;
-            } else if (changingTarget.mWallpaperX >= 0) {
-                mLastWallpaperX = changingTarget.mWallpaperX;
-            }
-            if (target.mWallpaperY >= 0) {
-                mLastWallpaperY = target.mWallpaperY;
-            } else if (changingTarget.mWallpaperY >= 0) {
-                mLastWallpaperY = changingTarget.mWallpaperY;
-            }
-            if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
-                mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
-            } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
-                mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
-            }
-            if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
-                mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
-            } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
-                mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
-            }
-            if (target.mWallpaperXStep >= 0) {
-                mLastWallpaperXStep = target.mWallpaperXStep;
-            } else if (changingTarget.mWallpaperXStep >= 0) {
-                mLastWallpaperXStep = changingTarget.mWallpaperXStep;
-            }
-            if (target.mWallpaperYStep >= 0) {
-                mLastWallpaperYStep = target.mWallpaperYStep;
-            } else if (changingTarget.mWallpaperYStep >= 0) {
-                mLastWallpaperYStep = changingTarget.mWallpaperYStep;
-            }
-        }
-
-        for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
-            for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-                WindowState wallpaper = windows.get(wallpaperNdx);
-                if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
-                    WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
-                    winAnimator.computeShownFrameLocked();
-                    // No need to lay out the windows - we can just set the wallpaper position
-                    // directly.
-                    winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
-                    // We only want to be synchronous with one wallpaper.
-                    sync = false;
-                }
-            }
-        }
-    }
-
-    /**
-     * Check wallpaper for visibility change and notify window if so.
-     * @param wallpaper The wallpaper to test and notify.
-     * @param visible Current visibility.
-     */
-    void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
-        // Only send notification if the visibility actually changed and we are not trying to hide
-        // the wallpaper when we are deferring hiding of the wallpaper.
-        if (wallpaper.mWallpaperVisible != visible
-                && (mDeferredHideWallpaper == null || visible)) {
-            wallpaper.mWallpaperVisible = visible;
-            try {
-                if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
-                        "Updating vis of wallpaper " + wallpaper
-                        + ": " + visible + " from:\n" + Debug.getCallers(4, "  "));
-                wallpaper.mClient.dispatchAppVisibility(visible);
-            } catch (RemoteException e) {
-            }
-        }
-    }
-
-    private void updateWallpaperVisibilityLocked() {
-        final boolean visible = isWallpaperVisible(mWallpaperTarget);
-        final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
-        if (displayContent == null) {
-            return;
-        }
-        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-        final int dw = displayInfo.logicalWidth;
-        final int dh = displayInfo.logicalHeight;
-
-        for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            WindowToken token = mWallpaperTokens.get(curTokenNdx);
-            if (token.hidden == visible) {
-                token.hidden = !visible;
-                // Need to do a layout to ensure the wallpaper now has the
-                // correct size.
-                displayContent.layoutNeeded = true;
-            }
-
-            final WindowList windows = token.windows;
-            for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-                WindowState wallpaper = windows.get(wallpaperNdx);
-                if (visible) {
-                    updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
-                }
-
-                dispatchWallpaperVisibility(wallpaper, visible);
-            }
-        }
-    }
-
     public int addWindow(Session session, IWindow client, int seq,
             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
             Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
@@ -2561,12 +1956,11 @@
             } else {
                 addWindowToListInOrderLocked(win, true);
                 if (type == TYPE_WALLPAPER) {
-                    mLastWallpaperTimeoutTime = 0;
+                    mWallpaperControllerLocked.clearLastWallpaperTimeoutTime();
                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-                } else if (mWallpaperTarget != null
-                        && mWallpaperTarget.mLayer >= win.mBaseLayer) {
+                } else if (mWallpaperControllerLocked.isBelowWallpaperTarget(win)) {
                     // If there is currently a wallpaper being shown, and
                     // the base layer of the new window is below the current
                     // layer of the target window, then adjust the wallpaper.
@@ -2863,7 +2257,7 @@
         }
 
         if (win.mAttrs.type == TYPE_WALLPAPER) {
-            mLastWallpaperTimeoutTime = 0;
+            mWallpaperControllerLocked.clearLastWallpaperTimeoutTime();
             getDefaultDisplayContentLocked().pendingLayoutChanges |=
                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
         } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
@@ -2983,62 +2377,6 @@
         }
     }
 
-    public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
-            float xStep, float yStep) {
-        if (window.mWallpaperX != x || window.mWallpaperY != y)  {
-            window.mWallpaperX = x;
-            window.mWallpaperY = y;
-            window.mWallpaperXStep = xStep;
-            window.mWallpaperYStep = yStep;
-            updateWallpaperOffsetLocked(window, true);
-        }
-    }
-
-    void wallpaperCommandComplete(IBinder window, Bundle result) {
-        synchronized (mWindowMap) {
-            if (mWaitingOnWallpaper != null &&
-                    mWaitingOnWallpaper.mClient.asBinder() == window) {
-                mWaitingOnWallpaper = null;
-                mWindowMap.notifyAll();
-            }
-        }
-    }
-
-    public void setWindowWallpaperDisplayOffsetLocked(WindowState window, int x, int y) {
-        if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y)  {
-            window.mWallpaperDisplayOffsetX = x;
-            window.mWallpaperDisplayOffsetY = y;
-            updateWallpaperOffsetLocked(window, true);
-        }
-    }
-
-    public Bundle sendWindowWallpaperCommandLocked(WindowState window,
-            String action, int x, int y, int z, Bundle extras, boolean sync) {
-        if (window == mWallpaperTarget || window == mLowerWallpaperTarget
-                || window == mUpperWallpaperTarget) {
-            boolean doWait = sync;
-            for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-                final WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
-                for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-                    WindowState wallpaper = windows.get(wallpaperNdx);
-                    try {
-                        wallpaper.mClient.dispatchWallpaperCommand(action,
-                                x, y, z, extras, sync);
-                        // We only want to be synchronous with one wallpaper.
-                        sync = false;
-                    } catch (RemoteException e) {
-                    }
-                }
-            }
-
-            if (doWait) {
-                // XXX Need to wait for result.
-            }
-        }
-
-        return null;
-    }
-
     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
         synchronized (mWindowMap) {
             if (mAccessibilityController != null) {
@@ -3293,7 +2631,7 @@
                             // Currently in a hide animation... turn this into
                             // an exit.
                             win.mExiting = true;
-                        } else if (win == mWallpaperTarget) {
+                        } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
                             // If the wallpaper is currently behind this
                             // window, we need to change both of them inside
                             // of a transaction to avoid artifacts.
@@ -3351,8 +2689,8 @@
             performLayoutAndPlaceSurfacesLocked();
             if (toBeDisplayed && win.mIsWallpaper) {
                 DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
-                updateWallpaperOffsetLocked(win,
-                        displayInfo.logicalWidth, displayInfo.logicalHeight, false);
+                mWallpaperControllerLocked.updateWallpaperOffset(
+                        win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
             }
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
@@ -3495,7 +2833,8 @@
             final boolean resizedWindow = !fullscreen && !dialogWindow;
             Animation a = mAppTransition.loadAnimation(lp, transit, enter, containingWidth,
                     containingHeight, mCurConfiguration.orientation, containingFrame, contentInsets,
-                    surfaceInsets, appFrame, isVoiceInteraction, resizedWindow);
+                    surfaceInsets, appFrame, isVoiceInteraction, resizedWindow,
+                    atoken.mTask.mTaskId);
             if (a != null) {
                 if (DEBUG_ANIM) {
                     RuntimeException e = null;
@@ -3629,7 +2968,7 @@
             wtoken = new WindowToken(this, token, type, true);
             mTokenMap.put(token, wtoken);
             if (type == TYPE_WALLPAPER) {
-                mWallpaperTokens.add(wtoken);
+                mWallpaperControllerLocked.addWallpaperToken(wtoken);
             }
         }
     }
@@ -3685,10 +3024,10 @@
                     if (delayed && displayContent != null) {
                         displayContent.mExitingTokens.add(wtoken);
                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
-                        mWallpaperTokens.remove(wtoken);
+                        mWallpaperControllerLocked.removeWallpaperToken(wtoken);
                     }
                 } else if (wtoken.windowType == TYPE_WALLPAPER) {
-                    mWallpaperTokens.remove(wtoken);
+                    mWallpaperControllerLocked.removeWallpaperToken(wtoken);
                 }
 
                 mInputMonitor.updateInputWindowsLw(true /*force*/);
@@ -4219,6 +3558,14 @@
     }
 
     @Override
+    public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
+            IRemoteCallback callback, boolean scaleUp) {
+        synchronized (mWindowMap) {
+            mAppTransition.overridePendingAppTransitionMultiThumb(specs, callback, scaleUp);
+        }
+    }
+
+    @Override
     public void overridePendingAppTransitionInPlace(String packageName, int anim) {
         synchronized(mWindowMap) {
             mAppTransition.overrideInPlaceAppTransition(packageName, anim);
@@ -4427,7 +3774,7 @@
                 }
                 if (ent.array.getBoolean(
                         com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
-                    if (mWallpaperTarget == null) {
+                    if (mWallpaperControllerLocked.getWallpaperTarget() == null) {
                         // If this theme is requesting a wallpaper, and the wallpaper
                         // is not curently visible, then this effectively serves as
                         // an opaque window and our starting window transition animation
@@ -5853,6 +5200,7 @@
 
             if (!mBootAnimationStopped) {
                 // Do this one time.
+                Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
                 try {
                     IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
                     if (surfaceFlinger != null) {
@@ -5875,6 +5223,7 @@
             }
 
             EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
+            Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
             mDisplayEnabled = true;
             if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
 
@@ -6286,7 +5635,7 @@
                         int right = wf.right - cr.right;
                         int bottom = wf.bottom - cr.bottom;
                         frame.union(left, top, right, bottom);
-                        ws.getTaskBounds(stackBounds);
+                        ws.getTaskBounds(stackBounds, !BOUNDS_FOR_TOUCH);
                         if (!frame.intersect(stackBounds)) {
                             // Set frame empty if there's no intersection.
                             frame.setEmpty();
@@ -7656,7 +7005,9 @@
     }
 
     public void displayReady() {
-        displayReady(Display.DEFAULT_DISPLAY);
+        for (Display display : mDisplays) {
+            displayReady(display.getDisplayId());
+        }
 
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDefaultDisplayContentLocked();
@@ -8282,10 +7633,7 @@
                 break;
                 case WALLPAPER_DRAW_PENDING_TIMEOUT: {
                     synchronized (mWindowMap) {
-                        if (mWallpaperDrawState == WALLPAPER_DRAW_PENDING) {
-                            mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
-                            if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
-                                    "*** WALLPAPER DRAW TIMEOUT");
+                        if (mWallpaperControllerLocked.processWallpaperDrawPendingTimeout()) {
                             performLayoutAndPlaceSurfacesLocked();
                         }
                     }
@@ -8908,7 +8256,7 @@
             if (w.mIsImWindow) {
                 winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
             } else if (w.mIsWallpaper) {
-                winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
+                winAnimator.mAnimLayer += mWallpaperControllerLocked.getAnimLayerAdjustment();
             }
             if (winAnimator.mAnimLayer != oldLayer) {
                 layerChanged = true;
@@ -9209,404 +8557,399 @@
      * @return bitmap indicating if another pass through layout must be made.
      */
     public int handleAppTransitionReadyLocked(WindowList windows) {
-        int changes = 0;
-        int i;
         int appsCount = mOpeningApps.size();
-        boolean goodToGo = true;
+        if (!checkIfTransitionGoodToGo(appsCount)) {
+            return 0;
+        }
+        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
+        int transit = mAppTransition.getAppTransition();
+        if (mSkipAppTransitionAnimation) {
+            transit = AppTransition.TRANSIT_UNSET;
+        }
+        mSkipAppTransitionAnimation = false;
+        mNoAnimationNotifyOnTransitionFinished.clear();
+
+        mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
+
+        rebuildAppWindowListLocked();
+
+        mInnerFields.mWallpaperMayChange = false;
+
+        // The top-most window will supply the layout params,
+        // and we will determine it below.
+        LayoutParams animLp = null;
+        int bestAnimLayer = -1;
+        boolean fullscreenAnim = false;
+        boolean voiceInteraction = false;
+
+        final WindowState lowerWallpaperTarget =
+                mWallpaperControllerLocked.getLowerWallpaperTarget();
+        final WindowState upperWallpaperTarget =
+                mWallpaperControllerLocked.getUpperWallpaperTarget();
+
+        boolean openingAppHasWallpaper = false;
+        boolean closingAppHasWallpaper = false;
+        final AppWindowToken lowerWallpaperAppToken;
+        final AppWindowToken upperWallpaperAppToken;
+        if (lowerWallpaperTarget == null) {
+            lowerWallpaperAppToken = upperWallpaperAppToken = null;
+        } else {
+            lowerWallpaperAppToken = lowerWallpaperTarget.mAppToken;
+            upperWallpaperAppToken = upperWallpaperTarget.mAppToken;
+        }
+
+        int i;
+        // Do a first pass through the tokens for two
+        // things:
+        // (1) Determine if both the closing and opening
+        // app token sets are wallpaper targets, in which
+        // case special animations are needed
+        // (since the wallpaper needs to stay static
+        // behind them).
+        // (2) Find the layout params of the top-most
+        // application window in the tokens, which is
+        // what will control the animation theme.
+        final int closingAppsCount = mClosingApps.size();
+        appsCount = closingAppsCount + mOpeningApps.size();
+        for (i = 0; i < appsCount; i++) {
+            final AppWindowToken wtoken;
+            if (i < closingAppsCount) {
+                wtoken = mClosingApps.valueAt(i);
+                if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
+                    closingAppHasWallpaper = true;
+                }
+            } else {
+                wtoken = mOpeningApps.valueAt(i - closingAppsCount);
+                if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
+                    openingAppHasWallpaper = true;
+                }
+            }
+
+            voiceInteraction |= wtoken.voiceInteraction;
+
+            if (wtoken.appFullscreen) {
+                WindowState ws = wtoken.findMainWindow();
+                if (ws != null) {
+                    animLp = ws.mAttrs;
+                    bestAnimLayer = ws.mLayer;
+                    fullscreenAnim = true;
+                }
+            } else if (!fullscreenAnim) {
+                WindowState ws = wtoken.findMainWindow();
+                if (ws != null) {
+                    if (ws.mLayer > bestAnimLayer) {
+                        animLp = ws.mAttrs;
+                        bestAnimLayer = ws.mLayer;
+                    }
+                }
+            }
+        }
+
+        transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
+                closingAppHasWallpaper, lowerWallpaperTarget, upperWallpaperTarget);
+
+        // If all closing windows are obscured, then there is
+        // no need to do an animation.  This is the case, for
+        // example, when this transition is being done behind
+        // the lock screen.
+        if (!mPolicy.allowAppAnimationsLw()) {
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+                    "Animations disallowed by keyguard or dream.");
+            animLp = null;
+        }
+
+        processApplicationsAnimatingInPlace(transit);
+
+        AppWindowToken topClosingApp = null;
+        int topClosingLayer = 0;
+        appsCount = mClosingApps.size();
+        for (i = 0; i < appsCount; i++) {
+            AppWindowToken wtoken = mClosingApps.valueAt(i);
+            final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
+            appAnimator.clearThumbnail();
+            appAnimator.animation = null;
+            wtoken.inPendingTransaction = false;
+            setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
+            wtoken.updateReportedVisibilityLocked();
+            // Force the allDrawn flag, because we want to start
+            // this guy's animations regardless of whether it's
+            // gotten drawn.
+            wtoken.allDrawn = true;
+            wtoken.deferClearAllDrawn = false;
+            // Ensure that apps that are mid-starting are also scheduled to have their
+            // starting windows removed after the animation is complete
+            if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) {
+                scheduleRemoveStartingWindowLocked(wtoken);
+            }
+            mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
+
+            if (animLp != null) {
+                int layer = -1;
+                for (int j = 0; j < wtoken.windows.size(); j++) {
+                    WindowState win = wtoken.windows.get(j);
+                    if (win.mWinAnimator.mAnimLayer > layer) {
+                        layer = win.mWinAnimator.mAnimLayer;
+                    }
+                }
+                if (topClosingApp == null || layer > topClosingLayer) {
+                    topClosingApp = wtoken;
+                    topClosingLayer = layer;
+                }
+            }
+        }
+
+        AppWindowToken topOpeningApp = null;
+        appsCount = mOpeningApps.size();
+        for (i = 0; i < appsCount; i++) {
+            AppWindowToken wtoken = mOpeningApps.valueAt(i);
+            final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
+
+            if (!appAnimator.usingTransferredAnimation) {
+                appAnimator.clearThumbnail();
+                appAnimator.animation = null;
+            }
+            wtoken.inPendingTransaction = false;
+            if (!setTokenVisibilityLocked(
+                    wtoken, animLp, true, transit, false, voiceInteraction)){
+                // This token isn't going to be animating. Add it to the list of tokens to
+                // be notified of app transition complete since the notification will not be
+                // sent be the app window animator.
+                mNoAnimationNotifyOnTransitionFinished.add(wtoken.token);
+            }
+            wtoken.updateReportedVisibilityLocked();
+            wtoken.waitingToShow = false;
+
+            appAnimator.mAllAppWinAnimators.clear();
+            final int windowsCount = wtoken.allAppWindows.size();
+            for (int j = 0; j < windowsCount; j++) {
+                appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
+            }
+            mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+            mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
+
+            int topOpeningLayer = 0;
+            if (animLp != null) {
+                int layer = -1;
+                for (int j = 0; j < wtoken.windows.size(); j++) {
+                    WindowState win = wtoken.windows.get(j);
+                    if (win.mWinAnimator.mAnimLayer > layer) {
+                        layer = win.mWinAnimator.mAnimLayer;
+                    }
+                }
+                if (topOpeningApp == null || layer > topOpeningLayer) {
+                    topOpeningApp = wtoken;
+                    topOpeningLayer = layer;
+                }
+            }
+            createThumbnailAppAnimator(transit, wtoken, topOpeningLayer, topClosingLayer);
+        }
+
+        AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ?  null :
+                topOpeningApp.mAppAnimator;
+        AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
+                topClosingApp.mAppAnimator;
+
+        mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator);
+        mAppTransition.postAnimationCallback();
+        mAppTransition.clear();
+
+        mOpeningApps.clear();
+        mClosingApps.clear();
+
+        // This has changed the visibility of windows, so perform
+        // a new layout to get them all up-to-date.
+        getDefaultDisplayContentLocked().layoutNeeded = true;
+
+        // TODO(multidisplay): IMEs are only supported on the default display.
+        if (windows == getDefaultWindowListLocked()
+                && !moveInputMethodWindowsIfNeededLocked(true)) {
+            assignLayersLocked(windows);
+        }
+        updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/);
+        mFocusMayChange = false;
+        notifyActivityDrawnForKeyguard();
+        return WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
+                | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
+
+    }
+
+    private int maybeUpdateTransitToWallpaper(int transit, boolean openingAppHasWallpaper,
+            boolean closingAppHasWallpaper, WindowState lowerWallpaperTarget,
+            WindowState upperWallpaperTarget) {
+        // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
+        final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
+        final WindowState oldWallpaper = mWallpaperControllerLocked.isWallpaperTargetAnimating()
+                ? null : wallpaperTarget;
+        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+                "New wallpaper target=" + wallpaperTarget
+                        + ", oldWallpaper=" + oldWallpaper
+                        + ", lower target=" + lowerWallpaperTarget
+                        + ", upper target=" + upperWallpaperTarget);
+        mAnimateWallpaperWithTarget = false;
+        if (closingAppHasWallpaper && openingAppHasWallpaper) {
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
+            switch (transit) {
+                case AppTransition.TRANSIT_ACTIVITY_OPEN:
+                case AppTransition.TRANSIT_TASK_OPEN:
+                case AppTransition.TRANSIT_TASK_TO_FRONT:
+                    transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
+                    break;
+                case AppTransition.TRANSIT_ACTIVITY_CLOSE:
+                case AppTransition.TRANSIT_TASK_CLOSE:
+                case AppTransition.TRANSIT_TASK_TO_BACK:
+                    transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
+                    break;
+            }
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+                    "New transit: " + AppTransition.appTransitionToString(transit));
+        } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
+                && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
+            // We are transitioning from an activity with
+            // a wallpaper to one without.
+            transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+                    "New transit away from wallpaper: "
+                    + AppTransition.appTransitionToString(transit));
+        } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()) {
+            // We are transitioning from an activity without
+            // a wallpaper to now showing the wallpaper
+            transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+                    "New transit into wallpaper: "
+                    + AppTransition.appTransitionToString(transit));
+        } else {
+            mAnimateWallpaperWithTarget = true;
+        }
+        return transit;
+    }
+
+    private void processApplicationsAnimatingInPlace(int transit) {
+        if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
+            // Find the focused window
+            final WindowState win =
+                    findFocusedWindowLocked(getDefaultDisplayContentLocked());
+            if (win != null) {
+                final AppWindowToken wtoken = win.mAppToken;
+                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken);
+                appAnimator.clearThumbnail();
+                appAnimator.animation = null;
+                updateTokenInPlaceLocked(wtoken, transit);
+                wtoken.updateReportedVisibilityLocked();
+
+                appAnimator.mAllAppWinAnimators.clear();
+                final int N = wtoken.allAppWindows.size();
+                for (int j = 0; j < N; j++) {
+                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
+                }
+                mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
+                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+            }
+        }
+    }
+
+    private boolean checkIfTransitionGoodToGo(int appsCount) {
         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                 "Checking " + appsCount + " opening apps (frozen="
-                + mDisplayFrozen + " timeout="
-                + mAppTransition.isTimeout() + ")...");
+                        + mDisplayFrozen + " timeout="
+                        + mAppTransition.isTimeout() + ")...");
         if (!mAppTransition.isTimeout()) {
-            for (i = 0; i < appsCount && goodToGo; i++) {
+            for (int i = 0; i < appsCount; i++) {
                 AppWindowToken wtoken = mOpeningApps.valueAt(i);
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                         "Check opening app=" + wtoken + ": allDrawn="
                         + wtoken.allDrawn + " startingDisplayed="
                         + wtoken.startingDisplayed + " startingMoved="
                         + wtoken.startingMoved);
-                if (!wtoken.allDrawn && !wtoken.startingDisplayed
-                        && !wtoken.startingMoved) {
-                    goodToGo = false;
+                if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
+                    return false;
                 }
             }
 
-            if (goodToGo && isWallpaperVisible(mWallpaperTarget)) {
-                boolean wallpaperGoodToGo = true;
-                for (int curTokenIndex = mWallpaperTokens.size() - 1;
-                        curTokenIndex >= 0 && wallpaperGoodToGo; curTokenIndex--) {
-                    WindowToken token = mWallpaperTokens.get(curTokenIndex);
-                    for (int curWallpaperIndex = token.windows.size() - 1; curWallpaperIndex >= 0;
-                            curWallpaperIndex--) {
-                        WindowState wallpaper = token.windows.get(curWallpaperIndex);
-                        if (wallpaper.mWallpaperVisible && !wallpaper.isDrawnLw()) {
-                            // We've told this wallpaper to be visible, but it is not drawn yet
-                            wallpaperGoodToGo = false;
-                            if (mWallpaperDrawState != WALLPAPER_DRAW_TIMEOUT) {
-                                // wait for this wallpaper until it is drawn or timeout
-                                goodToGo = false;
-                            }
-                            if (mWallpaperDrawState == WALLPAPER_DRAW_NORMAL) {
-                                mWallpaperDrawState = WALLPAPER_DRAW_PENDING;
-                                mH.removeMessages(H.WALLPAPER_DRAW_PENDING_TIMEOUT);
-                                mH.sendEmptyMessageDelayed(H.WALLPAPER_DRAW_PENDING_TIMEOUT,
-                                        WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION);
-                            }
-                            if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
-                                    "Wallpaper should be visible but has not been drawn yet. " +
-                                    "mWallpaperDrawState=" + mWallpaperDrawState);
-                            break;
-                        }
-                    }
-                }
-                if (wallpaperGoodToGo) {
-                    mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
-                    mH.removeMessages(H.WALLPAPER_DRAW_PENDING_TIMEOUT);
-                }
-            }
+            // If the wallpaper is visible, we need to check it's ready too.
+            return !mWallpaperControllerLocked.isWallpaperVisible() ||
+                    mWallpaperControllerLocked.wallpaperTransitionReady();
         }
-        if (goodToGo) {
-            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
-            int transit = mAppTransition.getAppTransition();
-            if (mSkipAppTransitionAnimation) {
-                transit = AppTransition.TRANSIT_UNSET;
-            }
-            mSkipAppTransitionAnimation = false;
-            mNoAnimationNotifyOnTransitionFinished.clear();
+        return true;
+    }
 
-            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
-
-            rebuildAppWindowListLocked();
-
-            // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
-            WindowState oldWallpaper =
-                    mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
-                        && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
-                    ? null : mWallpaperTarget;
-
-            mInnerFields.mWallpaperMayChange = false;
-
-            // The top-most window will supply the layout params,
-            // and we will determine it below.
-            LayoutParams animLp = null;
-            int bestAnimLayer = -1;
-            boolean fullscreenAnim = false;
-            boolean voiceInteraction = false;
-
-            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                    "New wallpaper target=" + mWallpaperTarget
-                    + ", oldWallpaper=" + oldWallpaper
-                    + ", lower target=" + mLowerWallpaperTarget
-                    + ", upper target=" + mUpperWallpaperTarget);
-
-            boolean openingAppHasWallpaper = false;
-            boolean closingAppHasWallpaper = false;
-            final AppWindowToken lowerWallpaperAppToken;
-            final AppWindowToken upperWallpaperAppToken;
-            if (mLowerWallpaperTarget == null) {
-                lowerWallpaperAppToken = upperWallpaperAppToken = null;
-            } else {
-                lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
-                upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
-            }
-
-            // Do a first pass through the tokens for two
-            // things:
-            // (1) Determine if both the closing and opening
-            // app token sets are wallpaper targets, in which
-            // case special animations are needed
-            // (since the wallpaper needs to stay static
-            // behind them).
-            // (2) Find the layout params of the top-most
-            // application window in the tokens, which is
-            // what will control the animation theme.
-            final int closingAppsCount = mClosingApps.size();
-            appsCount = closingAppsCount + mOpeningApps.size();
-            for (i = 0; i < appsCount; i++) {
-                final AppWindowToken wtoken;
-                if (i < closingAppsCount) {
-                    wtoken = mClosingApps.valueAt(i);
-                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
-                        closingAppHasWallpaper = true;
-                    }
-                } else {
-                    wtoken = mOpeningApps.valueAt(i - closingAppsCount);
-                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
-                        openingAppHasWallpaper = true;
-                    }
-                }
-
-                voiceInteraction |= wtoken.voiceInteraction;
-
-                if (wtoken.appFullscreen) {
-                    WindowState ws = wtoken.findMainWindow();
-                    if (ws != null) {
-                        animLp = ws.mAttrs;
-                        bestAnimLayer = ws.mLayer;
-                        fullscreenAnim = true;
-                    }
-                } else if (!fullscreenAnim) {
-                    WindowState ws = wtoken.findMainWindow();
-                    if (ws != null) {
-                        if (ws.mLayer > bestAnimLayer) {
-                            animLp = ws.mAttrs;
-                            bestAnimLayer = ws.mLayer;
-                        }
-                    }
-                }
-            }
-
-            mAnimateWallpaperWithTarget = false;
-            if (closingAppHasWallpaper && openingAppHasWallpaper) {
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
-                switch (transit) {
-                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
-                    case AppTransition.TRANSIT_TASK_OPEN:
-                    case AppTransition.TRANSIT_TASK_TO_FRONT:
-                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
-                        break;
-                    case AppTransition.TRANSIT_ACTIVITY_CLOSE:
-                    case AppTransition.TRANSIT_TASK_CLOSE:
-                    case AppTransition.TRANSIT_TASK_TO_BACK:
-                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
-                        break;
-                }
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                        "New transit: " + AppTransition.appTransitionToString(transit));
-            } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
-                    && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
-                // We are transitioning from an activity with
-                // a wallpaper to one without.
-                transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                        "New transit away from wallpaper: "
-                        + AppTransition.appTransitionToString(transit));
-            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
-                // We are transitioning from an activity without
-                // a wallpaper to now showing the wallpaper
-                transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                        "New transit into wallpaper: "
-                        + AppTransition.appTransitionToString(transit));
-            } else {
-                mAnimateWallpaperWithTarget = true;
-            }
-
-            // If all closing windows are obscured, then there is
-            // no need to do an animation.  This is the case, for
-            // example, when this transition is being done behind
-            // the lock screen.
-            if (!mPolicy.allowAppAnimationsLw()) {
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                        "Animations disallowed by keyguard or dream.");
-                animLp = null;
-            }
-
-            AppWindowToken topOpeningApp = null;
-            AppWindowToken topClosingApp = null;
-            int topOpeningLayer = 0;
-            int topClosingLayer = 0;
-
-            // Process all applications animating in place
-            if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
-                // Find the focused window
-                final WindowState win =
-                        findFocusedWindowLocked(getDefaultDisplayContentLocked());
-                if (win != null) {
-                    final AppWindowToken wtoken = win.mAppToken;
-                    final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
-                    if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken);
-                    appAnimator.clearThumbnail();
-                    appAnimator.animation = null;
-                    updateTokenInPlaceLocked(wtoken, transit);
-                    wtoken.updateReportedVisibilityLocked();
-
-                    appAnimator.mAllAppWinAnimators.clear();
-                    final int N = wtoken.allAppWindows.size();
-                    for (int j = 0; j < N; j++) {
-                        appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
-                    }
-                    mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
-                    mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
-                }
-            }
-
-            appsCount = mOpeningApps.size();
-            for (i = 0; i < appsCount; i++) {
-                AppWindowToken wtoken = mOpeningApps.valueAt(i);
-                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
-
-                if (!appAnimator.usingTransferredAnimation) {
-                    appAnimator.clearThumbnail();
-                    appAnimator.animation = null;
-                }
-                wtoken.inPendingTransaction = false;
-                if (!setTokenVisibilityLocked(
-                        wtoken, animLp, true, transit, false, voiceInteraction)){
-                    // This token isn't going to be animating. Add it to the list of tokens to
-                    // be notified of app transition complete since the notification will not be
-                    // sent be the app window animator.
-                    mNoAnimationNotifyOnTransitionFinished.add(wtoken.token);
-                }
-                wtoken.updateReportedVisibilityLocked();
-                wtoken.waitingToShow = false;
-
-                appAnimator.mAllAppWinAnimators.clear();
-                final int windowsCount = wtoken.allAppWindows.size();
-                for (int j = 0; j < windowsCount; j++) {
-                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
-                }
-                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
-                mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
-
-                if (animLp != null) {
-                    int layer = -1;
-                    for (int j = 0; j < wtoken.windows.size(); j++) {
-                        WindowState win = wtoken.windows.get(j);
-                        if (win.mWinAnimator.mAnimLayer > layer) {
-                            layer = win.mWinAnimator.mAnimLayer;
-                        }
-                    }
-                    if (topOpeningApp == null || layer > topOpeningLayer) {
-                        topOpeningApp = wtoken;
-                        topOpeningLayer = layer;
-                    }
-                }
-            }
-            appsCount = mClosingApps.size();
-            for (i = 0; i < appsCount; i++) {
-                AppWindowToken wtoken = mClosingApps.valueAt(i);
-                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
-                appAnimator.clearThumbnail();
-                appAnimator.animation = null;
-                wtoken.inPendingTransaction = false;
-                setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
-                wtoken.updateReportedVisibilityLocked();
-                // Force the allDrawn flag, because we want to start
-                // this guy's animations regardless of whether it's
-                // gotten drawn.
-                wtoken.allDrawn = true;
-                wtoken.deferClearAllDrawn = false;
-                // Ensure that apps that are mid-starting are also scheduled to have their
-                // starting windows removed after the animation is complete
-                if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) {
-                    scheduleRemoveStartingWindowLocked(wtoken);
-                }
-                mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
-
-                if (animLp != null) {
-                    int layer = -1;
-                    for (int j = 0; j < wtoken.windows.size(); j++) {
-                        WindowState win = wtoken.windows.get(j);
-                        if (win.mWinAnimator.mAnimLayer > layer) {
-                            layer = win.mWinAnimator.mAnimLayer;
-                        }
-                    }
-                    if (topClosingApp == null || layer > topClosingLayer) {
-                        topClosingApp = wtoken;
-                        topClosingLayer = layer;
-                    }
-                }
-            }
-
-            AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
-                    topOpeningApp.mAppAnimator;
-            AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
-                    topClosingApp.mAppAnimator;
-            Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
-            if (nextAppTransitionThumbnail != null
-                    && openingAppAnimator != null && openingAppAnimator.animation != null &&
-                    nextAppTransitionThumbnail.getConfig() != Config.ALPHA_8) {
-                // This thumbnail animation is very special, we need to have
-                // an extra surface with the thumbnail included with the animation.
-                Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
-                        nextAppTransitionThumbnail.getHeight());
-                try {
-                    // TODO(multi-display): support other displays
-                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
-                    final Display display = displayContent.getDisplay();
-                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-
-                    // Create a new surface for the thumbnail
-                    SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
-                            "thumbnail anim", dirty.width(), dirty.height(),
-                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
-                    surfaceControl.setLayerStack(display.getLayerStack());
-                    if (SHOW_TRANSACTIONS) {
-                        Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
-                    }
-
-                    // Draw the thumbnail onto the surface
-                    Surface drawSurface = new Surface();
-                    drawSurface.copyFrom(surfaceControl);
-                    Canvas c = drawSurface.lockCanvas(dirty);
-                    c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
-                    drawSurface.unlockCanvasAndPost(c);
-                    drawSurface.release();
-
-                    // Get the thumbnail animation
-                    Animation anim;
-                    if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
-                        // If this is a multi-window scenario, we use the windows frame as
-                        // destination of the thumbnail header animation. If this is a full screen
-                        // window scenario, we use the whole display as the target.
-                        WindowState win = topOpeningApp.findMainWindow();
-                        Rect appRect = win != null ? win.getContentFrameLw() :
-                                new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
-                        // For the new aspect-scaled transition, we want it to always show
-                        // above the animating opening/closing window, and we want to
-                        // synchronize its thumbnail surface with the surface for the
-                        // open/close animation (only on the way down)
-                        anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect);
-                        openingAppAnimator.thumbnailForceAboveLayer = Math.max(topOpeningLayer,
-                                topClosingLayer);
-                        openingAppAnimator.deferThumbnailDestruction =
-                                !mAppTransition.isNextThumbnailTransitionScaleUp();
-                    } else {
-                        anim = mAppTransition.createThumbnailScaleAnimationLocked(
-                                displayInfo.appWidth, displayInfo.appHeight, transit);
-                    }
-                    anim.restrictDuration(MAX_ANIMATION_DURATION);
-                    anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
-
-                    openingAppAnimator.thumbnail = surfaceControl;
-                    openingAppAnimator.thumbnailLayer = topOpeningLayer;
-                    openingAppAnimator.thumbnailAnimation = anim;
-                    openingAppAnimator.thumbnailX = mAppTransition.getStartingX();
-                    openingAppAnimator.thumbnailY = mAppTransition.getStartingY();
-                } catch (OutOfResourcesException e) {
-                    Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
-                            + " h=" + dirty.height(), e);
-                    openingAppAnimator.clearThumbnail();
-                }
-            }
-
-            mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator);
-            mAppTransition.postAnimationCallback();
-            mAppTransition.clear();
-
-            mOpeningApps.clear();
-            mClosingApps.clear();
-
-            // This has changed the visibility of windows, so perform
-            // a new layout to get them all up-to-date.
-            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
-                    | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
-            getDefaultDisplayContentLocked().layoutNeeded = true;
-
-            // TODO(multidisplay): IMEs are only supported on the default display.
-            if (windows == getDefaultWindowListLocked()
-                    && !moveInputMethodWindowsIfNeededLocked(true)) {
-                assignLayersLocked(windows);
-            }
-            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/);
-            mFocusMayChange = false;
-            notifyActivityDrawnForKeyguard();
+    private void createThumbnailAppAnimator(int transit, AppWindowToken appToken,
+            int openingLayer, int closingLayer) {
+        AppWindowAnimator openingAppAnimator = (appToken == null) ? null : appToken.mAppAnimator;
+        if (openingAppAnimator == null || openingAppAnimator.animation == null) {
+            return;
         }
+        final int taskId = appToken.mTask.mTaskId;
+        Bitmap thumbnailHeader = mAppTransition.getAppTransitionThumbnailHeader(taskId);
+        if (thumbnailHeader == null || thumbnailHeader.getConfig() == Config.ALPHA_8) {
+            return;
+        }
+        // This thumbnail animation is very special, we need to have
+        // an extra surface with the thumbnail included with the animation.
+        Rect dirty = new Rect(0, 0, thumbnailHeader.getWidth(), thumbnailHeader.getHeight());
+        try {
+            // TODO(multi-display): support other displays
+            final DisplayContent displayContent = getDefaultDisplayContentLocked();
+            final Display display = displayContent.getDisplay();
+            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
 
-        return changes;
+            // Create a new surface for the thumbnail
+            SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
+                    "thumbnail anim", dirty.width(), dirty.height(),
+                    PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+            surfaceControl.setLayerStack(display.getLayerStack());
+            if (SHOW_TRANSACTIONS) {
+                Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
+            }
+
+            // Draw the thumbnail onto the surface
+            Surface drawSurface = new Surface();
+            drawSurface.copyFrom(surfaceControl);
+            Canvas c = drawSurface.lockCanvas(dirty);
+            c.drawBitmap(thumbnailHeader, 0, 0, null);
+            drawSurface.unlockCanvasAndPost(c);
+            drawSurface.release();
+
+            // Get the thumbnail animation
+            Animation anim;
+            if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
+                // If this is a multi-window scenario, we use the windows frame as
+                // destination of the thumbnail header animation. If this is a full screen
+                // window scenario, we use the whole display as the target.
+                WindowState win = appToken.findMainWindow();
+                Rect appRect = win != null ? win.getContentFrameLw() :
+                        new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
+                // For the new aspect-scaled transition, we want it to always show
+                // above the animating opening/closing window, and we want to
+                // synchronize its thumbnail surface with the surface for the
+                // open/close animation (only on the way down)
+                anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect,
+                        thumbnailHeader, taskId);
+                Log.d(TAG, "assigning thumbnail force above layer: " + openingLayer + " " +
+                        closingLayer);
+                openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer);
+                openingAppAnimator.deferThumbnailDestruction =
+                        !mAppTransition.isNextThumbnailTransitionScaleUp();
+            } else {
+                anim = mAppTransition.createThumbnailScaleAnimationLocked(
+                        displayInfo.appWidth, displayInfo.appHeight, transit, thumbnailHeader);
+            }
+            anim.restrictDuration(MAX_ANIMATION_DURATION);
+            anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
+
+            openingAppAnimator.thumbnail = surfaceControl;
+            openingAppAnimator.thumbnailLayer = openingLayer;
+            openingAppAnimator.thumbnailAnimation = anim;
+            mAppTransition.getNextAppTransitionStartRect(taskId, mTmpStartRect);
+            openingAppAnimator.thumbnailX = mTmpStartRect.left;
+            openingAppAnimator.thumbnailY = mTmpStartRect.top;
+        } catch (OutOfResourcesException e) {
+            Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
+                    + " h=" + dirty.height(), e);
+            openingAppAnimator.clearThumbnail();
+        }
     }
 
     /**
@@ -9624,10 +8967,7 @@
         }
         mNoAnimationNotifyOnTransitionFinished.clear();
 
-        if (mDeferredHideWallpaper != null) {
-            hideWallpapersLocked(mDeferredHideWallpaper);
-            mDeferredHideWallpaper = null;
-        }
+        mWallpaperControllerLocked.hideDeferredWallpapersIfNeeded();
 
         // Restore window app tokens to the ActivityManager views
         ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
@@ -9948,7 +9288,7 @@
 
                     if ((displayContent.pendingLayoutChanges &
                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
-                            adjustWallpaperWindowsLocked()) {
+                            mWallpaperControllerLocked.adjustWallpaperWindows()) {
                         assignLayersLocked(windows);
                         displayContent.layoutNeeded = true;
                     }
@@ -10020,12 +9360,12 @@
                         handleFlagDimBehind(w);
                     }
 
-                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
-                            && w.isVisibleLw()) {
+                    if (isDefaultDisplay && obscuredChanged
+                            && mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) {
                         // This is the wallpaper target and its obscured state
                         // changed... make sure the current wallaper's visibility
                         // has been updated accordingly.
-                        updateWallpaperVisibilityLocked();
+                        mWallpaperControllerLocked.updateWallpaperVisibility();
                     }
 
                     final WindowStateAnimator winAnimator = w.mWinAnimator;
@@ -10274,7 +9614,7 @@
                 if (mInputMethodWindow == win) {
                     mInputMethodWindow = null;
                 }
-                if (win == mWallpaperTarget) {
+                if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
                     wallpaperDestroyed = true;
                 }
                 win.mWinAnimator.destroySurfaceLocked();
@@ -10291,7 +9631,7 @@
                 if (!token.hasVisible) {
                     exitingTokens.remove(i);
                     if (token.windowType == TYPE_WALLPAPER) {
-                        mWallpaperTokens.remove(token);
+                        mWallpaperControllerLocked.removeWallpaperToken(token);
                     }
                 }
             }
@@ -11198,21 +10538,7 @@
                 }
             }
         }
-        if (!mWallpaperTokens.isEmpty()) {
-            pw.println();
-            pw.println("  Wallpaper tokens:");
-            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
-                WindowToken token = mWallpaperTokens.get(i);
-                pw.print("  Wallpaper #"); pw.print(i);
-                        pw.print(' '); pw.print(token);
-                if (dumpAll) {
-                    pw.println(':');
-                    token.dump(pw, "    ");
-                } else {
-                    pw.println();
-                }
-            }
-        }
+        mWallpaperControllerLocked.dumpTokens(pw, "  ", dumpAll);
         if (!mFinishedStarting.isEmpty()) {
             pw.println();
             pw.println("  Finishing start of application tokens:");
@@ -11412,25 +10738,13 @@
             if (mInputMethodWindow != null) {
                 pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
             }
-            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
-            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
-                pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
-                pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
-            }
-            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
-                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
-            if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
-                    || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
-                pw.print("  mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
-                        pw.print(" mLastWallpaperDisplayOffsetY=");
-                        pw.println(mLastWallpaperDisplayOffsetY);
-            }
+            mWallpaperControllerLocked.dump(pw, "  ");
             if (mInputMethodAnimLayerAdjustment != 0 ||
-                    mWallpaperAnimLayerAdjustment != 0) {
+                    mWallpaperControllerLocked.getAnimLayerAdjustment() != 0) {
                 pw.print("  mInputMethodAnimLayerAdjustment=");
                         pw.print(mInputMethodAnimLayerAdjustment);
                         pw.print("  mWallpaperAnimLayerAdjustment=");
-                        pw.println(mWallpaperAnimLayerAdjustment);
+                        pw.println(mWallpaperControllerLocked.getAnimLayerAdjustment());
             }
             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
@@ -11985,12 +11299,18 @@
                 final WindowList windows = getDefaultWindowListLocked();
                 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
                     final WindowState win = windows.get(winNdx);
+                    final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
                     if (win.isVisibleLw()
-                            && (win.mAppToken != null || mPolicy.isForceHiding(win.mAttrs))) {
+                            && (win.mAppToken != null || isForceHiding)) {
                         win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
                         // Force add to mResizingWindows.
                         win.mLastContentInsets.set(-1, -1, -1, -1);
                         mWaitingForDrawn.add(win);
+
+                        // No need to wait for the windows below Keyguard.
+                        if (isForceHiding) {
+                            break;
+                        }
                     }
                 }
                 requestTraversalLocked();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4061149..092a6d1 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
@@ -33,11 +34,11 @@
 import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
 
 import android.app.AppOpsManager;
-import android.os.Debug;
 import android.os.PowerManager;
 import android.os.RemoteCallbackList;
 import android.os.SystemClock;
 import android.os.WorkSource;
+import android.util.DisplayMetrics;
 import android.util.TimeUtils;
 import android.view.Display;
 import android.view.IWindowFocusObserver;
@@ -78,6 +79,16 @@
 final class WindowState implements WindowManagerPolicy.WindowState {
     static final String TAG = "WindowState";
 
+    // The minimal size of a window within the usable area of the freeform stack.
+    private static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48;
+    private static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32;
+
+    // The thickness of a window resize handle outside the window bounds on the free form workspace
+    // to capture touch events in that area.
+    private static final int RESIZE_HANDLE_WIDTH_IN_DP = 10;
+
+    static final boolean BOUNDS_FOR_TOUCH = true;
+
     final WindowManagerService mService;
     final WindowManagerPolicy mPolicy;
     final Context mContext;
@@ -537,6 +548,7 @@
 
         final Task task = mAppToken != null ? getTask() : null;
         final boolean nonFullscreenTask = task != null && !task.isFullscreen();
+        final boolean freeformWorkspace = inFreeformWorkspace();
         if (nonFullscreenTask) {
             task.getBounds(mContainingFrame);
             final WindowState imeWin = mService.mInputMethodWindow;
@@ -545,10 +557,20 @@
                 // IME is up and obscuring this window. Adjust the window position so it is visible.
                 mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
             }
-            // Make sure the containing frame is within the content frame so we don't layout
-            // resized window under screen decorations.
-            if (!mContainingFrame.intersect(cf)) {
-                mContainingFrame.set(cf);
+
+            if (freeformWorkspace) {
+                // In free form mode we have only to set the rectangle if it wasn't set already. No
+                // need to intersect it with the (visible) "content frame" since it is allowed to
+                // be outside the visible desktop.
+                if (mContainingFrame.isEmpty()) {
+                    mContainingFrame.set(cf);
+                }
+            } else {
+                // Make sure the containing frame is within the content frame so we don't layout
+                // resized window under screen decorations.
+                if (!mContainingFrame.intersect(cf)) {
+                    mContainingFrame.set(cf);
+                }
             }
             mDisplayFrame.set(mContainingFrame);
         } else {
@@ -652,20 +674,38 @@
 
         // Make sure the content and visible frames are inside of the
         // final window frame.
-        mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
-                Math.max(mContentFrame.top, mFrame.top),
-                Math.min(mContentFrame.right, mFrame.right),
-                Math.min(mContentFrame.bottom, mFrame.bottom));
+        if (freeformWorkspace && !mFrame.isEmpty()) {
+            // Keep the frame out of the blocked system area, limit it in size to the content area
+            // and make sure that there is always a minimum visible so that the user can drag it
+            // into a usable area..
+            final int height = Math.min(mFrame.height(), mContentFrame.height());
+            final int width = Math.min(mContentFrame.width(), mFrame.width());
+            final int minVisibleHeight = calculatePixelFromDp(MINIMUM_VISIBLE_HEIGHT_IN_DP);
+            final int minVisibleWidth = calculatePixelFromDp(MINIMUM_VISIBLE_WIDTH_IN_DP);
+            final int top = Math.max(mContentFrame.top,
+                    Math.min(mFrame.top, mContentFrame.bottom - minVisibleHeight));
+            final int left = Math.max(mContentFrame.left + minVisibleWidth - width,
+                    Math.min(mFrame.left, mContentFrame.right - minVisibleWidth));
+            mFrame.set(left, top, left + width, top + height);
+            mContentFrame.set(mFrame);
+            mVisibleFrame.set(mContentFrame);
+            mStableFrame.set(mContentFrame);
+        } else {
+            mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
+                    Math.max(mContentFrame.top, mFrame.top),
+                    Math.min(mContentFrame.right, mFrame.right),
+                    Math.min(mContentFrame.bottom, mFrame.bottom));
 
-        mVisibleFrame.set(Math.max(mVisibleFrame.left, mFrame.left),
-                Math.max(mVisibleFrame.top, mFrame.top),
-                Math.min(mVisibleFrame.right, mFrame.right),
-                Math.min(mVisibleFrame.bottom, mFrame.bottom));
+            mVisibleFrame.set(Math.max(mVisibleFrame.left, mFrame.left),
+                    Math.max(mVisibleFrame.top, mFrame.top),
+                    Math.min(mVisibleFrame.right, mFrame.right),
+                    Math.min(mVisibleFrame.bottom, mFrame.bottom));
 
-        mStableFrame.set(Math.max(mStableFrame.left, mFrame.left),
-                Math.max(mStableFrame.top, mFrame.top),
-                Math.min(mStableFrame.right, mFrame.right),
-                Math.min(mStableFrame.bottom, mFrame.bottom));
+            mStableFrame.set(Math.max(mStableFrame.left, mFrame.left),
+                    Math.max(mStableFrame.top, mFrame.top),
+                    Math.min(mStableFrame.right, mFrame.right),
+                    Math.min(mStableFrame.bottom, mFrame.bottom));
+        }
 
         mOverscanInsets.set(Math.max(mOverscanFrame.left - mFrame.left, 0),
                 Math.max(mOverscanFrame.top - mFrame.top, 0),
@@ -707,8 +747,8 @@
             final DisplayContent displayContent = getDisplayContent();
             if (displayContent != null) {
                 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-                mService.updateWallpaperOffsetLocked(this,
-                        displayInfo.logicalWidth, displayInfo.logicalHeight, false);
+                mService.mWallpaperControllerLocked.updateWallpaperOffset(
+                        this, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
             }
         }
 
@@ -875,10 +915,22 @@
         return mDisplayContent.getHomeStack();
     }
 
-    void getTaskBounds(Rect bounds) {
+    /**
+     * Retrieves the bounds for a task.
+     * @param bounds The rect which gets the bounds.
+     * @param forTouch Pass in BOUNDS_FOR_TOUCH to get touch related bounds, otherwise visible
+     *        bounds will be returned.
+     */
+    void getTaskBounds(Rect bounds, boolean forTouch) {
         final Task task = getTask();
         if (task != null) {
             task.getBounds(bounds);
+            if (forTouch == BOUNDS_FOR_TOUCH) {
+                if (inFreeformWorkspace()) {
+                    final int delta = calculatePixelFromDp(RESIZE_HANDLE_WIDTH_IN_DP);
+                    bounds.inset(-delta, -delta);
+                }
+            }
             return;
         }
         bounds.set(mFrame);
@@ -1577,6 +1629,19 @@
         }
     }
 
+    private boolean inFreeformWorkspace() {
+        final Task task = getTask();
+        return task != null && task.mStack != null &&
+                task.mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
+    }
+
+    private int calculatePixelFromDp(int dp) {
+        final Configuration serviceConfig = mService.mCurConfiguration;
+        // TODO(multidisplay): Update Dp to that of display stack is on.
+        final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+        return (int)(dp * density);
+    }
+
     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
         final TaskStack stack = getStack();
         pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId());
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 28491e4..7aa48ab 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -47,7 +47,6 @@
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
-import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 import android.view.WindowManager.LayoutParams;
@@ -77,6 +76,7 @@
     final WindowManagerPolicy mPolicy;
     final Context mContext;
     final boolean mIsWallpaper;
+    final WallpaperController mWallpaperControllerLocked;
 
     // Currently running animation.
     boolean mAnimating;
@@ -209,6 +209,7 @@
         mSession = win.mSession;
         mAttrType = win.mAttrs.type;
         mIsWallpaper = win.mIsWallpaper;
+        mWallpaperControllerLocked = mService.mWallpaperControllerLocked;
     }
 
     public void setAnimation(Animation anim, long startTime) {
@@ -375,7 +376,7 @@
         if (mWin.mIsImWindow) {
             mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
         } else if (mIsWallpaper) {
-            mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
+            mAnimLayer += mWallpaperControllerLocked.getAnimLayerAdjustment();
         }
         if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
                 + " anim layer: " + mAnimLayer);
@@ -484,7 +485,7 @@
             mService.mPendingRemove.add(mWin);
             mWin.mRemoveOnExit = false;
         }
-        mService.hideWallpapersLocked(mWin);
+        mWallpaperControllerLocked.hideWallpapers(mWin);
     }
 
     void hide() {
@@ -986,7 +987,7 @@
                     }
                     mSurfaceControl.destroy();
                 }
-                mService.hideWallpapersLocked(mWin);
+                mWallpaperControllerLocked.hideWallpapers(mWin);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Exception thrown when destroying Window " + this
                     + " surface " + mSurfaceControl + " session " + mSession
@@ -1012,7 +1013,7 @@
                     WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
                 }
                 mPendingDestroySurface.destroy();
-                mService.hideWallpapersLocked(mWin);
+                mWallpaperControllerLocked.hideWallpapers(mWin);
             }
         } catch (RuntimeException e) {
             Slog.w(TAG, "Exception thrown when destroying Window "
@@ -1033,7 +1034,7 @@
 
         // Wallpapers are animated based on the "real" window they
         // are currently targeting.
-        final WindowState wallpaperTarget = mService.mWallpaperTarget;
+        final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
         if (mIsWallpaper && wallpaperTarget != null && mService.mAnimateWallpaperWithTarget) {
             final WindowStateAnimator wallpaperAnimator = wallpaperTarget.mWinAnimator;
             if (wallpaperAnimator.mHasLocalTransformation &&
@@ -1467,7 +1468,7 @@
             hide();
         } else if (w.mAttachedHidden || !w.isOnScreen()) {
             hide();
-            mService.hideWallpapersLocked(w);
+            mWallpaperControllerLocked.hideWallpapers(w);
 
             // If we are waiting for this window to handle an
             // orientation change, well, it is hidden, so
@@ -1522,7 +1523,7 @@
                         if (showSurfaceRobustlyLocked()) {
                             mLastHidden = false;
                             if (mIsWallpaper) {
-                                mService.dispatchWallpaperVisibility(w, true);
+                                mWallpaperControllerLocked.dispatchWallpaperVisibility(w, true);
                             }
                             // This draw means the difference between unique content and mirroring.
                             // Run another pass through performLayout to set mHasContent in the
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cd2885b..0f60cc8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21,6 +21,7 @@
 import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
 import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
 import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
 import static org.xmlpull.v1.XmlPullParser.TEXT;
@@ -44,6 +45,7 @@
 import android.app.admin.IDevicePolicyManager;
 import android.app.admin.SystemUpdatePolicy;
 import android.app.backup.IBackupManager;
+import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -2957,7 +2959,8 @@
             }
             boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
             if (requireEntry) {
-                utils.requireCredentialEntry(UserHandle.USER_ALL);
+                utils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
+                        UserHandle.USER_ALL);
             }
             synchronized (this) {
                 int newOwner = requireEntry ? callingUid : -1;
@@ -3089,7 +3092,8 @@
             mPowerManager.goToSleep(SystemClock.uptimeMillis(),
                     PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);
             // Ensure the device is locked
-            new LockPatternUtils(mContext).requireCredentialEntry(UserHandle.USER_ALL);
+            new LockPatternUtils(mContext).requireStrongAuth(
+                    STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW, UserHandle.USER_ALL);
             getWindowManager().lockNow(null);
         } catch (RemoteException e) {
         } finally {
@@ -4523,12 +4527,12 @@
             long id = Binder.clearCallingIdentity();
             try {
                 mUserManager.setUserEnabled(userId);
+                UserInfo parent = mUserManager.getProfileParent(userId);
                 Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
                 intent.putExtra(Intent.EXTRA_USER, new UserHandle(userHandle));
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
                         Intent.FLAG_RECEIVER_FOREGROUND);
-                // TODO This should send to parent of profile (which is always owner at the moment).
-                mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
+                mContext.sendBroadcastAsUser(intent, new UserHandle(parent.id));
             } finally {
                 restoreCallingIdentity(id);
             }
@@ -4963,13 +4967,19 @@
             IPackageManager pm = AppGlobals.getPackageManager();
             long id = Binder.clearCallingIdentity();
             try {
+                UserInfo parent = mUserManager.getProfileParent(callingUserId);
+                if (parent == null) {
+                    Slog.e(LOG_TAG, "Cannot call addCrossProfileIntentFilter if there is no "
+                            + "parent");
+                    return;
+                }
                 if ((flags & DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED) != 0) {
                     pm.addCrossProfileIntentFilter(filter, who.getPackageName(), callingUserId,
-                            UserHandle.USER_OWNER, 0);
+                            parent.id, 0);
                 }
                 if ((flags & DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT) != 0) {
                     pm.addCrossProfileIntentFilter(filter, who.getPackageName(),
-                            UserHandle.USER_OWNER, callingUserId, 0);
+                            parent.id, callingUserId, 0);
                 }
             } catch (RemoteException re) {
                 // Shouldn't happen
@@ -4988,12 +4998,18 @@
             IPackageManager pm = AppGlobals.getPackageManager();
             long id = Binder.clearCallingIdentity();
             try {
-                // Removing those that go from the managed profile to the primary user.
+                UserInfo parent = mUserManager.getProfileParent(callingUserId);
+                if (parent == null) {
+                    Slog.e(LOG_TAG, "Cannot call clearCrossProfileIntentFilter if there is no "
+                            + "parent");
+                    return;
+                }
+                // Removing those that go from the managed profile to the parent.
                 pm.clearCrossProfileIntentFilters(callingUserId, who.getPackageName());
-                // And those that go from the primary user to the managed profile.
+                // And those that go from the parent to the managed profile.
                 // If we want to support multiple managed profiles, we will have to only remove
                 // those that have callingUserId as their target.
-                pm.clearCrossProfileIntentFilters(UserHandle.USER_OWNER, who.getPackageName());
+                pm.clearCrossProfileIntentFilters(parent.id, who.getPackageName());
             } catch (RemoteException re) {
                 // Shouldn't happen
             } finally {
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 33979b1..3ad26d3 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -13,6 +13,7 @@
     services.net \
     easymocklib \
     guava \
+    android-support-test \
     mockito-target
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 919293a..386a9cb 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -69,7 +69,7 @@
     </application>
 
     <instrumentation
-    	android:name="android.test.InstrumentationTestRunner"
+    	android:name="android.support.test.runner.AndroidJUnitRunner"
     	android:targetPackage="com.android.frameworks.servicestests"
     	android:label="Frameworks Services Tests" />
 </manifest>
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 696f106..b4c76b7 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -943,8 +943,7 @@
         if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
                 capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
                 capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
-                capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP ||
-                capability == NET_CAPABILITY_TRUSTED || capability == NET_CAPABILITY_NOT_VPN) {
+                capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
             assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
         } else {
             assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index d91fa90..2d31a78 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -512,8 +512,8 @@
                         Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
                         Objects.equals(mVideoState, d.mVideoState) &&
                         Objects.equals(mStatusHints, d.mStatusHints) &&
-                        Objects.equals(mExtras, d.mExtras) &&
-                        Objects.equals(mIntentExtras, d.mIntentExtras);
+                        areBundlesEqual(mExtras, d.mExtras) &&
+                        areBundlesEqual(mIntentExtras, d.mIntentExtras);
             }
             return false;
         }
@@ -1253,4 +1253,32 @@
             });
         }
     }
+
+    /**
+     * Determines if two bundles are equal.
+     *
+     * @param bundle The original bundle.
+     * @param newBundle The bundle to compare with.
+     * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
+     */
+    private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
+        if (bundle == null || newBundle == null) {
+            return bundle == newBundle;
+        }
+
+        if (bundle.size() != newBundle.size()) {
+            return false;
+        }
+
+        for(String key : bundle.keySet()) {
+            if (key != null) {
+                final Object value = bundle.get(key);
+                final Object newValue = newBundle.get(key);
+                if (!Objects.equals(value, newValue)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 263c5e9..31f1d7f 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -358,6 +358,13 @@
     public static final String KEY_CDMA_DTMF_TONE_DELAY_INT = "cdma_dtmf_tone_delay_int";
 
     /**
+     * Determines whether conference calls are supported by a carrier.  When {@code true},
+     * conference calling is supported, {@code false otherwise}.
+     * @hide
+     */
+    public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
+
+    /**
      * If this is true, the SIM card (through Customer Service Profile EF file) will be able to
      * prevent manual operator selection. If false, this SIM setting will be ignored and manual
      * operator selection will always be available. See CPHS4_2.WW6, CPHS B.4.7.1 for more
@@ -457,6 +464,7 @@
         sDefaults.putBoolean(KEY_FORCE_HOME_NETWORK_BOOL, false);
         sDefaults.putInt(KEY_IMS_DTMF_TONE_DELAY_INT, 0);
         sDefaults.putInt(KEY_CDMA_DTMF_TONE_DELAY_INT, 100);
+        sDefaults.putBoolean(KEY_SUPPORT_CONFERENCE_CALL_BOOL, true);
 
         // MMS defaults
         sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 62859ec..a8fd91c 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -30,6 +30,7 @@
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
+import android.view.AppTransitionAnimationSpec;
 
 import java.lang.Override;
 
@@ -241,6 +242,12 @@
     }
 
     @Override
+    public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
+            IRemoteCallback callback, boolean scaleUp) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
     public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
         // TODO Auto-generated method stub