Merge "Using actual users in more places."
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 acc9c4b..4157c6f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -240,8 +240,10 @@
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
     field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
     field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
+    field public static final int activityHeight = 16844019; // 0x10104f3
     field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
     field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
+    field public static final int activityWidth = 16844018; // 0x10104f2
     field public static final int addPrintersActivity = 16843750; // 0x10103e6
     field public static final int addStatesFromChildren = 16842992; // 0x10100f0
     field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -8881,6 +8883,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 +8897,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 +18148,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 +32524,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);
diff --git a/api/system-current.txt b/api/system-current.txt
index 955fb07..33ce543 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -333,8 +333,10 @@
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
     field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
     field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
+    field public static final int activityHeight = 16844019; // 0x10104f3
     field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
     field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
+    field public static final int activityWidth = 16844018; // 0x10104f2
     field public static final int addPrintersActivity = 16843750; // 0x10103e6
     field public static final int addStatesFromChildren = 16842992; // 0x10100f0
     field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -9139,6 +9141,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 +9155,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 +19661,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 +34857,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);
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/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index f66a4c7..68c11ad 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -51,6 +51,7 @@
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.IUserManager;
@@ -1094,6 +1095,7 @@
             }
         }
 
+        userId = translateUserId(userId, "runInstall");
         if (userId == UserHandle.USER_ALL) {
             userId = UserHandle.USER_SYSTEM;
             installFlags |= PackageManager.INSTALL_ALL_USERS;
@@ -1164,6 +1166,16 @@
         }
     }
 
+    /**
+     * @param userId The user id to be translated.
+     * @param logContext Optional human readable text to provide some context in error log.
+     * @return Translated concrete user id.  This will include USER_ALL.
+     */
+    private int translateUserId(int userId, String logContext) {
+        return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+                userId, true, true, logContext, "pm command");
+    }
+
     private int runInstallCreate() throws RemoteException {
         int userId = UserHandle.USER_ALL;
         String installerPackageName = null;
@@ -1220,6 +1232,7 @@
             }
         }
 
+        userId = translateUserId(userId, "runInstallCreate");
         if (userId == UserHandle.USER_ALL) {
             userId = UserHandle.USER_SYSTEM;
             params.installFlags |= PackageManager.INSTALL_ALL_USERS;
@@ -1551,6 +1564,7 @@
             return 1;
         }
 
+        userId = translateUserId(userId, "runUninstall");
         if (userId == UserHandle.USER_ALL) {
             userId = UserHandle.USER_SYSTEM;
             flags |= PackageManager.DELETE_ALL_USERS;
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index c551482..cb39e37 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -61,7 +61,7 @@
             IBinder token = new Binder();
             try {
                 ContentProviderHolder holder = activityManager.getContentProviderExternal(
-                        providerName, UserHandle.USER_OWNER, token);
+                        providerName, UserHandle.USER_SYSTEM, token);
                 if (holder == null) {
                     throw new IllegalStateException("Could not find provider: " + providerName);
                 }
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 7718a36..9ea2ba2 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -401,7 +401,19 @@
                             activeSet.add(canonicalJournalPath);
                             if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) {
                                 Log.v(TAG_XML_PARSER, "...automatically generated "
-                                        + canonicalJournalPath + ". Ignore if nonexistant.");
+                                        + canonicalJournalPath + ". Ignore if nonexistent.");
+                            }
+                        }
+
+                        // Special case for sharedpref files (not dirs) also add ".xml" suffix file.
+                        if ("sharedpref".equals(domainFromXml) && !canonicalFile.isDirectory() &&
+                            !canonicalFile.getCanonicalPath().endsWith(".xml")) {
+                            final String canonicalXmlPath =
+                                    canonicalFile.getCanonicalPath() + ".xml";
+                            activeSet.add(canonicalXmlPath);
+                            if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) {
+                                Log.v(TAG_XML_PARSER, "...automatically generated "
+                                        + canonicalXmlPath + ". Ignore if nonexistent.");
                             }
                         }
                 }
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java
index 7a80936..30c11ef 100644
--- a/core/java/android/app/backup/WallpaperBackupHelper.java
+++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -56,11 +56,12 @@
 
     // This path must match what the WallpaperManagerService uses
     // TODO: Will need to change if backing up non-primary user's wallpaper
+    // http://b/22388012
     public static final String WALLPAPER_IMAGE =
-            new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+            new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
                     "wallpaper").getAbsolutePath();
     public static final String WALLPAPER_INFO =
-            new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+            new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
                     "wallpaper_info.xml").getAbsolutePath();
     // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
     public static final String WALLPAPER_IMAGE_KEY =
@@ -71,8 +72,9 @@
     // will be saved to this file from the restore stream, then renamed to the proper
     // location if it's deemed suitable.
     // TODO: Will need to change if backing up non-primary user's wallpaper
+    // http://b/22388012
     private static final String STAGE_FILE =
-            new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+            new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
                     "wallpaper-tmp").getAbsolutePath();
 
     Context mContext;
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..83092a9 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() {
     }
 
@@ -717,6 +719,7 @@
         maxRecents = orig.maxRecents;
         resizeable = orig.resizeable;
         lockTaskLaunchMode = orig.lockTaskLaunchMode;
+        initialLayout = orig.initialLayout;
     }
 
     /**
@@ -763,9 +766,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 +801,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 +840,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..502f735 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_activityWidth);
+        if (widthType == TypedValue.TYPE_FRACTION) {
+            widthFraction = sw.getFraction(
+                    com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth,
+                    1, 1, -1);
+        } else if (widthType == TypedValue.TYPE_DIMENSION) {
+            width = sw.getDimensionPixelSize(
+                    com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth,
+                    -1);
+        }
+        final int heightType = sw.getType(
+                com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight);
+        if (heightType == TypedValue.TYPE_FRACTION) {
+            heightFraction = sw.getFraction(
+                    com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight,
+                    1, 1, -1);
+        } else if (heightType == TypedValue.TYPE_DIMENSION) {
+            height = sw.getDimensionPixelSize(
+                    com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight,
+                    -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 {
@@ -3375,6 +3415,7 @@
         info.uiOptions = target.info.uiOptions;
         info.parentActivityName = target.info.parentActivityName;
         info.maxRecents = target.info.maxRecents;
+        info.initialLayout = target.info.initialLayout;
 
         Activity a = new Activity(mParseActivityAliasArgs, info);
         if (outError[0] != null) {
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index cbd2f78..38f971a 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -145,6 +145,18 @@
         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;
+        } else {
+            return id == UserHandle.USER_SYSTEM;
+        }
+    }
+
     public UserInfo() {
     }
 
diff --git a/core/java/android/hardware/ICameraServiceProxy.aidl b/core/java/android/hardware/ICameraServiceProxy.aidl
index 0bb24bc..0e654d5 100644
--- a/core/java/android/hardware/ICameraServiceProxy.aidl
+++ b/core/java/android/hardware/ICameraServiceProxy.aidl
@@ -19,6 +19,8 @@
 /**
  * Binder interface for the camera service proxy running in system_server.
  *
+ * Keep in sync with frameworks/av/include/camera/ICameraServiceProxy.h
+ *
  * @hide
  */
 interface ICameraServiceProxy
@@ -27,4 +29,9 @@
      * Ping the service proxy to update the valid users for the camera service.
      */
     oneway void pingForUserUpdate();
+
+    /**
+     * Update the status of a camera device
+     */
+     oneway void notifyCameraState(String cameraId, int newCameraState);
 }
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 5583920..a2ef078 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1003,13 +1003,13 @@
     /**
      * <p>The orientation of the camera relative to the sensor
      * coordinate system.</p>
-     * <p>The four coefficients that describe the quarternion
+     * <p>The four coefficients that describe the quaternion
      * rotation from the Android sensor coordinate system to a
      * camera-aligned coordinate system where the X-axis is
      * aligned with the long side of the image sensor, the Y-axis
      * is aligned with the short side of the image sensor, and
      * the Z-axis is aligned with the optical axis of the sensor.</p>
-     * <p>To convert from the quarternion coefficients <code>(x,y,z,w)</code>
+     * <p>To convert from the quaternion coefficients <code>(x,y,z,w)</code>
      * to the axis of rotation <code>(a_x, a_y, a_z)</code> and rotation
      * amount <code>theta</code>, the following formulas can be used:</p>
      * <pre><code> theta = 2 * acos(w)
@@ -1018,7 +1018,7 @@
      * a_z = z / sin(theta/2)
      * </code></pre>
      * <p>To create a 3x3 rotation matrix that applies the rotation
-     * defined by this quarternion, the following matrix can be
+     * defined by this quaternion, the following matrix can be
      * used:</p>
      * <pre><code>R = [ 1 - 2y^2 - 2z^2,       2xy - 2zw,       2xz + 2yw,
      *            2xy + 2zw, 1 - 2x^2 - 2z^2,       2yz - 2xw,
@@ -1030,7 +1030,7 @@
      * <p>where <code>p</code> is in the device sensor coordinate system, and
      *  <code>p'</code> is in the camera-oriented coordinate system.</p>
      * <p><b>Units</b>:
-     * Quarternion coefficients</p>
+     * Quaternion coefficients</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      */
     @PublicKey
@@ -1052,13 +1052,13 @@
      * user's perspective) will report <code>(0.03, 0, 0)</code>.</p>
      * <p>To transform a pixel coordinates between two cameras
      * facing the same direction, first the source camera
-     * android.lens.radialDistortion must be corrected for.  Then
-     * the source camera android.lens.intrinsicCalibration needs
+     * {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion} must be corrected for.  Then
+     * the source camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs
      * to be applied, followed by the {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}
      * of the source camera, the translation of the source camera
      * relative to the destination camera, the
      * {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the destination camera, and
-     * finally the inverse of android.lens.intrinsicCalibration
+     * finally the inverse of {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}
      * of the destination camera. This obtains a
      * radial-distortion-free coordinate in the destination
      * camera pixel coordinates.</p>
@@ -1069,7 +1069,9 @@
      * <p><b>Units</b>: Meters</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
+     * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
      * @see CameraCharacteristics#LENS_POSE_ROTATION
+     * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
      */
     @PublicKey
     public static final Key<float[]> LENS_POSE_TRANSLATION =
@@ -1115,7 +1117,7 @@
      * where <code>(0,0)</code> is the top-left of the
      * preCorrectionActiveArraySize rectangle. Once the pose and
      * intrinsic calibration transforms have been applied to a
-     * world point, then the android.lens.radialDistortion
+     * world point, then the {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}
      * transform needs to be applied, and the result adjusted to
      * be in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
      * system (where <code>(0, 0)</code> is the top-left of the
@@ -1130,6 +1132,7 @@
      *
      * @see CameraCharacteristics#LENS_POSE_ROTATION
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
+     * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
@@ -1156,7 +1159,7 @@
      * </code></pre>
      * <p>The pixel coordinates are defined in a normalized
      * coordinate system related to the
-     * android.lens.intrinsicCalibration calibration fields.
+     * {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} calibration fields.
      * Both <code>[x_i, y_i]</code> and <code>[x_c, y_c]</code> have <code>(0,0)</code> at the
      * lens optical center <code>[c_x, c_y]</code>. The maximum magnitudes
      * of both x and y coordinates are normalized to be 1 at the
@@ -1169,6 +1172,8 @@
      * <p><b>Units</b>:
      * Unitless coefficients.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
      */
     @PublicKey
     public static final Key<float[]> LENS_RADIAL_DISTORTION =
@@ -2262,7 +2267,7 @@
      * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
      * <p>The currently supported fields that correct for geometric distortion are:</p>
      * <ol>
-     * <li>android.lens.radialDistortion.</li>
+     * <li>{@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}.</li>
      * </ol>
      * <p>If all of the geometric distortion fields are no-ops, this rectangle will be the same
      * as the post-distortion-corrected rectangle given in
@@ -2275,6 +2280,7 @@
      * <p><b>Units</b>: Pixel coordinates on the image sensor</p>
      * <p>This key is available on all devices.</p>
      *
+     * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index c580083..35a1d96 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -647,8 +647,8 @@
      *   {@link android.hardware.camera2.CaptureResult }:<ul>
      * <li>{@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}</li>
      * <li>{@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}</li>
-     * <li>android.lens.intrinsicCalibration</li>
-     * <li>android.lens.radialDistortion</li>
+     * <li>{@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}</li>
+     * <li>{@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}</li>
      * </ul>
      * </li>
      * <li>The {@link CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE android.depth.depthIsExclusive} entry is listed by this device.</li>
@@ -667,8 +667,10 @@
      *
      * @see CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE
      * @see CameraCharacteristics#LENS_FACING
+     * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
      * @see CameraCharacteristics#LENS_POSE_ROTATION
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
+     * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
     public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d5511c1..46eddb3 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2602,13 +2602,13 @@
     /**
      * <p>The orientation of the camera relative to the sensor
      * coordinate system.</p>
-     * <p>The four coefficients that describe the quarternion
+     * <p>The four coefficients that describe the quaternion
      * rotation from the Android sensor coordinate system to a
      * camera-aligned coordinate system where the X-axis is
      * aligned with the long side of the image sensor, the Y-axis
      * is aligned with the short side of the image sensor, and
      * the Z-axis is aligned with the optical axis of the sensor.</p>
-     * <p>To convert from the quarternion coefficients <code>(x,y,z,w)</code>
+     * <p>To convert from the quaternion coefficients <code>(x,y,z,w)</code>
      * to the axis of rotation <code>(a_x, a_y, a_z)</code> and rotation
      * amount <code>theta</code>, the following formulas can be used:</p>
      * <pre><code> theta = 2 * acos(w)
@@ -2617,7 +2617,7 @@
      * a_z = z / sin(theta/2)
      * </code></pre>
      * <p>To create a 3x3 rotation matrix that applies the rotation
-     * defined by this quarternion, the following matrix can be
+     * defined by this quaternion, the following matrix can be
      * used:</p>
      * <pre><code>R = [ 1 - 2y^2 - 2z^2,       2xy - 2zw,       2xz + 2yw,
      *            2xy + 2zw, 1 - 2x^2 - 2z^2,       2yz - 2xw,
@@ -2629,7 +2629,7 @@
      * <p>where <code>p</code> is in the device sensor coordinate system, and
      *  <code>p'</code> is in the camera-oriented coordinate system.</p>
      * <p><b>Units</b>:
-     * Quarternion coefficients</p>
+     * Quaternion coefficients</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      */
     @PublicKey
@@ -2651,13 +2651,13 @@
      * user's perspective) will report <code>(0.03, 0, 0)</code>.</p>
      * <p>To transform a pixel coordinates between two cameras
      * facing the same direction, first the source camera
-     * android.lens.radialDistortion must be corrected for.  Then
-     * the source camera android.lens.intrinsicCalibration needs
+     * {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion} must be corrected for.  Then
+     * the source camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs
      * to be applied, followed by the {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}
      * of the source camera, the translation of the source camera
      * relative to the destination camera, the
      * {@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} of the destination camera, and
-     * finally the inverse of android.lens.intrinsicCalibration
+     * finally the inverse of {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration}
      * of the destination camera. This obtains a
      * radial-distortion-free coordinate in the destination
      * camera pixel coordinates.</p>
@@ -2668,7 +2668,9 @@
      * <p><b>Units</b>: Meters</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
+     * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
      * @see CameraCharacteristics#LENS_POSE_ROTATION
+     * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
      */
     @PublicKey
     public static final Key<float[]> LENS_POSE_TRANSLATION =
@@ -2714,7 +2716,7 @@
      * where <code>(0,0)</code> is the top-left of the
      * preCorrectionActiveArraySize rectangle. Once the pose and
      * intrinsic calibration transforms have been applied to a
-     * world point, then the android.lens.radialDistortion
+     * world point, then the {@link CameraCharacteristics#LENS_RADIAL_DISTORTION android.lens.radialDistortion}
      * transform needs to be applied, and the result adjusted to
      * be in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
      * system (where <code>(0, 0)</code> is the top-left of the
@@ -2729,6 +2731,7 @@
      *
      * @see CameraCharacteristics#LENS_POSE_ROTATION
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
+     * @see CameraCharacteristics#LENS_RADIAL_DISTORTION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
@@ -2755,7 +2758,7 @@
      * </code></pre>
      * <p>The pixel coordinates are defined in a normalized
      * coordinate system related to the
-     * android.lens.intrinsicCalibration calibration fields.
+     * {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} calibration fields.
      * Both <code>[x_i, y_i]</code> and <code>[x_c, y_c]</code> have <code>(0,0)</code> at the
      * lens optical center <code>[c_x, c_y]</code>. The maximum magnitudes
      * of both x and y coordinates are normalized to be 1 at the
@@ -2768,6 +2771,8 @@
      * <p><b>Units</b>:
      * Unitless coefficients.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CameraCharacteristics#LENS_INTRINSIC_CALIBRATION
      */
     @PublicKey
     public static final Key<float[]> LENS_RADIAL_DISTORTION =
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index e786707..fddfbde 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -338,6 +338,8 @@
                     } else {
                         sizedSurfaces.add(new Pair<>(output, s));
                     }
+                    // Lock down the size before configuration
+                    setSurfaceDimens(output, s.getWidth(), s.getHeight());
                 } catch (BufferQueueAbandonedException e) {
                     Log.e(TAG, "Surface bufferqueue is abandoned, cannot configure as output: ", e);
                     return BAD_VALUE;
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index e71e49f..b8d6960 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -1290,7 +1290,7 @@
         for (StreamConfiguration config : configurations) {
             int fmt = config.getFormat();
             if (fmt == format && config.isOutput() == output) {
-                if (output) {
+                if (output && mListHighResolution) {
                     // Filter slow high-res output formats; include for
                     // highRes, remove for !highRes
                     long duration = 0;
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/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/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index ce50091..ea0873d 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -19,12 +19,13 @@
 import android.annotation.StyleRes;
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.res.AssetManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 
 /**
- * A ContextWrapper that allows you to modify the theme from what is in the 
- * wrapped context. 
+ * A context wrapper that allows you to modify or replace the theme of the
+ * wrapped context.
  */
 public class ContextThemeWrapper extends ContextWrapper {
     private int mThemeResource;
@@ -33,15 +34,42 @@
     private Configuration mOverrideConfiguration;
     private Resources mResources;
 
+    /**
+     * Creates a new context wrapper with no theme and no base context.
+     * <p>
+     * <stong>Note:</strong> A base context <strong>must</strong> be attached
+     * using {@link #attachBaseContext(Context)} before calling any other
+     * method on the newly constructed context wrapper.
+     */
     public ContextThemeWrapper() {
         super(null);
     }
 
+    /**
+     * Creates a new context wrapper with the specified theme.
+     * <p>
+     * The specified theme will be applied on top of the base context's theme.
+     * Any attributes not explicitly defined in the theme identified by
+     * <var>themeResId</var> will retain their original values.
+     *
+     * @param base the base context
+     * @param themeResId the resource ID of the theme to be applied on top of
+     *                   the base context's theme
+     */
     public ContextThemeWrapper(Context base, @StyleRes int themeResId) {
         super(base);
         mThemeResource = themeResId;
     }
 
+    /**
+     * Creates a new context wrapper with the specified theme.
+     * <p>
+     * Unlike {@link #ContextThemeWrapper(Context, int)}, the theme passed to
+     * this constructor will completely replace the base context's theme.
+     *
+     * @param base the base context
+     * @param theme the theme against which resources should be inflated
+     */
     public ContextThemeWrapper(Context base, Resources.Theme theme) {
         super(base);
         mTheme = theme;
@@ -60,11 +88,12 @@
      * information.
      *
      * <p>This method can only be called once, and must be called before any
-     * calls to {@link #getResources()} are made.
+     * calls to {@link #getResources()} or {@link #getAssets()} are made.
      */
     public void applyOverrideConfiguration(Configuration overrideConfiguration) {
         if (mResources != null) {
-            throw new IllegalStateException("getResources() has already been called");
+            throw new IllegalStateException(
+                    "getResources() or getAssets() has already been called");
         }
         if (mOverrideConfiguration != null) {
             throw new IllegalStateException("Override configuration has already been set");
@@ -73,20 +102,25 @@
     }
 
     @Override
-    public Resources getResources() {
-        if (mResources != null) {
-            return mResources;
-        }
-        if (mOverrideConfiguration == null) {
-            mResources = super.getResources();
-            return mResources;
-        } else {
-            Context resc = createConfigurationContext(mOverrideConfiguration);
-            mResources = resc.getResources();
-            return mResources;
-        }
+    public AssetManager getAssets() {
+        // Ensure we're returning assets with the correct configuration.
+        return getResources().getAssets();
     }
-    
+
+    @Override
+    public Resources getResources() {
+        if (mResources == null) {
+            if (mOverrideConfiguration == null) {
+                mResources = super.getResources();
+            } else {
+                final Context resContext = createConfigurationContext(mOverrideConfiguration);
+                mResources = resContext.getResources();
+            }
+        }
+
+        return mResources;
+    }
+
     @Override
     public void setTheme(int resid) {
         if (mThemeResource != resid) {
@@ -94,14 +128,15 @@
             initializeTheme();
         }
     }
-    
+
     /** @hide */
     @Override
     public int getThemeResId() {
         return mThemeResource;
     }
 
-    @Override public Resources.Theme getTheme() {
+    @Override
+    public Resources.Theme getTheme() {
         if (mTheme != null) {
             return mTheme;
         }
@@ -113,7 +148,8 @@
         return mTheme;
     }
 
-    @Override public Object getSystemService(String name) {
+    @Override
+    public Object getSystemService(String name) {
         if (LAYOUT_INFLATER_SERVICE.equals(name)) {
             if (mInflater == null) {
                 mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
@@ -122,27 +158,27 @@
         }
         return getBaseContext().getSystemService(name);
     }
-    
+
     /**
      * Called by {@link #setTheme} and {@link #getTheme} to apply a theme
-     * resource to the current Theme object.  Can override to change the
-     * default (simple) behavior.  This method will not be called in multiple
+     * resource to the current Theme object. May be overridden to change the
+     * default (simple) behavior. This method will not be called in multiple
      * threads simultaneously.
      *
-     * @param theme The Theme object being modified.
-     * @param resid The theme style resource being applied to <var>theme</var>.
-     * @param first Set to true if this is the first time a style is being
-     *              applied to <var>theme</var>.
+     * @param theme the theme being modified
+     * @param resId the style resource being applied to <var>theme</var>
+     * @param first {@code true} if this is the first time a style is being
+     *              applied to <var>theme</var>
      */
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        theme.applyStyle(resid, true);
+    protected void onApplyThemeResource(Resources.Theme theme, int resId, boolean first) {
+        theme.applyStyle(resId, true);
     }
 
     private void initializeTheme() {
         final boolean first = mTheme == null;
         if (first) {
             mTheme = getResources().newTheme();
-            Resources.Theme theme = getBaseContext().getTheme();
+            final Resources.Theme theme = getBaseContext().getTheme();
             if (theme != null) {
                 mTheme.setTo(theme);
             }
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/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/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 20fe61d..b53af0c 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -72,6 +72,8 @@
  */
 @RemoteView
 public class ImageView extends View {
+    private static final String LOG_TAG = "ImageView";
+
     // settable by the client
     private Uri mUri;
     private int mResource = 0;
@@ -87,7 +89,7 @@
     private boolean mHasColorFilter = false;
     private Xfermode mXfermode;
     private int mAlpha = 255;
-    private int mViewAlphaScale = 256;
+    private final int mViewAlphaScale = 256;
     private boolean mColorMod = false;
 
     private Drawable mDrawable = null;
@@ -105,8 +107,8 @@
     private Matrix mDrawMatrix = null;
 
     // Avoid allocations...
-    private RectF mTempSrc = new RectF();
-    private RectF mTempDst = new RectF();
+    private final RectF mTempSrc = new RectF();
+    private final RectF mTempDst = new RectF();
 
     private boolean mCropToPadding;
 
@@ -116,6 +118,9 @@
     // AdjustViewBounds behavior will be in compatibility mode for older apps.
     private boolean mAdjustViewBoundsCompat = false;
 
+    /** Whether to pass Resources when creating the source from a stream. */
+    private boolean mUseCorrectStreamDensity;
+
     private static final ScaleType[] sScaleTypeArray = {
         ScaleType.MATRIX,
         ScaleType.FIT_XY,
@@ -147,30 +152,21 @@
         initImageView();
 
         final TypedArray a = context.obtainStyledAttributes(
-                attrs, com.android.internal.R.styleable.ImageView, defStyleAttr, defStyleRes);
+                attrs, R.styleable.ImageView, defStyleAttr, defStyleRes);
 
-        Drawable d = a.getDrawable(com.android.internal.R.styleable.ImageView_src);
+        final Drawable d = a.getDrawable(R.styleable.ImageView_src);
         if (d != null) {
             setImageDrawable(d);
         }
 
-        mBaselineAlignBottom = a.getBoolean(
-                com.android.internal.R.styleable.ImageView_baselineAlignBottom, false);
+        mBaselineAlignBottom = a.getBoolean(R.styleable.ImageView_baselineAlignBottom, false);
+        mBaseline = a.getDimensionPixelSize(R.styleable.ImageView_baseline, -1);
 
-        mBaseline = a.getDimensionPixelSize(
-                com.android.internal.R.styleable.ImageView_baseline, -1);
+        setAdjustViewBounds(a.getBoolean(R.styleable.ImageView_adjustViewBounds, false));
+        setMaxWidth(a.getDimensionPixelSize(R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
+        setMaxHeight(a.getDimensionPixelSize(R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));
 
-        setAdjustViewBounds(
-            a.getBoolean(com.android.internal.R.styleable.ImageView_adjustViewBounds,
-            false));
-
-        setMaxWidth(a.getDimensionPixelSize(
-                com.android.internal.R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
-        
-        setMaxHeight(a.getDimensionPixelSize(
-                com.android.internal.R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));
-        
-        final int index = a.getInt(com.android.internal.R.styleable.ImageView_scaleType, -1);
+        final int index = a.getInt(R.styleable.ImageView_scaleType, -1);
         if (index >= 0) {
             setScaleType(sScaleTypeArray[index]);
         }
@@ -193,24 +189,26 @@
 
         applyImageTint();
 
-        final int alpha = a.getInt(com.android.internal.R.styleable.ImageView_drawableAlpha, 255);
+        final int alpha = a.getInt(R.styleable.ImageView_drawableAlpha, 255);
         if (alpha != 255) {
-            setAlpha(alpha);
+            setImageAlpha(alpha);
         }
 
         mCropToPadding = a.getBoolean(
-                com.android.internal.R.styleable.ImageView_cropToPadding, false);
-        
+                R.styleable.ImageView_cropToPadding, false);
+
         a.recycle();
 
         //need inflate syntax/reader for matrix
     }
 
     private void initImageView() {
-        mMatrix     = new Matrix();
-        mScaleType  = ScaleType.FIT_CENTER;
-        mAdjustViewBoundsCompat = mContext.getApplicationInfo().targetSdkVersion <=
-                Build.VERSION_CODES.JELLY_BEAN_MR1;
+        mMatrix = new Matrix();
+        mScaleType = ScaleType.FIT_CENTER;
+
+        final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+        mAdjustViewBoundsCompat = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
+        mUseCorrectStreamDensity = targetSdkVersion > Build.VERSION_CODES.M;
     }
 
     @Override
@@ -258,7 +256,8 @@
     @Override
     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
         super.onPopulateAccessibilityEventInternal(event);
-        CharSequence contentDescription = getContentDescription();
+
+        final CharSequence contentDescription = getContentDescription();
         if (!TextUtils.isEmpty(contentDescription)) {
             event.getText().add(contentDescription);
         }
@@ -269,7 +268,7 @@
      * to preserve the aspect ratio of its drawable
      *
      * @return whether to adjust the bounds of this view
-     * to presrve the original aspect ratio of the drawable
+     * to preserve the original aspect ratio of the drawable
      *
      * @see #setAdjustViewBounds(boolean)
      *
@@ -291,7 +290,7 @@
      *
      * @param adjustViewBounds Whether to adjust the bounds of this view
      * to preserve the original aspect ratio of the drawable.
-     * 
+     *
      * @see #getAdjustViewBounds()
      *
      * @attr ref android.R.styleable#ImageView_adjustViewBounds
@@ -323,14 +322,14 @@
      * of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
      * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
      * layout params to WRAP_CONTENT.
-     * 
+     *
      * <p>
      * Note that this view could be still smaller than 100 x 100 using this approach if the original
      * image is small. To set an image to a fixed size, specify that size in the layout params and
      * then use {@link #setScaleType(android.widget.ImageView.ScaleType)} to determine how to fit
      * the image within the bounds.
      * </p>
-     * 
+     *
      * @param maxWidth maximum width for this view
      *
      * @see #getMaxWidth()
@@ -361,14 +360,14 @@
      * maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
      * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
      * layout params to WRAP_CONTENT.
-     * 
+     *
      * <p>
      * Note that this view could be still smaller than 100 x 100 using this approach if the original
      * image is small. To set an image to a fixed size, specify that size in the layout params and
      * then use {@link #setScaleType(android.widget.ImageView.ScaleType)} to determine how to fit
      * the image within the bounds.
      * </p>
-     * 
+     *
      * @param maxHeight maximum height for this view
      *
      * @see #getMaxHeight()
@@ -436,9 +435,7 @@
      */
     @android.view.RemotableViewMethod
     public void setImageURI(@Nullable Uri uri) {
-        if (mResource != 0 ||
-                (mUri != uri &&
-                 (uri == null || mUri == null || !uri.equals(mUri)))) {
+        if (mResource != 0 || (mUri != uri && (uri == null || mUri == null || !uri.equals(mUri)))) {
             updateDrawable(null);
             mResource = 0;
             mUri = uri;
@@ -457,7 +454,7 @@
 
     /**
      * Sets a drawable as the content of this ImageView.
-     * 
+     *
      * @param drawable the Drawable to set, or {@code null} to clear the
      *                 content
      */
@@ -577,7 +574,7 @@
 
     /**
      * Sets a Bitmap as the content of this ImageView.
-     * 
+     *
      * @param bm The bitmap to set
      */
     @android.view.RemotableViewMethod
@@ -609,7 +606,7 @@
     }
 
     /**
-     * Sets the image level, when it is constructed from a 
+     * Sets the image level, when it is constructed from a
      * {@link android.graphics.drawable.LevelListDrawable}.
      *
      * @param level The new level for the image.
@@ -675,7 +672,7 @@
          * From XML, use this syntax: <code>android:scaleType="centerInside"</code>.
          */
         CENTER_INSIDE (7);
-        
+
         ScaleType(int ni) {
             nativeInt = ni;
         }
@@ -685,9 +682,9 @@
     /**
      * Controls how the image should be resized or moved to match the size
      * of this ImageView.
-     * 
+     *
      * @param scaleType The desired scaling mode.
-     * 
+     *
      * @attr ref android.R.styleable#ImageView_scaleType
      */
     public void setScaleType(ScaleType scaleType) {
@@ -698,13 +695,13 @@
         if (mScaleType != scaleType) {
             mScaleType = scaleType;
 
-            setWillNotCacheDrawing(mScaleType == ScaleType.CENTER);            
+            setWillNotCacheDrawing(mScaleType == ScaleType.CENTER);
 
             requestLayout();
             invalidate();
         }
     }
-    
+
     /**
      * Return the current scale type in use by this ImageView.
      *
@@ -734,7 +731,7 @@
      * Adds a transformation {@link Matrix} that is applied
      * to the view's drawable when it is drawn.  Allows custom scaling,
      * translation, and perspective distortion.
-     * 
+     *
      * @param matrix the transformation parameters in matrix form
      */
     public void setImageMatrix(Matrix matrix) {
@@ -787,8 +784,8 @@
             return;
         }
 
-        Resources rsrc = getResources();
-        if (rsrc == null) {
+        final Resources res = getResources();
+        if (res == null) {
             return;
         }
 
@@ -798,12 +795,12 @@
             try {
                 d = mContext.getDrawable(mResource);
             } catch (Exception e) {
-                Log.w("ImageView", "Unable to find resource: " + mResource, e);
+                Log.w(LOG_TAG, "Unable to find resource: " + mResource, e);
                 // Don't try again.
                 mUri = null;
             }
         } else if (mUri != null) {
-            String scheme = mUri.getScheme();
+            final String scheme = mUri.getScheme();
             if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
                 try {
                     // Load drawable through Resources, to get the source density information
@@ -811,31 +808,32 @@
                             mContext.getContentResolver().getResourceId(mUri);
                     d = r.r.getDrawable(r.id, mContext.getTheme());
                 } catch (Exception e) {
-                    Log.w("ImageView", "Unable to open content: " + mUri, e);
+                    Log.w(LOG_TAG, "Unable to open content: " + mUri, e);
                 }
             } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
                     || ContentResolver.SCHEME_FILE.equals(scheme)) {
                 InputStream stream = null;
                 try {
                     stream = mContext.getContentResolver().openInputStream(mUri);
-                    d = Drawable.createFromStream(stream, null);
+                    d = Drawable.createFromResourceStream(
+                            mUseCorrectStreamDensity ? res : null, null, stream, null);
                 } catch (Exception e) {
-                    Log.w("ImageView", "Unable to open content: " + mUri, e);
+                    Log.w(LOG_TAG, "Unable to open content: " + mUri, e);
                 } finally {
                     if (stream != null) {
                         try {
                             stream.close();
                         } catch (IOException e) {
-                            Log.w("ImageView", "Unable to close content: " + mUri, e);
+                            Log.w(LOG_TAG, "Unable to close content: " + mUri, e);
                         }
                     }
                 }
-        } else {
+            } else {
                 d = Drawable.createFromPath(mUri.toString());
             }
-    
+
             if (d == null) {
-                System.out.println("resolveUri failed on bad bitmap uri: " + mUri);
+                Log.w(LOG_TAG, "resolveUri failed on bad bitmap uri: " + mUri);
                 // Don't try again.
                 mUri = null;
             }
@@ -890,7 +888,7 @@
     }
 
     private void resizeFromDrawable() {
-        Drawable d = mDrawable;
+        final Drawable d = mDrawable;
         if (d != null) {
             int w = d.getIntrinsicWidth();
             if (w < 0) w = mDrawableWidth;
@@ -923,23 +921,23 @@
     private static Matrix.ScaleToFit scaleTypeToScaleToFit(ScaleType st)  {
         // ScaleToFit enum to their corresponding Matrix.ScaleToFit values
         return sS2FArray[st.nativeInt - 1];
-    }    
+    }
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         resolveUri();
         int w;
         int h;
-        
+
         // Desired aspect ratio of the view's contents (not including padding)
         float desiredAspect = 0.0f;
-        
+
         // We are allowed to change the view's width
         boolean resizeWidth = false;
-        
+
         // We are allowed to change the view's height
         boolean resizeHeight = false;
-        
+
         final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
         final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
 
@@ -959,15 +957,15 @@
             if (mAdjustViewBounds) {
                 resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
                 resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
-                
+
                 desiredAspect = (float) w / (float) h;
             }
         }
-        
-        int pleft = mPaddingLeft;
-        int pright = mPaddingRight;
-        int ptop = mPaddingTop;
-        int pbottom = mPaddingBottom;
+
+        final int pleft = mPaddingLeft;
+        final int pright = mPaddingRight;
+        final int ptop = mPaddingTop;
+        final int pbottom = mPaddingBottom;
 
         int widthSize;
         int heightSize;
@@ -975,7 +973,7 @@
         if (resizeWidth || resizeHeight) {
             /* If we get here, it means we want to resize to match the
                 drawables aspect ratio, and we have the freedom to change at
-                least one dimension. 
+                least one dimension.
             */
 
             // Get the max possible width given our constraints
@@ -986,13 +984,13 @@
 
             if (desiredAspect != 0.0f) {
                 // See what our actual aspect ratio is
-                float actualAspect = (float)(widthSize - pleft - pright) /
+                final float actualAspect = (float)(widthSize - pleft - pright) /
                                         (heightSize - ptop - pbottom);
-                
+
                 if (Math.abs(actualAspect - desiredAspect) > 0.0000001) {
-                    
+
                     boolean done = false;
-                    
+
                     // Try adjusting width to be proportional to height
                     if (resizeWidth) {
                         int newWidth = (int)(desiredAspect * (heightSize - ptop - pbottom)) +
@@ -1006,9 +1004,9 @@
                         if (newWidth <= widthSize) {
                             widthSize = newWidth;
                             done = true;
-                        } 
+                        }
                     }
-                    
+
                     // Try adjusting height to be proportional to width
                     if (!done && resizeHeight) {
                         int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) +
@@ -1033,7 +1031,7 @@
             */
             w += pleft + pright;
             h += ptop + pbottom;
-                
+
             w = Math.max(w, getSuggestedMinimumWidth());
             h = Math.max(h, getSuggestedMinimumHeight());
 
@@ -1047,8 +1045,8 @@
     private int resolveAdjustedSize(int desiredSize, int maxSize,
                                    int measureSpec) {
         int result = desiredSize;
-        int specMode = MeasureSpec.getMode(measureSpec);
-        int specSize =  MeasureSpec.getSize(measureSpec);
+        final int specMode = MeasureSpec.getMode(measureSpec);
+        final int specSize =  MeasureSpec.getSize(measureSpec);
         switch (specMode) {
             case MeasureSpec.UNSPECIFIED:
                 /* Parent says we can be as big as we want. Just don't be larger
@@ -1057,8 +1055,8 @@
                 result = Math.min(desiredSize, maxSize);
                 break;
             case MeasureSpec.AT_MOST:
-                // Parent says we can be as big as we want, up to specSize. 
-                // Don't be larger than specSize, and don't be larger than 
+                // Parent says we can be as big as we want, up to specSize.
+                // Don't be larger than specSize, and don't be larger than
                 // the max size imposed on ourselves.
                 result = Math.min(Math.min(desiredSize, specSize), maxSize);
                 break;
@@ -1072,7 +1070,7 @@
 
     @Override
     protected boolean setFrame(int l, int t, int r, int b) {
-        boolean changed = super.setFrame(l, t, r, b);
+        final boolean changed = super.setFrame(l, t, r, b);
         mHaveFrame = true;
         configureBounds();
         return changed;
@@ -1083,14 +1081,14 @@
             return;
         }
 
-        int dwidth = mDrawableWidth;
-        int dheight = mDrawableHeight;
+        final int dwidth = mDrawableWidth;
+        final int dheight = mDrawableHeight;
 
-        int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
-        int vheight = getHeight() - mPaddingTop - mPaddingBottom;
+        final int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
+        final int vheight = getHeight() - mPaddingTop - mPaddingBottom;
 
-        boolean fits = (dwidth < 0 || vwidth == dwidth) &&
-                       (dheight < 0 || vheight == dheight);
+        final boolean fits = (dwidth < 0 || vwidth == dwidth)
+                && (dheight < 0 || vheight == dheight);
 
         if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
             /* If the drawable has no intrinsic size, or we're told to
@@ -1125,7 +1123,7 @@
                 float dx = 0, dy = 0;
 
                 if (dwidth * vheight > vwidth * dheight) {
-                    scale = (float) vheight / (float) dheight; 
+                    scale = (float) vheight / (float) dheight;
                     dx = (vwidth - dwidth * scale) * 0.5f;
                 } else {
                     scale = (float) vwidth / (float) dwidth;
@@ -1139,14 +1137,14 @@
                 float scale;
                 float dx;
                 float dy;
-                
+
                 if (dwidth <= vwidth && dheight <= vheight) {
                     scale = 1.0f;
                 } else {
                     scale = Math.min((float) vwidth / (float) dwidth,
                             (float) vheight / (float) dheight);
                 }
-                
+
                 dx = Math.round((vwidth - dwidth * scale) * 0.5f);
                 dy = Math.round((vheight - dheight * scale) * 0.5f);
 
@@ -1156,7 +1154,7 @@
                 // Generate the required transform.
                 mTempSrc.set(0, 0, dwidth, dheight);
                 mTempDst.set(0, 0, vwidth, vheight);
-                
+
                 mDrawMatrix = mMatrix;
                 mDrawMatrix.setRectToRect(mTempSrc, mTempDst, scaleTypeToScaleToFit(mScaleType));
             }
@@ -1166,7 +1164,8 @@
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        Drawable d = mDrawable;
+
+        final Drawable d = mDrawable;
         if (d != null && d.isStateful()) {
             d.setState(getDrawableState());
         }
@@ -1213,9 +1212,9 @@
         if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
             mDrawable.draw(canvas);
         } else {
-            int saveCount = canvas.getSaveCount();
+            final int saveCount = canvas.getSaveCount();
             canvas.save();
-            
+
             if (mCropToPadding) {
                 final int scrollX = mScrollX;
                 final int scrollY = mScrollY;
@@ -1223,7 +1222,7 @@
                         scrollX + mRight - mLeft - mPaddingRight,
                         scrollY + mBottom - mTop - mPaddingBottom);
             }
-            
+
             canvas.translate(mPaddingLeft, mPaddingTop);
 
             if (mDrawMatrix != null) {
@@ -1258,7 +1257,7 @@
      *
      * @param baseline The baseline to use, or -1 if none is to be provided.
      *
-     * @see #setBaseline(int) 
+     * @see #setBaseline(int)
      * @attr ref android.R.styleable#ImageView_baseline
      */
     public void setBaseline(int baseline) {
@@ -1295,11 +1294,11 @@
 
     /**
      * Set a tinting option for the image.
-     * 
+     *
      * @param color Color tint to apply.
      * @param mode How to apply the color.  The standard mode is
      * {@link PorterDuff.Mode#SRC_ATOP}
-     * 
+     *
      * @attr ref android.R.styleable#ImageView_tint
      */
     public final void setColorFilter(int color, PorterDuff.Mode mode) {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 088adbb..ad2b4a7 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -816,7 +816,15 @@
         mSearchButton.setVisibility(visCollapsed);
         updateSubmitButton(hasText);
         mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE);
-        mCollapsedIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE);
+
+        final int iconVisibility;
+        if (mCollapsedIcon.getDrawable() == null || mIconifiedByDefault) {
+            iconVisibility = GONE;
+        } else {
+            iconVisibility = VISIBLE;
+        }
+        mCollapsedIcon.setVisibility(iconVisibility);
+
         updateCloseButton();
         updateVoiceButton(!hasText);
         updateSubmitArea();
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 7db2cc9f..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_media_AudioErrors.h b/core/jni/android_media_AudioErrors.h
index 4907830..c17a020 100644
--- a/core/jni/android_media_AudioErrors.h
+++ b/core/jni/android_media_AudioErrors.h
@@ -32,6 +32,7 @@
     AUDIO_JAVA_PERMISSION_DENIED  = -4,
     AUDIO_JAVA_NO_INIT            = -5,
     AUDIO_JAVA_DEAD_OBJECT        = -6,
+    AUDIO_JAVA_WOULD_BLOCK        = -7,
 };
 
 static inline jint nativeToJavaStatus(status_t status) {
@@ -46,6 +47,8 @@
         return AUDIO_JAVA_PERMISSION_DENIED;
     case NO_INIT:
         return AUDIO_JAVA_NO_INIT;
+    case WOULD_BLOCK:
+        return AUDIO_JAVA_WOULD_BLOCK;
     case DEAD_OBJECT:
         return AUDIO_JAVA_DEAD_OBJECT;
     default:
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-mcc219-mnc02/config.xml b/core/res/res/values-mcc219-mnc02/config.xml
new file mode 100644
index 0000000..2ac6ba6
--- /dev/null
+++ b/core/res/res/values-mcc219-mnc02/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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 my 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Don't use roaming icon for considered operators -->
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21901</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index cfdd69b..d77dca1f 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -39,7 +39,7 @@
     <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
     <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> seconden"</string>
     <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> seconde"</string>
-    <string name="untitled" msgid="4638956954852782576">"&lt;Zonder titel&gt;"</string>
+    <string name="untitled" msgid="4638956954852782576">"&lt;Naamloos&gt;"</string>
     <string name="emptyPhoneNumber" msgid="7694063042079676517">"(Geen telefoonnummer)"</string>
     <string name="unknownName" msgid="6867811765370350269">"Onbekend"</string>
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Voicemail"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 2cf1d1e..d215d4c 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -50,7 +50,7 @@
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Serviciul a fost activat pentru:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Serviciul a fost dezactivat."</string>
     <string name="serviceRegistered" msgid="6275019082598102493">"Înregistrarea a reuşit."</string>
-    <string name="serviceErased" msgid="1288584695297200972">"Ștergerea a reuşit."</string>
+    <string name="serviceErased" msgid="1288584695297200972">"Ștergerea a reușit."</string>
     <string name="passwordIncorrect" msgid="7612208839450128715">"Parolă incorectă."</string>
     <string name="mmiComplete" msgid="8232527495411698359">"MMI finalizat."</string>
     <string name="badPin" msgid="9015277645546710014">"Codul PIN vechi introdus nu este corect."</string>
@@ -59,7 +59,7 @@
     <string name="invalidPin" msgid="3850018445187475377">"Introduceţi un cod PIN alcătuit din 4 până la 8 cifre."</string>
     <string name="invalidPuk" msgid="8761456210898036513">"Introduceţi un cod PUK care să aibă 8 cifre sau mai mult."</string>
     <string name="needPuk" msgid="919668385956251611">"Cardul SIM este blocat cu codul PUK. Introduceţi codul PUK pentru a-l debloca."</string>
-    <string name="needPuk2" msgid="4526033371987193070">"Introduceţi codul PUK2 pentru a debloca cardul SIM."</string>
+    <string name="needPuk2" msgid="4526033371987193070">"Introduceți codul PUK2 pentru a debloca cardul SIM."</string>
     <string name="enablePin" msgid="209412020907207950">"Operațiunea nu a reușit. Activați blocarea cardului SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
       <item quantity="few">V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> încercări până la blocarea cardului SIM.</item>
@@ -85,8 +85,8 @@
     <string name="DndMmi" msgid="1265478932418334331">"Nu deranjaţi"</string>
     <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"ID-ul apelantului este restricţionat în mod prestabilit. Apelul următor: restricţionat"</string>
     <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"ID-ul apelantului este restricționat în mod prestabilit. Apelul următor: nerestricționat"</string>
-    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"ID-ul apelantului este nerestricţionat în mod prestabilit. Apelul următor: Restricţionat."</string>
-    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID-ul apelantului este nerestricţionat în mod prestabilit. Apelul următor: nerestricţionat"</string>
+    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"ID-ul apelantului este nerestricționat în mod prestabilit. Apelul următor: Restricționat."</string>
+    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID-ul apelantului este nerestricționat în mod prestabilit. Apelul următor: nerestricționat"</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"Nu se asigură accesul la acest serviciu."</string>
     <string name="CLIRPermanent" msgid="3377371145926835671">"Nu puteți să modificaţi setarea pentru ID-ul apelantului."</string>
     <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Acces restricționat modificat"</string>
@@ -181,7 +181,7 @@
     <string name="power_dialog" product="tv" msgid="6153888706430556356">"Opțiuni TV"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Opţiuni telefon"</string>
     <string name="silent_mode" msgid="7167703389802618663">"Mod Silențios"</string>
-    <string name="turn_on_radio" msgid="3912793092339962371">"Activați funcţia wireless"</string>
+    <string name="turn_on_radio" msgid="3912793092339962371">"Activați funcția wireless"</string>
     <string name="turn_off_radio" msgid="8198784949987062346">"Dezactivați funcția wireless"</string>
     <string name="screen_lock" msgid="799094655496098153">"Blocați ecranul"</string>
     <string name="power_off" msgid="4266614107412865048">"Opriți alimentarea"</string>
@@ -266,9 +266,9 @@
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"redirecţionează apelurile efectuate"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permite aplicației să vadă numărul format în timpul unui apel de ieșire, cu opțiunea de a redirecționa apelul către un alt număr sau de a întrerupe apelul."</string>
     <string name="permlab_receiveSms" msgid="8673471768947895082">"primeşte mesaje text (SMS)"</string>
-    <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite aplicației să primească și să proceseze mesaje SMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau şterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
+    <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite aplicației să primească și să proceseze mesaje SMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primeşte mesaje text (MMS)"</string>
-    <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite aplicației să primească și să proceseze mesaje MMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau şterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
+    <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite aplicației să primească și să proceseze mesaje MMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"citeşte mesajele cu transmisie celulară"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite aplicației să citească mesajele primite prin transmisie celulară de dispozitivul dvs. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situaţiile de urgenţă. Aplicaţiile rău intenţionate pot afecta performanţa sau funcţionarea dispozitivului dvs. când este primită o transmisie celulară de urgenţă."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"citire feeduri abonat"</string>
@@ -280,7 +280,7 @@
     <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"Permite aplicației să citească mesajele SMS stocate pe televizor sau pe cardul SIM. Cu această permisiune, aplicația poate citi toate mesajele SMS, indiferent de conținutul sau de gradul de confidențialitate al acestora."</string>
     <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Permite aplicației să citească mesajele SMS stocate pe telefon sau pe cardul SIM. În acest fel, aplicația poate citi toate mesajele SMS, indiferent de conţinutul sau de gradul de confidenţialitate al acestora."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"primeşte mesaje text (WAP)"</string>
-    <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite aplicației să primească și să proceseze mesaje WAP. Această permisiune include capacitatea de a monitoriza sau şterge mesajele care v-au fost trimise fără a vi le arăta."</string>
+    <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite aplicației să primească și să proceseze mesaje WAP. Această permisiune include capacitatea de a monitoriza sau șterge mesajele care v-au fost trimise fără a vi le arăta."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"preluare aplicații care rulează"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite aplicației să preia informațiile despre activităţile care rulează în prezent și care au rulat recent. În acest fel, aplicația poate descoperi informații despre aplicațiile care sunt utilizate pe dispozitiv."</string>
     <string name="permlab_manageProfileAndDeviceOwners" msgid="5979288447973722097">"Gestionează proprietarii de profiluri și proprietarul dispozitivului"</string>
@@ -314,17 +314,17 @@
     <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"Permite aplicației să citească datele despre persoanele de contact salvate pe televizor, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune, aplicațiile pot salva datele de contact, iar aplicațiile rău-intenționate pot permite accesul la datele de contact fără cunoștința dvs."</string>
     <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Permite aplicației să citească datele despre persoanele din agenda stocată pe telefon, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenţionate pot distribui datele de contact fără ştirea dvs."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"modifică agenda"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate şterge datele de contact."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
     <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Permite aplicației să modifice datele despre persoanele de contact salvate pe televizor, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane de contact. Cu această permisiune, aplicația poate șterge datele de contact."</string>
-    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe telefon, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate şterge datele de contact."</string>
+    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe telefon, inclusiv frecvenţa cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"citeşte jurnalul de apeluri"</string>
     <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Permite aplicației să citească jurnalul de apeluri al tabletei, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune aplicația salvează datele dvs. din jurnalul de apeluri, iar aplicațiile rău intenţionate pot distribui aceste date fără ştirea dvs."</string>
     <string name="permdesc_readCallLog" product="tv" msgid="5611770887047387926">"Permite aplicației să citească jurnalul de apeluri al televizorului, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune, aplicațiile pot să salveze datele din jurnalul de apeluri, iar aplicațiile rău-intenționate pot permite accesul la datele din jurnalul de apeluri fără cunoștința dvs."</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Permite aplicației să citească jurnalul de apeluri al telefonului, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune aplicația salvează datele dvs. din jurnalul de apeluri, iar aplicațiile rău intenţionate pot distribui aceste date fără ştirea dvs."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"scrie jurnalul de apeluri"</string>
-    <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Permite aplicației să modifice jurnalul de apeluri al tabletei dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a şterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
+    <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Permite aplicației să modifice jurnalul de apeluri al tabletei dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
     <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Permite aplicației să modifice jurnalul de apeluri al televizorului, inclusiv datele despre apelurile primite sau efectuate. Aplicațiile rău-intenționate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul de apeluri."</string>
-    <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite aplicației să modifice jurnalul de apeluri al telefonului dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a şterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
+    <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite aplicației să modifice jurnalul de apeluri al telefonului dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
     <string name="permlab_bodySensors" msgid="4871091374767171066">"senzori (ex.: senzori de ritm cardiac)"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite aplicației să acceseze date de la senzorii care vă monitorizează starea fizică, cum ar fi ritmul cardiac."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"citirea evenimentelor din calendar și a informaţiilor confidenţiale"</string>
@@ -335,7 +335,7 @@
     <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteți modifica pe tabletă, inclusiv cele ale prietenilor sau colegilor dvs. În acest fel, aplicația poate trimite mesaje care par să vină de la proprietarii calendarelor sau să modifice evenimentele fără ştirea proprietarilor."</string>
     <string name="permdesc_writeCalendar" product="tv" msgid="1273290605500902507">"Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteți modifica pe televizor, inclusiv pe cele ale prietenilor sau ale colegilor. Cu această permisiune, aplicația poate să trimită mesaje care par că vin din partea proprietarilor calendarului sau să modifice evenimentele fără cunoștința acestora."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteți modifica pe telefon, inclusiv cele ale prietenilor sau colegilor dvs. În acest fel, aplicația poate trimite mesaje care par să vină de la proprietarii calendarelor sau să modifice evenimentele fără ştirea proprietarilor."</string>
-    <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accesare comenzi suplimentare ale furnizorului locaţiei"</string>
+    <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accesare comenzi suplimentare ale furnizorului locației"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite aplicației să acceseze comenzi suplimentare pentru furnizorul locației. Aplicația ar putea să utilizeze această permisiune pentru a influența operațiile GPS sau ale altor surse de locații."</string>
     <string name="permlab_accessFineLocation" msgid="1191898061965273372">"locaţia exactă (bazată pe rețea și GPS)"</string>
     <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permite aplicației să obţină locaţia dvs. exactă utilizând sistemul GPS (Global Positioning System) sau surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locaţia dvs. și pot să consume mai multă energie a bateriei."</string>
@@ -446,8 +446,8 @@
     <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"citeşte conţinutul cardului SD"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"Permite aplic. citirea conținutului stoc. USB."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"Permite aplicației citirea conținutul cardului SD."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modifică sau şterge conţinutul stocării USB"</string>
-    <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifică sau şterge conţinutul cardului SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modifică sau șterge conţinutul stocării USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifică sau șterge conţinutul cardului SD"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Permite scriere în stoc. USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Permite aplicației să scrie pe cardul SD."</string>
     <string name="permlab_use_sip" msgid="2052499390128979920">"efectuarea/primirea apelurilor SIP"</string>
@@ -650,10 +650,10 @@
     <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Introduceţi codul PIN pentru a debloca"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Cod PIN incorect."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Pentru a debloca, apăsaţi Meniu, apoi 0."</string>
-    <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Număr de urgenţă"</string>
+    <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Număr de urgență"</string>
     <string name="lockscreen_carrier_default" msgid="8963839242565653192">"Fără serviciu."</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Ecranul este blocat."</string>
-    <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Apăsaţi Meniu pentru a debloca sau pentru a efectua apeluri de urgenţă."</string>
+    <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Apăsați Meniu pentru a debloca sau pentru a efectua apeluri de urgență."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Apăsaţi Meniu pentru deblocare."</string>
     <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Desenaţi modelul pentru a debloca"</string>
     <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Urgență"</string>
@@ -710,7 +710,7 @@
     <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Sunet activat"</string>
     <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Sunet dezactivat"</string>
     <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Desenarea modelului a început"</string>
-    <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Modelul a fost şters"</string>
+    <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Modelul a fost șters"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Celulă adăugată"</string>
     <string name="lockscreen_access_pattern_cell_added_verbose" msgid="7264580781744026939">"Celula <xliff:g id="CELL_INDEX">%1$s</xliff:g> a fost adăugată"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Modelul a fost desenat"</string>
@@ -755,7 +755,7 @@
     <string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"Părăsiți această pagină"</string>
     <string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"Rămâneți în această pagină"</string>
     <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nSigur doriți să părăsiți această pagină?"</string>
-    <string name="save_password_label" msgid="6860261758665825069">"Confirmaţi"</string>
+    <string name="save_password_label" msgid="6860261758665825069">"Confirmați"</string>
     <string name="double_tap_toast" msgid="4595046515400268881">"Sfat: măriţi și micşoraţi prin dublă atingere."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Automat"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Conf.Compl.auto."</string>
@@ -778,9 +778,9 @@
     <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"citeşte marcajele și istoricul web"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Permite aplicației să citească istoricul tuturor adreselor URL accesate de Browser și toate marcajele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicații cu capacităţi de navigare pe web."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"scrie în marcajele și în istoricul web"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Permite aplicației să modifice istoricul Browserului sau marcajele stocate pe tabletă. În acest fel, aplicația poate şterge sau modifica datele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicații cu capacităţi de navigare pe web."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Permite aplicației să modifice istoricul Browserului sau marcajele stocate pe tabletă. În acest fel, aplicația poate șterge sau modifica datele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicații cu capacităţi de navigare pe web."</string>
     <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"Permite aplicației să modifice istoricul sau marcajele browserului stocate pe televizor. Cu această permisiune, aplicația poate șterge sau modifica datele din browser. Notă: această permisiune nu poate fi aplicată de browsere terță parte sau de alte aplicații cu capacități de navigare pe web."</string>
-    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite aplicației să modifice istoricul Browserului sau marcajele stocate pe telefon. În acest fel, aplicația poate şterge sau modifica datele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicații cu capacităţi de navigare pe web."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite aplicației să modifice istoricul Browserului sau marcajele stocate pe telefon. În acest fel, aplicația poate șterge sau modifica datele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicații cu capacităţi de navigare pe web."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"setează o alarmă"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite aplicației să seteze o alarmă într-o aplicație de ceas cu alarmă instalată. Este posibil ca unele aplicații de ceas cu alarmă să nu implementeze această funcție."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"adăugare mesagerie vocală"</string>
@@ -795,7 +795,7 @@
     <string name="text_copied" msgid="4985729524670131385">"Text copiat în clipboard."</string>
     <string name="more_item_label" msgid="4650918923083320495">"Mai multe"</string>
     <string name="prepend_shortcut_label" msgid="2572214461676015642">"Meniu+"</string>
-    <string name="menu_space_shortcut_label" msgid="2410328639272162537">"spaţiu"</string>
+    <string name="menu_space_shortcut_label" msgid="2410328639272162537">"spațiu"</string>
     <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"enter"</string>
     <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"delete"</string>
     <string name="search_go" msgid="8298016669822141719">"Căutați"</string>
@@ -1140,8 +1140,8 @@
       <item quantity="one">Un rezultat</item>
     </plurals>
     <string name="action_mode_done" msgid="7217581640461922289">"Terminat"</string>
-    <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Se şterge stocarea USB..."</string>
-    <string name="progress_erasing" product="default" msgid="6596988875507043042">"Se şterge cardul SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Se șterge stocarea USB..."</string>
+    <string name="progress_erasing" product="default" msgid="6596988875507043042">"Se șterge cardul SD..."</string>
     <string name="share" msgid="1778686618230011964">"Distribuiţi"</string>
     <string name="find" msgid="4808270900322985960">"Găsiţi"</string>
     <string name="websearch" msgid="4337157977400211589">"Căutare pe web"</string>
diff --git a/core/res/res/values-watch/strings.xml b/core/res/res/values-watch/strings.xml
index 4ea2b52..e5991fc 100644
--- a/core/res/res/values-watch/strings.xml
+++ b/core/res/res/values-watch/strings.xml
@@ -23,4 +23,50 @@
     <string name="android_upgrading_apk">App
         <xliff:g id="number" example="123">%1$d</xliff:g> of
         <xliff:g id="number" example="123">%2$d</xliff:g>.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. Override from base which says "Body Sensors". [CHAR_LIMIT=25] -->
+    <string name="permgrouplab_sensors">Sensors</string>
+
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permgrouplab_contactswear">access your contacts</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permgrouplab_locationwear">access this watch\'s location</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permgrouplab_calendarwear">access your calendar</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permgrouplab_smswear">send and view SMS messages</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permgrouplab_storagewear">access photos, media, and files on your watch</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permgrouplab_microphonewear">record audio</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permgrouplab_camerawear">take pictures and record video</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permgrouplab_phonewear">make and manage phone calls</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permgrouplab_sensorswear">access sensor data about your vital signs</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_statusBarServicewear">be the status bar</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_bodySensorswear">access body sensors (like heart rate monitors)</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_accessFineLocationwear">access precise location (GPS and network-based)</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_accessCoarseLocationwear">access approximate location (network-based)</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_sim_communicationwear">send commands to the SIM</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_createNetworkSocketswear">have full network access</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_manageProfileAndDeviceOwnerswear">manage profile and device owners</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_changeWimaxStatewear">change WiMAX state</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_handoverStatuswear">receive Android Beam transfer status</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_route_media_outputwear">route media output</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_readInstallSessionswear">read install sessions</string>
+    <!-- Description of a  permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=100] -->
+    <string name="permlab_requestInstallPackageswear">request install packages</string>
 </resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 1a45b3a..1a2600d 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="activityWidth" 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="activityHeight" 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/public.xml b/core/res/res/values/public.xml
index cabb56c..d2089cd 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2679,5 +2679,7 @@
     <public type="style" name="Theme.Material.DayNight.DialogWhenLarge.DarkActionBar" />
 
     <public type="id" name="accessibilityActionSetProgress" />
+    <public type="attr" name="activityWidth" />
+    <public type="attr" name="activityHeight" />
 
 </resources>
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/app/backup/FullBackupTest.java b/core/tests/coretests/src/android/app/backup/FullBackupTest.java
index 8c9c63c..c3afbf6 100644
--- a/core/tests/coretests/src/android/app/backup/FullBackupTest.java
+++ b/core/tests/coretests/src/android/app/backup/FullBackupTest.java
@@ -114,12 +114,14 @@
     public void testparseBackupSchemeFromXml_lotsOfIncludesAndExcludes() throws Exception {
         mXpp.setInput(new StringReader(
                 "<full-backup-content>" +
-                        "<exclude path=\"exclude1.txt\" domain=\"file\"/>" +
+                         "<exclude path=\"exclude1.txt\" domain=\"file\"/>" +
                         "<include path=\"include1.txt\" domain=\"file\"/>" +
                          "<exclude path=\"exclude2.txt\" domain=\"database\"/>" +
                         "<include path=\"include2.txt\" domain=\"database\"/>" +
-                         "<exclude path=\"exclude3.txt\" domain=\"sharedpref\"/>" +
-                        "<include path=\"include3.txt\" domain=\"sharedpref\"/>" +
+                         "<exclude path=\"exclude3\" domain=\"sharedpref\"/>" +
+                        "<include path=\"include3\" domain=\"sharedpref\"/>" +
+                         "<exclude path=\"exclude4.xml\" domain=\"sharedpref\"/>" +
+                        "<include path=\"include4.xml\" domain=\"sharedpref\"/>" +
                 "</full-backup-content>"));
 
 
@@ -146,16 +148,27 @@
                                 "include2.txt-journal")
                                 .getCanonicalPath()));
 
-        Set<String> sharedPrefDomainIncludes = includeMap.get(FullBackup.SHAREDPREFS_TREE_TOKEN);
+        List<String> sharedPrefDomainIncludes = new ArrayList<String>(
+                includeMap.get(FullBackup.SHAREDPREFS_TREE_TOKEN));
+        Collections.sort(sharedPrefDomainIncludes);
+
         assertEquals("Didn't find expected sharedpref domain include.",
-                1, sharedPrefDomainIncludes.size());
+                3, sharedPrefDomainIncludes.size());
         assertEquals("Invalid path parsed for <include/>",
-                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include3.txt")
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include3")
                         .getCanonicalPath(),
-                sharedPrefDomainIncludes.iterator().next());
+                sharedPrefDomainIncludes.get(0));
+        assertEquals("Invalid path parsed for <include/>",
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include3.xml")
+                        .getCanonicalPath(),
+                sharedPrefDomainIncludes.get(1));
+        assertEquals("Invalid path parsed for <include/>",
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include4.xml")
+                        .getCanonicalPath(),
+                sharedPrefDomainIncludes.get(2));
 
 
-        assertEquals("Unexpected number of <exclude/>s", 4, excludesSet.size());
+        assertEquals("Unexpected number of <exclude/>s", 6, excludesSet.size());
         // Sets are annoying to iterate over b/c order isn't enforced - convert to an array and
         // sort lexicographically.
         List<String> arrayedSet = new ArrayList<String>(excludesSet);
@@ -173,9 +186,17 @@
                 new File(mContext.getFilesDir(), "exclude1.txt").getCanonicalPath(),
                 arrayedSet.get(2));
         assertEquals("Invalid path parsed for <exclude/>",
-                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude3.txt")
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude3")
                         .getCanonicalPath(),
                 arrayedSet.get(3));
+        assertEquals("Invalid path parsed for <exclude/>",
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude3.xml")
+                        .getCanonicalPath(),
+                arrayedSet.get(4));
+        assertEquals("Invalid path parsed for <exclude/>",
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude4.xml")
+                        .getCanonicalPath(),
+                arrayedSet.get(5));
     }
 
     public void testParseBackupSchemeFromXml_invalidXmlFails() throws Exception {
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/preview/features/runtime-permissions.jd b/docs/html/preview/features/runtime-permissions.jd
index 8ab7619..62e49b9 100644
--- a/docs/html/preview/features/runtime-permissions.jd
+++ b/docs/html/preview/features/runtime-permissions.jd
@@ -916,8 +916,11 @@
   </dt>
 
   <dd>
-    Returns <code>true</code> if the app has the specified permission, whether
-    or not the device is using the M Preview.
+    Returns {@link android.content.pm.PackageManager#PERMISSION_GRANTED
+    PERMISSION_GRANTED} if the app has the specified permission, whether
+    or not the device is using the M Preview. If the app does not have the
+    specified permission, returns {@link
+    android.content.pm.PackageManager#PERMISSION_DENIED PERMISSION_DENIED}.
   </dd>
 
   <dt>
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/sdk/index.jd b/docs/html/sdk/index.jd
index dbc0f35..39822e5 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -5,28 +5,28 @@
 header.hide=1
 page.metaDescription=Download the official Android IDE and developer tools to build apps for Android phones, tablets, wearables, TVs, and more.
 
-studio.version=1.3.1.0
+studio.version=1.3.2.0
 
-studio.linux_bundle_download=android-studio-ide-141.2135290-linux.zip
-studio.linux_bundle_bytes=351992670
-studio.linux_bundle_checksum=51e5f5de2b82883d87f85ee38cf7b7b8b2e7debf
+studio.linux_bundle_download=android-studio-ide-141.2178183-linux.zip
+studio.linux_bundle_bytes=352010593
+studio.linux_bundle_checksum=cf780413f8c8223eb348bd27c19a9c04b75eaeb2
 
-studio.mac_bundle_download=android-studio-ide-141.2135290-mac.dmg
-studio.mac_bundle_bytes=368321249
-studio.mac_bundle_checksum=9fc12b5657ff52c761b7e7c115feade2a9728386
+studio.mac_bundle_download=android-studio-ide-141.2178183-mac.dmg
+studio.mac_bundle_bytes=368335367
+studio.mac_bundle_checksum=75b67eb15a34a152a40e7189484ab0ebc375b877
 
-studio.win_bundle_download=android-studio-ide-141.2135290-windows.zip
-studio.win_bundle_bytes=344406793
-studio.win_bundle_checksum=3b4c4924cb9495e56db61ca0e8c8d2bf588c4b97
+studio.win_bundle_download=android-studio-ide-141.2178183-windows.zip
+studio.win_bundle_bytes=344424713
+studio.win_bundle_checksum=3134f226b5f3c3f74d4fc2d9cff03a4458f01d69
 
 
-studio.win_bundle_exe_download=android-studio-bundle-141.2135290-windows.exe
-studio.win_bundle_exe_bytes=1008506096
-studio.win_bundle_exe_checksum=8cff590f2e08e339f8c2491b287a840ae87c7383
+studio.win_bundle_exe_download=android-studio-bundle-141.2178183-windows.exe
+studio.win_bundle_exe_bytes=1136982712
+studio.win_bundle_exe_checksum=c7d39c529dd434489da9d086ff689d34dc791526
 
-studio.win_notools_exe_download=android-studio-ide-141.2135290-windows.exe
-studio.win_notools_exe_bytes=321791312
-studio.win_notools_exe_checksum=d70fb49d03db9dded19c891a92452601e39272f4
+studio.win_notools_exe_download=android-studio-ide-141.2178183-windows.exe
+studio.win_notools_exe_bytes=321810248
+studio.win_notools_exe_checksum=b5d1aaa000729c03a3cf980add79d1b93121c56d
 
 
 
@@ -289,7 +289,7 @@
 </ul>
 
 <a class="online landing-button green download-bundle-button"
-href="#Other" >Download Android Studio</a>
+href="#Other" >Download Android Studio<br/><span class='small'></span></a>
 
 <!-- this appears when viewing the offline docs -->
 <p class="offline">
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/tools/revisions/studio.jd b/docs/html/tools/revisions/studio.jd
index c922b28..298b173 100644
--- a/docs/html/tools/revisions/studio.jd
+++ b/docs/html/tools/revisions/studio.jd
@@ -43,6 +43,29 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>Android Studio v1.3.2</a> <em>(August 2015)</em>
+  </p>
+  <div class="toggle-content-toggleme">
+    <p>Fixes and enhancements:</p>
+    <ul>
+      <li>Added support for Android 6.0 (API level 23), including new icons and AVD Manager
+        support for creating devices with new screen densities.</li>
+      <li>Fixed an exception that was occuring during update checks.
+        <a href="http://b.android.com/183068">Issue: 183068</a></li>
+      <li>Fixed problem where unresolved view coordinates could cause the layout editor to crash.
+        <a href="http://b.android.com/178690">Issue: 178690</a></li>
+      <li>Fixed issue with invalid resource type warnings.
+        <a href="http://b.android.com/182433">Issue: 182433</a></li>
+      <li>Fixed lint check that was incorrectly flagging resources as private.
+        <a href="http://b.android.com/183120">Issue: 183120</a></li>
+    </ul>
+  </div>
+</div>
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>Android Studio v1.3.1</a> <em>(August 2015)</em>
   </p>
   <div class="toggle-content-toggleme">
@@ -60,8 +83,6 @@
 </div>
 
 
-
-
 <div class="toggle-content closed">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
@@ -100,7 +121,7 @@
       <li>Added <a href="{@docRoot}tools/data-binding/guide.html">data binding</a> support to
         create declarative layouts that bind your application logic to layout elements. </li>
       <li>Added support for a separate
-        <a href="{@docRoot}tools/studio/studio-features.html#test-module">test APK module</a> 
+        <a href="{@docRoot}tools/studio/studio-features.html#test-module">test APK module</a>
         to build test APKs in Android Studio.  </li>
       <li>Updated the <a href="{@docRoot}tools/help/avd-manager.html">AVD Manager</a> with HAXM
         optimizations and improved notifications. </li>
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index 08634da..3c12a64 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -53,6 +53,39 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>ADT 23.0.7</a> <em>(August 2015)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Java 7 or higher is required if you are targeting Android 5.0 and higher.</li>
+      <li>Java 1.6 or higher is required if you are targeting other releases.</li>
+      <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li>
+      <li>This version of ADT is designed for use with
+        <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r24.1.2</a>.
+        If you haven't already installed SDK Tools r24.1.2 into your SDK, use the
+        Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>General Notes:</dt>
+  <dd>
+    <ul>
+        <li>Fixed issues with the rendering library for the visual layout editor.</li>
+    </ul>
+  </dd>
+</dl>
+</div>
+</div>
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>ADT 23.0.6</a> <em>(March 2015)</em>
   </p>
 
@@ -75,7 +108,7 @@
   <dt>General Notes:</dt>
   <dd>
     <ul>
-        <li>Fixed issues with the rendering library.</li>
+        <li>Fixed issues with the rendering library for the visual layout editor.</li>
     </ul>
   </dd>
 </dl>
diff --git a/docs/html/tools/support-library/features.jd b/docs/html/tools/support-library/features.jd
index b3af7a2..19f93e9 100644
--- a/docs/html/tools/support-library/features.jd
+++ b/docs/html/tools/support-library/features.jd
@@ -307,8 +307,8 @@
 on how to set up your project, follow the instructions in <a
 href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
 with resources</a>. If you are developing in Eclipse/ADT, make sure to include
-both the <code>android-support-v7-mediarouter.jar</code> and
-<code>android-support-v7-appcompat.jar</code> files.</p>
+the <code>android-support-v7-mediarouter.jar</code>, <code>android-support-v7-appcompat.jar</code>,
+and <code>android-support-v7-palette.jar</code> files.</p>
 
 <p>If you are using Android Studio, all you need to do is specify the Gradle build
 script dependency identifier <code>com.android.support:support-v7-mediarouter:&lt;revision&gt;</code>,
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/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 1c14e2f..d960c8f 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -131,15 +131,7 @@
         mPropX = CanvasProperty.createFloat(0);
         mPropY = CanvasProperty.createFloat(0);
 
-        // Linear "fast" enter based on current opacity.
         final int fastEnterDuration = (int) ((1 - mOpacity) * OPACITY_ENTER_DURATION_FAST);
-        if (fastEnterDuration > 0) {
-            final RenderNodeAnimator enter = new RenderNodeAnimator(
-                    mPropPaint, RenderNodeAnimator.PAINT_ALPHA, targetAlpha);
-            enter.setInterpolator(LINEAR_INTERPOLATOR);
-            enter.setDuration(fastEnterDuration);
-            set.add(enter);
-        }
 
         // Linear exit after enter is completed.
         final RenderNodeAnimator exit = new RenderNodeAnimator(
@@ -149,6 +141,15 @@
         exit.setStartDelay(fastEnterDuration);
         set.add(exit);
 
+        // Linear "fast" enter based on current opacity.
+        if (fastEnterDuration > 0) {
+            final RenderNodeAnimator enter = new RenderNodeAnimator(
+                    mPropPaint, RenderNodeAnimator.PAINT_ALPHA, targetAlpha);
+            enter.setInterpolator(LINEAR_INTERPOLATOR);
+            enter.setDuration(fastEnterDuration);
+            set.add(enter);
+        }
+
         return set;
     }
 
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/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index 54fb5f2..e307ad9 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -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 bb149fe..506bfad 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -216,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 f29e835..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
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 8bb892f..14126a9 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1524,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 c9e3880..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;
     }
 }
 
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/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b35c017..5692d7e 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2268,7 +2268,7 @@
     mDirty = true;
 }
 
-void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
+void OpenGLRenderer::drawLayer(Layer* layer) {
     if (!layer) {
         return;
     }
@@ -2284,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) {
@@ -2313,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
@@ -2326,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 45662a7..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);
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 73c0107..7d09c0b 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -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;
     }
@@ -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 0c5b4b7..36633b5 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -701,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 41152dc..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;
 
@@ -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;
@@ -284,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);
 }
@@ -320,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 ca19a42..4d60b8d 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -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 {
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/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 0f1be6b..e92f294 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -671,15 +671,15 @@
             case USAGE_VOICE_COMMUNICATION:
                 return new String("USAGE_VOICE_COMMUNICATION");
             case USAGE_VOICE_COMMUNICATION_SIGNALLING:
-                return new String("USAGE_VOICE_COMMUNICATION");
+                return new String("USAGE_VOICE_COMMUNICATION_SIGNALLING");
             case USAGE_ALARM:
                 return new String("USAGE_ALARM");
             case USAGE_NOTIFICATION:
                 return new String("USAGE_NOTIFICATION");
             case USAGE_NOTIFICATION_RINGTONE:
-                return new String("USAGE_NOTIFICATION");
+                return new String("USAGE_NOTIFICATION_RINGTONE");
             case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-                return new String("USAGE_NOTIFICATION");
+                return new String("USAGE_NOTIFICATION_COMMUNICATION_REQUEST");
             case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
                 return new String("USAGE_NOTIFICATION_COMMUNICATION_INSTANT");
             case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index e99a37a..c59d1c7 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -279,6 +279,7 @@
     public static final int PERMISSION_DENIED  = -4;
     public static final int NO_INIT            = -5;
     public static final int DEAD_OBJECT        = -6;
+    public static final int WOULD_BLOCK        = -7;
 
     /*
      * AudioPolicyService methods
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 8880dad..bb4f7d9 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -158,6 +158,18 @@
      * Denotes a failure due to the improper use of a method.
      */
     public  static final int ERROR_INVALID_OPERATION               = AudioSystem.INVALID_OPERATION;
+    /**
+     * An error code indicating that the object reporting it is no longer valid and needs to
+     * be recreated.
+     * @hide
+     */
+    public  static final int ERROR_DEAD_OBJECT                     = AudioSystem.DEAD_OBJECT;
+    /**
+     * {@link #getTimestampWithStatus(AudioTimestamp)} is called in STOPPED or FLUSHED state,
+     * or immediately after start/ACTIVE.
+     * @hide
+     */
+    public  static final int ERROR_WOULD_BLOCK                     = AudioSystem.WOULD_BLOCK;
 
     // Error codes:
     // to keep in sync with frameworks/base/core/jni/android_media_AudioTrack.cpp
@@ -1225,6 +1237,44 @@
         return true;
     }
 
+    /**
+     * Poll for a timestamp on demand.
+     * <p>
+     * Same as {@link #getTimestamp(AudioTimestamp)} but with a more useful return code.
+     *
+     * @param timestamp a reference to a non-null AudioTimestamp instance allocated
+     *        and owned by caller.
+     * @return {@link #SUCCESS} if a timestamp is available
+     *         {@link #ERROR_WOULD_BLOCK} if called in STOPPED or FLUSHED state, or if called
+     *         immediately after start/ACTIVE, when the number of frames consumed is less than the
+     *         overall hardware latency to physical output. In WOULD_BLOCK cases, one might poll
+     *         again, or use {@link #getPlaybackHeadPosition}, or use 0 position and current time
+     *         for the timestamp.
+     *         {@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+     *         needs to be recreated.
+     *         {@link #ERROR_INVALID_OPERATION} if current route does not support
+     *         timestamps. In this case, the approximate frame position can be obtained
+     *         using {@link #getPlaybackHeadPosition}.
+     *
+     *         The AudioTimestamp instance is filled in with a position in frame units, together
+     *         with the estimated time when that frame was presented or is committed to
+     *         be presented.
+     * @hide
+     */
+     // Add this text when the "on new timestamp" API is added:
+     //   Use if you need to get the most recent timestamp outside of the event callback handler.
+     public int getTimestampWithStatus(AudioTimestamp timestamp)
+     {
+         if (timestamp == null) {
+             throw new IllegalArgumentException();
+         }
+         // It's unfortunate, but we have to either create garbage every time or use synchronized
+         long[] longArray = new long[2];
+         int ret = native_get_timestamp(longArray);
+         timestamp.framePosition = longArray[0];
+         timestamp.nanoTime = longArray[1];
+         return ret;
+     }
 
     //--------------------------------------------------------------------------
     // Initialization / configuration
diff --git a/media/java/android/media/midi/package.html b/media/java/android/media/midi/package.html
index 7baa5bc..45fb579 100644
--- a/media/java/android/media/midi/package.html
+++ b/media/java/android/media/midi/package.html
@@ -202,11 +202,12 @@
 <p>MIDI messages are sent as byte arrays. Here we encode a NoteOn message.</p>
 
 <pre class=prettyprint>
-byte[] buffer = new buffer[64];
+byte[] buffer = new byte[32];
 int numBytes = 0;
-buffer[numBytes++] = 0x90 + channel; // note on
-buffer[numBytes++] = pitch;
-buffer[numBytes++] = velocity;
+int channel = 3; // MIDI channels 1-16 are encoded as 0-15.
+buffer[numBytes++] = (byte)(0x90 + (channel - 1)); // note on
+buffer[numBytes++] = (byte)60; // pitch is middle C
+buffer[numBytes++] = (byte)127; // max velocity
 int offset = 0;
 // post is non-blocking
 inputPort.send(buffer, offset, numBytes);
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/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index a0e3868..d578769 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -48,8 +48,8 @@
         </activity>
 
         <activity
-            android:name=".StandaloneActivity"
-            android:theme="@style/StandaloneTheme"
+            android:name=".FilesActivity"
+            android:theme="@style/FilesTheme"
             android:icon="@drawable/ic_files_app"
             android:label="@string/files_label"
             android:enabled="@bool/productivity_device">
diff --git a/packages/DocumentsUI/res/layout/activity.xml b/packages/DocumentsUI/res/layout/drawer_layout.xml
similarity index 100%
rename from packages/DocumentsUI/res/layout/activity.xml
rename to packages/DocumentsUI/res/layout/drawer_layout.xml
diff --git a/packages/DocumentsUI/res/layout-sw720dp/activity.xml b/packages/DocumentsUI/res/layout/fixed_layout.xml
similarity index 100%
rename from packages/DocumentsUI/res/layout-sw720dp/activity.xml
rename to packages/DocumentsUI/res/layout/fixed_layout.xml
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/res/values-sw720dp-land/layouts.xml b/packages/DocumentsUI/res/values-sw720dp-land/layouts.xml
new file mode 100644
index 0000000..0e1807c
--- /dev/null
+++ b/packages/DocumentsUI/res/values-sw720dp-land/layouts.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <item name="files_activity" type="layout">@layout/fixed_layout</item>
+</resources>
diff --git a/packages/DocumentsUI/res/values-sw720dp/layouts.xml b/packages/DocumentsUI/res/values-sw720dp/layouts.xml
new file mode 100644
index 0000000..7d28f9c
--- /dev/null
+++ b/packages/DocumentsUI/res/values-sw720dp/layouts.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <item name="docs_activity" type="layout">@layout/fixed_layout</item>
+</resources>
diff --git a/packages/DocumentsUI/res/values/layouts.xml b/packages/DocumentsUI/res/values/layouts.xml
new file mode 100644
index 0000000..c73a1cb
--- /dev/null
+++ b/packages/DocumentsUI/res/values/layouts.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <item name="docs_activity" type="layout">@layout/drawer_layout</item>
+    <item name="files_activity" type="layout">@layout/drawer_layout</item>
+</resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 95c1d9c..fa94ff1 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -63,7 +63,7 @@
         <item name="android:colorAccent">@color/material_blue_700</item>
     </style>
 
-    <style name="StandaloneTheme" parent="@android:style/Theme.Material.DayNight.DarkActionBar">
+    <style name="FilesTheme" parent="@android:style/Theme.Material.DayNight.DarkActionBar">
         <item name="android:actionBarWidgetTheme">@null</item>
 
         <item name="android:colorPrimaryDark">@color/status_bar_background</item>
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..2835106 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,8 @@
 import android.os.Parcelable;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
+import android.support.annotation.LayoutRes;
+import android.support.annotation.Nullable;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
@@ -46,6 +47,7 @@
 import android.view.MenuItem.OnActionExpandListener;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewStub;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.BaseAdapter;
@@ -60,8 +62,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;
@@ -76,9 +76,13 @@
 
     static final String EXTRA_STATE = "state";
 
+    State mState;
     RootsCache mRoots;
     SearchManager mSearchManager;
+    DrawerController mDrawer;
 
+    @LayoutRes
+    private int mLayoutId;
     private final String mTag;
 
     public abstract State getDisplayState();
@@ -89,16 +93,28 @@
     abstract void onDirectoryChanged(int anim);
     abstract void updateActionBar();
     abstract void saveStackBlocking();
+    abstract State buildDefaultState();
 
-    public BaseActivity(String tag) {
+    public BaseActivity(@LayoutRes int layoutId, String tag) {
+        mLayoutId = layoutId;
         mTag = tag;
     }
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
+
+        mState = (icicle != null)
+                ? icicle.<State>getParcelable(EXTRA_STATE)
+                        : buildDefaultState();
+
+        setContentView(mLayoutId);
+
         mRoots = DocumentsApplication.getRootsCache(this);
         mSearchManager = new SearchManager();
+
+        // Base classes must update result in their onCreate.
+        setResult(Activity.RESULT_CANCELED);
     }
 
     @Override
@@ -371,7 +387,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>();
@@ -527,6 +543,30 @@
         }
     }
 
+    @Override
+    public void onBackPressed() {
+        // While action bar is expanded, the state stack UI is hidden.
+        if (mSearchManager.cancelSearch()) {
+            return;
+        }
+
+        if (!mState.stackTouched) {
+            super.onBackPressed();
+            return;
+        }
+
+        final int size = mState.stack.size();
+
+        if (mDrawer.isOpen()) {
+            mDrawer.setOpen(false);
+        } else if (size > 1) {
+            mState.stack.pop();
+            onCurrentDirectoryChanged(ANIM_UP);
+        } else {
+            super.onBackPressed();
+        }
+    }
+
     public void onStackPicked(DocumentStack stack) {
         try {
             // Update the restored stack to ensure we have freshest data
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
index 14155d5..8b92331 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
@@ -167,7 +167,7 @@
 
             if (mFailedFiles.size() > 0) {
                 final Context context = getApplicationContext();
-                final Intent navigateIntent = new Intent(context, StandaloneActivity.class);
+                final Intent navigateIntent = new Intent(context, FilesActivity.class);
                 navigateIntent.putExtra(EXTRA_STACK, (Parcelable) stack);
                 navigateIntent.putExtra(EXTRA_FAILURE, FAILURE_COPY);
                 navigateIntent.putParcelableArrayListExtra(EXTRA_SRC_LIST, mFailedFiles);
@@ -213,7 +213,7 @@
         mIsCancelled = false;
 
         final Context context = getApplicationContext();
-        final Intent navigateIntent = new Intent(context, StandaloneActivity.class);
+        final Intent navigateIntent = new Intent(context, FilesActivity.class);
         navigateIntent.putExtra(EXTRA_STACK, (Parcelable) stack);
 
         final String contentTitle = getString(copying ? R.string.copy_notification_title
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..240cdda 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;
     }
 
@@ -740,7 +738,7 @@
         new GetDocumentsTask() {
             @Override
             void onDocumentsReady(List<DocumentInfo> docs) {
-                // TODO: Implement support in standalone for opening multiple docs.
+                // TODO: Implement support in Files activity for opening multiple docs.
                 BaseActivity.get(DirectoryFragment.this).onDocumentsPicked(docs);
             }
         }.execute(selected);
@@ -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);
     }
 
@@ -1685,7 +1684,7 @@
 
     private FragmentTuner pickFragmentTuner(final State state) {
         return state.action == ACTION_BROWSE_ALL
-                ? new StandaloneTuner()
+                ? new FilesTuner()
                 : new DefaultTuner(state);
     }
 
@@ -1750,7 +1749,7 @@
             copyTo.setVisible(manageOrBrowse && dirType != TYPE_RECENT_OPEN);
             moveTo.setVisible(SystemProperties.getBoolean("debug.documentsui.enable_move", false));
 
-            // Only shown in standalone mode.
+            // Only shown in files mode.
             copyToClipboard.setVisible(false);
         }
 
@@ -1759,9 +1758,9 @@
     }
 
     /**
-     * Provides support for Standalone specific specializations of DirectoryFragment.
+     * Provides support for Files activity specific specializations of DirectoryFragment.
      */
-    private static final class StandaloneTuner implements FragmentTuner {
+    private static final class FilesTuner implements FragmentTuner {
         @Override
         public void updateActionMenu(Menu menu, int dirType, boolean canDelete) {
             menu.findItem(R.id.menu_share).setVisible(true);
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..fdc4bb0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -25,8 +25,6 @@
 import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_TREE;
 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 +46,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,42 +76,32 @@
 
     private Toolbar mRootsToolbar;
 
-    private DrawerLayout mDrawerLayout;
-    private ActionBarDrawerToggle mDrawerToggle;
-    private View mRootsDrawer;
-
     private DirectoryContainerView mDirectoryContainer;
 
-    private State mState;
-
     private ItemSelectedListener mStackListener;
     private BaseAdapter mStackAdapter;
 
     public DocumentsActivity() {
-        super(TAG);
+        super(R.layout.docs_activity, TAG);
     }
 
     @Override
     public void onCreate(Bundle icicle) {
-        mState = (icicle != null)
-                ? icicle.<State>getParcelable(EXTRA_STATE)
-                : buildDefaultState();
+        super.onCreate(icicle);
 
         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);
         }
 
-        super.onCreate(icicle);
-
-        setResult(Activity.RESULT_CANCELED);
-        setContentView(R.layout.activity);
-
         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 +113,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 +137,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);
             }
         }
 
@@ -205,7 +179,8 @@
         }
     }
 
-    private State buildDefaultState() {
+    @Override
+    State buildDefaultState() {
         State state = new State();
 
         final Intent intent = getIntent();
@@ -341,53 +316,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 +345,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,34 +440,7 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        if (mDrawerToggle != null && mDrawerToggle.onOptionsItemSelected(item)) {
-            return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
-    @Override
-    public void onBackPressed() {
-        // While action bar is expanded, the state stack UI is hidden.
-        if (mSearchManager.cancelSearch()) {
-            return;
-        }
-
-        if (!mState.stackTouched) {
-            super.onBackPressed();
-            return;
-        }
-
-        final int size = mState.stack.size();
-        if (size > 1) {
-            mState.stack.pop();
-            onCurrentDirectoryChanged(ANIM_UP);
-        } else if (size == 1 && !isRootsDrawerOpen()) {
-            // TODO: open root drawer once we can capture back key
-            super.onBackPressed();
-        } else {
-            super.onBackPressed();
-        }
+        return mDrawer.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
     }
 
     @Override
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..df3ac1b
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -0,0 +1,207 @@
+/*
+ * 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 isPresent();
+    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
+        boolean isPresent() {
+            return true;
+        }
+
+        @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
+        void setOpen(boolean open) {}
+
+        @Override
+        void syncState() {}
+
+        @Override
+        void lockOpen() {}
+
+        @Override
+        void lockClosed() {}
+
+        @Override
+        boolean isOpen() {
+            return false;
+        }
+
+        @Override
+        boolean isUnlocked() {
+            return true;
+        }
+
+        @Override
+        boolean isPresent() {
+            return false;
+        }
+
+        @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) {}
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
similarity index 91%
rename from packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java
rename to packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 1ca277d..7c445bf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -18,9 +18,7 @@
 
 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 android.annotation.Nullable;
 import android.app.Activity;
 import android.app.FragmentManager;
 import android.content.ActivityNotFoundException;
@@ -33,6 +31,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;
@@ -57,7 +56,7 @@
 /**
  * Standalone file management activity.
  */
-public class StandaloneActivity extends BaseActivity {
+public class FilesActivity extends BaseActivity {
 
     public static final String TAG = "StandaloneFileManagement";
     static final boolean DEBUG = false;
@@ -66,30 +65,22 @@
     private Spinner mToolbarStack;
     private Toolbar mRootsToolbar;
     private DirectoryContainerView mDirectoryContainer;
-    private State mState;
     private ItemSelectedListener mStackListener;
     private BaseAdapter mStackAdapter;
     private DocumentClipper mClipper;
 
-    public StandaloneActivity() {
-        super(TAG);
+    public FilesActivity() {
+        super(R.layout.files_activity, TAG);
     }
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-        setResult(Activity.RESULT_CANCELED);
-        setContentView(R.layout.activity);
-
         final Context context = this;
 
         mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
 
-        mState = (icicle != null)
-                ? icicle.<State> getParcelable(EXTRA_STATE)
-                : buildDefaultState();
-
         mToolbar = (Toolbar) findViewById(R.id.toolbar);
         mToolbar.setTitleTextAppearance(context,
                 android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
@@ -108,6 +99,11 @@
         setActionBar(mToolbar);
 
         mClipper = new DocumentClipper(this);
+        mDrawer = DrawerController.create(this);
+        if (mDrawer.isPresent()) {
+            setTheme(R.style.DocumentsNonDialogTheme);
+        }
+
 
         RootsFragment.show(getFragmentManager(), null);
         if (!mState.restored) {
@@ -130,7 +126,8 @@
         }
     }
 
-    private State buildDefaultState() {
+    @Override
+    State buildDefaultState() {
         State state = new State();
 
         final Intent intent = getIntent();
@@ -164,10 +161,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 (mDrawer.isPresent()) {
+            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);
@@ -236,22 +246,6 @@
     }
 
     @Override
-    public void onBackPressed() {
-        if (!mState.stackTouched) {
-            super.onBackPressed();
-            return;
-        }
-
-        final int size = mState.stack.size();
-        if (size > 1) {
-            mState.stack.pop();
-            onCurrentDirectoryChanged(ANIM_UP);
-        } else {
-            super.onBackPressed();
-        }
-    }
-
-    @Override
     public State getDisplayState() {
         return mState;
     }
@@ -284,6 +278,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/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/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/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 1c4b05f..3ad8f21 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -21,4 +21,6 @@
 
     <!-- The translation for disappearing security views after having solved them. -->
     <dimen name="disappear_y_translation">-32dp</dimen>
-</resources>
\ No newline at end of file
+
+    <dimen name="circle_avatar_size">40dp</dimen>
+</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index b03f100..9b1f103 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -195,4 +195,34 @@
     <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_wifi_signal_full">Wifi signal full.</string>
 
+    <!-- Label for kernel threads in battery usage -->
+    <string name="process_kernel_label">Android OS</string>
+    <!-- Title of data usage item that represents all uninstalled applications. [CHAR LIMIT=48] -->
+    <string name="data_usage_uninstalled_apps">Removed apps</string>
+    <!-- Title of data usage item that represents all uninstalled applications or removed users. [CHAR LIMIT=48] -->
+    <string name="data_usage_uninstalled_apps_users">Removed apps and users</string>
+
+    <!-- Tethering controls, item title to go into the tethering settings -->
+    <!-- Tethering controls, item title to go into the tethering settings when only USB tethering is available [CHAR LIMIT=25]-->
+    <string name="tether_settings_title_usb">USB tethering</string>
+    <!-- Tethering controls, item title to go into the tethering settings when only Wifi tethering is available [CHAR LIMIT=25]-->
+    <string name="tether_settings_title_wifi">Portable hotspot</string>
+    <!-- Tethering controls, item title to go into the tethering settings when only Bluetooth tethering is available [CHAR LIMIT=25]-->
+    <string name="tether_settings_title_bluetooth">Bluetooth tethering</string>
+    <!-- Tethering controls, item title to go into the tethering settings when USB and Bluetooth tethering are available [CHAR LIMIT=25]-->
+    <string name="tether_settings_title_usb_bluetooth">Tethering</string>
+    <!-- Tethering controls, item title to go into the tethering settings when USB, Bluetooth and Wifi tethering are available [CHAR LIMIT=25]-->
+    <string name="tether_settings_title_all">Tethering &amp; portable hotspot</string>
+
+    <!-- Title for a work profile. [CHAR LIMIT=25] -->
+    <string name="managed_user_title">Work profile</string>
+
+    <!-- Title for Guest user [CHAR LIMIT=35] -->
+    <string name="user_guest">Guest</string>
+
+    <!-- Manage apps, individual app screen, substituted for the application's label when the app's label CAN NOT be determined.-->
+    <string name="unknown">Unknown</string>
+
+    <!-- [CHAR LIMIT=NONE] Label of a running process that represents another user -->
+    <string name="running_process_item_user_label">User: <xliff:g id="user_name">%1$s</xliff:g></string>
 </resources>
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/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
new file mode 100644
index 0000000..621a09cd
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -0,0 +1,84 @@
+package com.android.settingslib;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.os.UserManager;
+
+import com.android.internal.util.UserIcons;
+import com.android.settingslib.drawable.CircleFramedDrawable;
+
+public final class Utils {
+
+    /**
+     * Return string resource that best describes combination of tethering
+     * options available on this device.
+     */
+    public static int getTetheringLabel(ConnectivityManager cm) {
+        String[] usbRegexs = cm.getTetherableUsbRegexs();
+        String[] wifiRegexs = cm.getTetherableWifiRegexs();
+        String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
+
+        boolean usbAvailable = usbRegexs.length != 0;
+        boolean wifiAvailable = wifiRegexs.length != 0;
+        boolean bluetoothAvailable = bluetoothRegexs.length != 0;
+
+        if (wifiAvailable && usbAvailable && bluetoothAvailable) {
+            return R.string.tether_settings_title_all;
+        } else if (wifiAvailable && usbAvailable) {
+            return R.string.tether_settings_title_all;
+        } else if (wifiAvailable && bluetoothAvailable) {
+            return R.string.tether_settings_title_all;
+        } else if (wifiAvailable) {
+            return R.string.tether_settings_title_wifi;
+        } else if (usbAvailable && bluetoothAvailable) {
+            return R.string.tether_settings_title_usb_bluetooth;
+        } else if (usbAvailable) {
+            return R.string.tether_settings_title_usb;
+        } else {
+            return R.string.tether_settings_title_bluetooth;
+        }
+    }
+
+    /**
+     * Returns a label for the user, in the form of "User: user name" or "Work profile".
+     */
+    public static String getUserLabel(Context context, UserInfo info) {
+        String name = info != null ? info.name : null;
+        if (info.isManagedProfile()) {
+            // We use predefined values for managed profiles
+            return context.getString(R.string.managed_user_title);
+        } else if (info.isGuest()) {
+            name = context.getString(R.string.user_guest);
+        }
+        if (name == null && info != null) {
+            name = Integer.toString(info.id);
+        } else if (info == null) {
+            name = context.getString(R.string.unknown);
+        }
+        return context.getResources().getString(R.string.running_process_item_user_label, name);
+    }
+
+    /**
+     * Returns a circular icon for a user.
+     */
+    public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) {
+        if (user.isManagedProfile()) {
+            // We use predefined values for managed profiles
+            Bitmap b = BitmapFactory.decodeResource(context.getResources(),
+                    com.android.internal.R.drawable.ic_corp_icon);
+            return CircleFramedDrawable.getInstance(context, b);
+        }
+        if (user.iconPath != null) {
+            Bitmap icon = um.getUserIcon(user.id);
+            if (icon != null) {
+                return CircleFramedDrawable.getInstance(context, icon);
+            }
+        }
+        return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap(
+                UserIcons.getDefaultUserIcon(user.id, /* light= */ false)));
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java
new file mode 100644
index 0000000..278b57d
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java
@@ -0,0 +1,136 @@
+/*
+ * 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.settingslib.drawable;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+
+import com.android.settingslib.R;
+
+/**
+ * Converts the user avatar icon to a circularly clipped one.
+ * TODO: Move this to an internal framework class and share with the one in Keyguard.
+ */
+public class CircleFramedDrawable extends Drawable {
+
+    private final Bitmap mBitmap;
+    private final int mSize;
+    private final Paint mPaint;
+
+    private float mScale;
+    private Rect mSrcRect;
+    private RectF mDstRect;
+
+    public static CircleFramedDrawable getInstance(Context context, Bitmap icon) {
+        Resources res = context.getResources();
+        float iconSize = res.getDimension(R.dimen.circle_avatar_size);
+
+        CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
+        return instance;
+    }
+
+    public CircleFramedDrawable(Bitmap icon, int size) {
+        super();
+        mSize = size;
+
+        mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
+        final Canvas canvas = new Canvas(mBitmap);
+
+        final int width = icon.getWidth();
+        final int height = icon.getHeight();
+        final int square = Math.min(width, height);
+
+        final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, square, square);
+        final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
+
+        final Path fillPath = new Path();
+        fillPath.addArc(circleRect, 0f, 360f);
+
+        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+
+        // opaque circle matte
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setColor(Color.BLACK);
+        mPaint.setStyle(Paint.Style.FILL);
+        canvas.drawPath(fillPath, mPaint);
+
+        // mask in the icon where the bitmap is opaque
+        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+        canvas.drawBitmap(icon, cropRect, circleRect, mPaint);
+
+        // prepare paint for frame drawing
+        mPaint.setXfermode(null);
+
+        mScale = 1f;
+
+        mSrcRect = new Rect(0, 0, mSize, mSize);
+        mDstRect = new RectF(0, 0, mSize, mSize);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        final float inside = mScale * mSize;
+        final float pad = (mSize - inside) / 2f;
+
+        mDstRect.set(pad, pad, mSize - pad, mSize - pad);
+        canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
+    }
+
+    public void setScale(float scale) {
+        mScale = scale;
+    }
+
+    public float getScale() {
+        return mScale;
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter cf) {
+    }
+    
+    @Override
+    public int getIntrinsicWidth() {
+        return mSize;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mSize;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
new file mode 100644
index 0000000..572bae1
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 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.settingslib.net;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStats;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+public class SummaryForAllUidLoader extends AsyncTaskLoader<NetworkStats> {
+    private static final String KEY_TEMPLATE = "template";
+    private static final String KEY_START = "start";
+    private static final String KEY_END = "end";
+
+    private final INetworkStatsSession mSession;
+    private final Bundle mArgs;
+
+    public static Bundle buildArgs(NetworkTemplate template, long start, long end) {
+        final Bundle args = new Bundle();
+        args.putParcelable(KEY_TEMPLATE, template);
+        args.putLong(KEY_START, start);
+        args.putLong(KEY_END, end);
+        return args;
+    }
+
+    public SummaryForAllUidLoader(Context context, INetworkStatsSession session, Bundle args) {
+        super(context);
+        mSession = session;
+        mArgs = args;
+    }
+
+    @Override
+    protected void onStartLoading() {
+        super.onStartLoading();
+        forceLoad();
+    }
+
+    @Override
+    public NetworkStats loadInBackground() {
+        final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
+        final long start = mArgs.getLong(KEY_START);
+        final long end = mArgs.getLong(KEY_END);
+
+        try {
+            return mSession.getSummaryForAllUid(template, start, end, false);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    @Override
+    protected void onStopLoading() {
+        super.onStopLoading();
+        cancelLoad();
+    }
+
+    @Override
+    protected void onReset() {
+        super.onReset();
+        cancelLoad();
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java
new file mode 100644
index 0000000..5e42281
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 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.settingslib.net;
+
+import android.graphics.drawable.Drawable;
+
+public class UidDetail {
+    public CharSequence label;
+    public CharSequence contentDescription;
+    public CharSequence[] detailLabels;
+    public CharSequence[] detailContentDescriptions;
+    public Drawable icon;
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
new file mode 100644
index 0000000..224b967
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2011 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.settingslib.net;
+
+import android.app.AppGlobals;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.net.TrafficStats;
+import android.os.UserManager;
+import android.os.UserHandle;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.settingslib.R;
+import com.android.settingslib.Utils;
+
+/**
+ * Return details about a specific UID, handling special cases like
+ * {@link TrafficStats#UID_TETHERING} and {@link UserInfo}.
+ */
+public class UidDetailProvider {
+    private static final String TAG = "DataUsage";
+    private final Context mContext;
+    private final SparseArray<UidDetail> mUidDetailCache;
+
+    public static final int OTHER_USER_RANGE_START = -2000;
+
+    public static int buildKeyForUser(int userHandle) {
+        return OTHER_USER_RANGE_START - userHandle;
+    }
+
+    public static boolean isKeyForUser(int key) {
+        return key <= OTHER_USER_RANGE_START;
+    }
+
+    public static int getUserIdForKey(int key) {
+        return OTHER_USER_RANGE_START - key;
+    }
+
+    public UidDetailProvider(Context context) {
+        mContext = context.getApplicationContext();
+        mUidDetailCache = new SparseArray<UidDetail>();
+    }
+
+    public void clearCache() {
+        synchronized (mUidDetailCache) {
+            mUidDetailCache.clear();
+        }
+    }
+
+    /**
+     * Resolve best descriptive label for the given UID.
+     */
+    public UidDetail getUidDetail(int uid, boolean blocking) {
+        UidDetail detail;
+
+        synchronized (mUidDetailCache) {
+            detail = mUidDetailCache.get(uid);
+        }
+
+        if (detail != null) {
+            return detail;
+        } else if (!blocking) {
+            return null;
+        }
+
+        detail = buildUidDetail(uid);
+
+        synchronized (mUidDetailCache) {
+            mUidDetailCache.put(uid, detail);
+        }
+
+        return detail;
+    }
+
+    /**
+     * Build {@link UidDetail} object, blocking until all {@link Drawable}
+     * lookup is finished.
+     */
+    private UidDetail buildUidDetail(int uid) {
+        final Resources res = mContext.getResources();
+        final PackageManager pm = mContext.getPackageManager();
+
+        final UidDetail detail = new UidDetail();
+        detail.label = pm.getNameForUid(uid);
+        detail.icon = pm.getDefaultActivityIcon();
+
+        // handle special case labels
+        switch (uid) {
+            case android.os.Process.SYSTEM_UID:
+                detail.label = res.getString(R.string.process_kernel_label);
+                detail.icon = pm.getDefaultActivityIcon();
+                return detail;
+            case TrafficStats.UID_REMOVED:
+                detail.label = res.getString(UserManager.supportsMultipleUsers()
+                        ? R.string.data_usage_uninstalled_apps_users
+                        : R.string.data_usage_uninstalled_apps);
+                detail.icon = pm.getDefaultActivityIcon();
+                return detail;
+            case TrafficStats.UID_TETHERING:
+                final ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
+                        Context.CONNECTIVITY_SERVICE);
+                detail.label = res.getString(Utils.getTetheringLabel(cm));
+                detail.icon = pm.getDefaultActivityIcon();
+                return detail;
+        }
+
+        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+
+        // Handle keys that are actually user handles
+        if (isKeyForUser(uid)) {
+            final int userHandle = getUserIdForKey(uid);
+            final UserInfo info = um.getUserInfo(userHandle);
+            if (info != null) {
+                detail.label = Utils.getUserLabel(mContext, info);
+                detail.icon = Utils.getUserIcon(mContext, um, info);
+                return detail;
+            }
+        }
+
+        // otherwise fall back to using packagemanager labels
+        final String[] packageNames = pm.getPackagesForUid(uid);
+        final int length = packageNames != null ? packageNames.length : 0;
+        try {
+            final int userId = UserHandle.getUserId(uid);
+            UserHandle userHandle = new UserHandle(userId);
+            IPackageManager ipm = AppGlobals.getPackageManager();
+            if (length == 1) {
+                final ApplicationInfo info = ipm.getApplicationInfo(packageNames[0],
+                        0 /* no flags */, userId);
+                if (info != null) {
+                    detail.label = info.loadLabel(pm).toString();
+                    detail.icon = um.getBadgedIconForUser(info.loadIcon(pm),
+                            new UserHandle(userId));
+                }
+            } else if (length > 1) {
+                detail.detailLabels = new CharSequence[length];
+                detail.detailContentDescriptions = new CharSequence[length];
+                for (int i = 0; i < length; i++) {
+                    final String packageName = packageNames[i];
+                    final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
+                    final ApplicationInfo appInfo = ipm.getApplicationInfo(packageName,
+                            0 /* no flags */, userId);
+
+                    if (appInfo != null) {
+                        detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
+                        detail.detailContentDescriptions[i] = um.getBadgedLabelForUser(
+                                detail.detailLabels[i], userHandle);
+                        if (packageInfo.sharedUserLabel != 0) {
+                            detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
+                                    packageInfo.applicationInfo).toString();
+                            detail.icon = um.getBadgedIconForUser(appInfo.loadIcon(pm), userHandle);
+                        }
+                    }
+                }
+            }
+            detail.contentDescription = um.getBadgedLabelForUser(detail.label, userHandle);
+        } catch (NameNotFoundException e) {
+            Log.w(TAG, "Error while building UI detail for uid "+uid, e);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error while building UI detail for uid "+uid, e);
+        }
+
+        if (TextUtils.isEmpty(detail.label)) {
+            detail.label = Integer.toString(uid);
+        }
+
+        return detail;
+    }
+}
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 51fea2a..314b3c4 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -3,13 +3,15 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-proto-files-under,src) \
     src/com/android/systemui/EventLogTags.logtags
 
 LOCAL_STATIC_JAVA_LIBRARIES := Keyguard
 LOCAL_JAVA_LIBRARIES := telephony-common
 
 LOCAL_PACKAGE_NAME := SystemUI
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
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-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 26d5274..9294a16 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Verwyder uit Instellings"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Verwyder Stelsel-UI-ontvanger uit Instellings en staak die gebruik van al sy kenmerke?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Program is nie op jou toestel geïnstalleer nie"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Wys horlosiesekondes"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Wys horlosiesekondes op die statusbalk. Sal batterylewe dalk beïnvloed."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e61b6c3..13f768d 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"ከቅንብሮች አስወግድ"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"ከቅንብሮች ላይ የስርዓት በይነገጽ መቃኛ ተወግዶ ሁሉም ባህሪዎቹን መጠቀም ይቁም?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"መተግበሪያ በእርስዎ መሣሪያ ላይ አልተጫነም"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"የሰዓት ሰከንዶችን አሳይ"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"የሰዓት ሰከንዶችን በሁኔታ አሞሌ ውስጥ አሳይ። በባትሪ ዕድሜ ላይ ተጽዕኖ ሊኖርው ይችል ይሆናል።"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 2e358a1..6889a43 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -437,4 +437,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"إزالة من الإعدادات"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"هل تريد إزالة أداة ضبط واجهة مستخدم النظام من الإعدادات وإيقاف استخدام كل ميزاتها؟"</string>
     <string name="activity_not_found" msgid="348423244327799974">"التطبيق غير مثبّت على جهازك"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"عرض ثواني الساعة"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"عرض ثواني الساعة في شريط الحالة. قد يؤثر ذلك في عمر البطارية."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index b82b42e..51513bd 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Ayarlardan Silin"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"System UI Tuner Ayarlardan silinsin və onun bütün funksiyalarından istifadə dayandırılsın?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Tətbiq cihazınızda quraşdırılmayıb"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Saatın saniyəsini göstərin"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Saatın saniyəsini status panelində göstərin. Batareyaya təsir edə bilər."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 82ace52..014d802 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Премахване от „Настройки“"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Да се премахне ли от „Настройки“ тунерът на системния потребителски интерфейс и да се спре ли използването на всичките му функции?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Приложението не е инсталирано на устройството ви"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Показване на секундите на часовника"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Показване на секундите на часовника в лентата на състоянието. Може да се отрази на живота на батерията."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 884fc42..0860019 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"সেটিংস থেকে সরান"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"সেটিংস থেকে সিস্টেম UI টিউনার সরাতে এবং এটির সমস্ত বৈশিষ্ট্য ব্যবহার করা বন্ধ করতে চান?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"আপনার ডিভাইসে অ্যাপ্লিকেশান ইনস্টল করা নেই"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"ঘড়ির সেকেন্ড দেখায়"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"স্থিতি দন্ডে ঘড়ির সেকেন্ড দেখায়৷ ব্যাটারি লাইফকে প্রভাবিত করতে পারে৷"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index cc04fd6..7dd11eb 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Treu de Configuració"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vols treure el Configurador de la UI del sistema de Configuració i deixar d\'utilitzar-ne totes les funcions?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"L\'aplicació no està instal·lada al dispositiu"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Mostra els segons del rellotge"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra els segons del rellotge a la barra d\'estat. Això pot afectar la durada de la bateria."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 7f94577..4d96a01 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -437,4 +437,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Odstranit z Nastavení"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Chcete nástroj na ladění uživatelského rozhraní systému odstranit z Nastavení a přestat používat všechny jeho funkce?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplikace není v zařízení nainstalována."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Zobrazit sekundovou ručičku"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Na stavovém řádku se bude zobrazovat sekundová ručička. Může být ovlivněna výdrž baterie."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 2129f03..7f005a3 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Fjern fra Indstillinger"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vil du fjerne System UI Tuner fra Indstillinger og stoppe med at bruge alle dens funktioner?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Applikationen er ikke installeret på din enhed."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Vis sekunder"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statuslinjen. Dette kan påvirke batteriets levetid."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 30a2baf..36f3c98 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Aus \"Einstellungen\" entfernen"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"System UI Tuner aus \"Einstellungen\" entfernen und die Verwendung von allen zugehörigen Funktionen beenden?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Die App ist nicht auf Ihrem Gerät installiert."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Uhrsekunden anzeigen"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Uhrsekunden in der Statusleiste anzeigen. Kann sich auf die Akkulaufzeit auswirken."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f2fc602..8e73b21 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Κατάργηση από τις Ρυθμίσεις"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Κατάργηση System UI Tuner από τις Ρυθμίσεις και διακοπή χρήσης όλων των λειτουργιών του;"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Η εφαρμογή δεν έχει εγκατασταθεί στη συσκευή σας"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Εμφάνιση δευτερολέπτων ρολογιού"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Εμφάνιση δευτερολέπτων ρολογιού στη γραμμή κατάστασης. Ενδέχεται να επηρεάσει τη διάρκεια ζωής της μπαταρίας."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index f1aafb6..0b49955 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Remove from settings"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Remove System UI Tuner from Settings and stop using all of its features?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Application is not installed on your device"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Show clock seconds"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index f1aafb6..0b49955 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Remove from settings"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Remove System UI Tuner from Settings and stop using all of its features?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Application is not installed on your device"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Show clock seconds"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index f1aafb6..0b49955 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Remove from settings"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Remove System UI Tuner from Settings and stop using all of its features?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Application is not installed on your device"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Show clock seconds"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 5136545..c4dca9c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Quitar de Configuración"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"¿Quieres quitar el sintonizador de IU del sistema de Configuración y dejar de utilizar todas sus funciones?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"La aplicación no está instalada en el dispositivo"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Mostrar los segundos del reloj"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar la duración de la batería."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 82fd6fc..e316a94 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Eliminar de Ajustes"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"¿Eliminar el configurador de IU del sistema de Ajustes y dejar de utilizar sus funciones?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"La aplicación no está instalada en tu dispositivo"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Mostrar los segundos del reloj"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar a la duración de la batería."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index dd3d823..a151bce 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Eemalda seadetest"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Kas eemaldada seadetest süsteemi kasutajaliidese tuuner ja lõpetada kõikide selle funktsioonide kasutamine?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Rakendust pole teie seadmesse installitud"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Kella sekundite kuvamine"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Olekuribal kella sekundite kuvamine. See võib mõjutada aku kasutusaega."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index a856c09..37cdee7 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Kendu Ezarpenak ataletik"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Sistemako erabiltzaile-interfazearen konfiguratzailea ezarpenetatik kendu nahi duzu, eta haren eginbide guztiak erabiltzeari utzi nahi diozu?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplikazioa ez dago gailuan instalatuta"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Erakutsi erlojuko segundoak"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Erakutsi erlojuko segundoak egoera-barran. Baliteke bateria gehiago erabiltzea."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 412f808..80d0918 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"حذف از تنظیمات"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"«تنظیم‌کننده واسط کاربری سیستم» از تنظیمات حذف شود و همه ویژگی‌های آن متوقف شوند؟"</string>
     <string name="activity_not_found" msgid="348423244327799974">"برنامه در دستگاه شما نصب نیست"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"نمایش ثانیه‌های ساعت"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"ثانیه‌های ساعت را در نوار وضعیت نشان می‌دهد. ممکن است بر ماندگاری باتری تأثیر بگذارد."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 836b136..b86247a 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Poista Asetuksista"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Haluatko poistaa System UI Tunerin Asetuksista ja lopettaa sen ominaisuuksien käytön?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Sovellusta ei ole asennettu laitteellesi."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Näytä sekunnit kellossa"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Näytä sekunnit tilapalkin kellossa. Tämä voi vaikuttaa akun kestoon."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 8c6773f..4e57f2b5 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Supprimer des paramètres"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Supprimer « System UI Tuner » des paramètres et arrêter d\'utiliser toutes ses fonctionnalités?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"L\'application n\'est pas installée sur votre appareil"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Afficher les secondes de l\'horloge"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes de l\'horloge dans la barre d\'état. Cela peut influer sur l\'autonomie de la pile."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 666c0ef..aada1eb 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Supprimer l\'outil des paramètres"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Supprimer System UI Tuner des paramètres et arrêter d\'utiliser toutes ses fonctionnalités ?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"L\'application n\'est pas installée sur votre appareil."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Afficher les secondes sur l\'horloge"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes dans la barre d\'état. Cela risque de réduire l\'autonomie de la batterie."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index d192257..951809f 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Eliminar da Configuración"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Queres eliminar o configurador da IU do sistema da Configuración e deixar de usar todas as súas funcións?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"A aplicación non está instalada no teu dispositivo"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do reloxo"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra os segundos do reloxo na barra de estado. Pode influír na duración da batería."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 81dab35..02e4e52 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"સેટિંગ્સમાંથી દૂર કરો"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"સેટિંગ્સમાંથી સિસ્ટમ UI ટ્યૂનર દૂર કરી અને તેની તમામ સુવિધાઓનો ઉપયોગ કરવાનું બંધ કરીએ?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"તમારા ઉપકરણ પર એપ્લિકેશન ઇન્સ્ટોલ થયેલ નથી"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"ઘડિયાળ સેકન્ડ બતાવો"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"ઘડિયાળ સેકન્ડ સ્થિતિ બારમાં બતાવો. બૅટરીની આવરદા પર અસર કરી શકે છે."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index a4bf691..3ed090c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"सेटिंग से निकालें"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"सेटिंग से सिस्टम UI ट्यूनर निकालें और इसकी सभी सुविधाओं का उपयोग रोक दें?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"ऐप्लिकेशन आपके डिवाइस पर इंस्टॉल नहीं है"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"घड़ी के सेकंड दिखाएं"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"स्थिति बार में घड़ी के सेकंड दिखाएं. इससे बैटरी के जीवनकाल पर प्रभाव पड़ सकता है."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index d18c04b..9698aba 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -434,4 +434,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Ukloni iz Postavki"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Želite li ukloniti Ugađanje korisničkog sučelja sustava iz Postavki i prestati upotrebljavati njegove značajke?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplikacija nije instalirana na vašem uređaju"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Prikaži sekunde na satu"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikazuju se sekunde na satu na traci statusa. Može utjecati na trajanje baterije."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 49543cb..37cb0a8 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Eltávolítás a Beállítások közül"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Eltávolítja a Kezelőfelület-hangolót a Beállításokból, és nem használja tovább egyik funkcióját sem?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Az alkalmazás nincs telepítve eszközén."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Másodpercek megjelenítése az órán"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Másodpercek megjelenítése az állapotsor óráján. Ez hatással lehet az akkumulátor üzemidejére."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 8cf062f..e31cf49 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Հեռացնել կարգավորումներից"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Հեռացնե՞լ Համակարգի ՕՄ-ի կարգավորիչը կարգավորումներից և չօգտվել այլևս նրա գործառույթներից:"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Հավելվածը տեղադրված չէ սարքի վրա"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Ցույց տալ ժամացույցի վայրկյանները"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Ցույց տալ ժամացույցի վայրկյանները կարգավիճակի տողում: Կարող է ազդել մարտկոցի աշխատանքի ժամանակի վրա:"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 6e738de..ad8141b 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Hapus dari Setelan"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Hapus Penyetel Antarmuka Pengguna Sistem dari Setelan dan berhenti menggunakan semua fiturnya?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplikasi tidak dipasang di perangkat"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Tampilkan detik jam"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Tampilkan detik jam di bilah status. Dapat memengaruhi masa pakai baterai."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 4c5bffb..02caf17 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Fjarlægja úr stillingum"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Viltu fjarlægja fínstillingar kerfisviðmóts úr stillingum og hætta að nota eiginleika þeirra?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Forritið er ekki uppsett í tækinu."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Sýna sekúndur á klukku"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Sýna sekúndur á klukku í stöðustikunni. Getur haft áhrif á endingu rafhlöðu."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 75ea3f6..ab5d8beab 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Rimuovi dalle impostazioni"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vuoi rimuovere il sintetizzatore interfaccia utente di sistema dalle impostazioni e smettere di utilizzare tutte le sue funzioni?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Applicazione non installata sul dispositivo"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Mostra i secondi nell\'orologio"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra i secondi nell\'orologio nella barra di stato. Ciò potrebbe ridurre la durata della carica della batteria."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 4db88bd..9dad8aa 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"הסר מההגדרות"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"‏האם להסיר את System UI Tuner ולהפסיק להשתמש בכל התכונות שלו?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"האפליקציה אינה מותקנת במכשיר"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"הצג שניות בשעון"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"הצג שניות בשעון בשורת הסטטוס. פעולה זו עשויה להשפיע על אורך חיי הסוללה."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index d7b687b..b9bfba9 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"設定から削除"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"設定からシステムUI調整ツールを削除して、全機能の使用を停止しますか?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"アプリが端末にインストールされていません"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"時計の秒を表示"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"ステータスバーに時計の秒を表示します。電池使用量に影響する可能性があります。"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 2097996..a9728b2 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"პარამეტრებიდან წაშლა"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"გსურთ სისტემის UI ტუნერის პარამეტრებიდან წაშლა და მისი ყველა ფუნქციის გამოყენების შეწყვეტა?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"აპლიკაცია თქვენს მოწყობილობაზე დაყენებული არ არის"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"საათის წამების ჩვენება"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"საათის წამების ჩვენება სტატუსის ზოლში. შეიძლება გავლენა იქონიოს ბატარეაზე."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index bd49612..1d61372 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Параметрлерден жою"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Жүйелік пайдаланушылық интерфейс тюнерін \"Параметрлер\" тармағынан жойып, оның барлық мүмкіндіктерін пайдалануды тоқтату керек пе?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Қолданба құрылғыда орнатылмаған"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Сағат секундтарын көрсету"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Күйін көрсету жолағында сағат секундтарын көрсету. Батареяның қызмет көрсету мерзіміне әсер етуі мүмкін."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index db5057e..c233f83 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"យកចេញពីការកំណត់"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"យកកម្មវិធីសម្រួល UI ប្រព័ន្ធចេញពីការកំណត់ ហើយឈប់ប្រើលក្ខណៈពិសេសរបស់វាទាំងអស់?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"កម្មវិធីមិនបានដំឡើងនៅលើឧបករណ៍របស់អ្នកទេ"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"បង្ហាញវិនាទី"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"បង្ហាញវិនាទីនៅលើរបារស្ថានភាពអាចនឹងប៉ះពាល់ដល់ថាមពលថ្ម។"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 7d88681e..d486e56 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಂದ ತೆಗೆದುಹಾಕಿ"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಂದ ಸಿಸ್ಟಮ್ UI ಟ್ಯೂನರ್ ತೆಗೆದುಹಾಕುವುದೇ ಮತ್ತು ಅದರ ಎಲ್ಲಾ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಬಳಸುವುದನ್ನು ನಿಲ್ಲಿಸುವುದೇ?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"ಗಡಿಯಾರದ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಗಡಿಯಾರ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು. ಇದಕ್ಕೆ ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯು ಪರಿಣಾಮಬೀರಬಹುದು."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index af02943..3505754 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"설정에서 삭제"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"시스템 UI 튜너를 설정에서 삭제하고 모든 관련 기능의 사용을 중지하시겠습니까?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"기기에 애플리케이션이 설치되어 있지 않습니다."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"시계 초 단위 표시"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"상태 표시줄에 시계 초 단위를 표시합니다. 배터리 수명에 영향을 줄 수도 있습니다."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 058cc18..968a65a 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Жөндөөлөрдөн алып салуу"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"System UI Tuner Жөндөөлөрдөн алынып салынып, анын бардык функциялары токтотулсунбу?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Колдонмо сиздин түзмөгүңүздө орнотулган эмес"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Сааттын секунддары көрсөтүлсүн"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Абал тилкесинен сааттын секунддары көрсөтүлсүн. Батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 3067fb7..f34c70e 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"ເອົາອອກ​ຈາກ​ການ​ຕັ້ງ​ຄ່າ"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"ເອົາ System UI Tuner ອອກຈາກການຕັ້ງຄ່າ ແລະຢຸດການໃຊ້ທຸກຄຸນສົມບັດໃຊ້ງານຂອງມັນ?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ບໍ່​ຖືກ​ຕິດ​ຕັ້ງ​ຢູ່​ໃນ​ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"ສະ​ແດງວິ​ນາ​ທີ​ໂມງ"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"ສະ​ແດງວິ​ນາ​ທີ​ໂມງ​ຢູ່​ໃນ​ແຖບ​ສະ​ຖາ​ນະ. ອາດ​ຈະ​ມີ​ຜົນ​ກະ​ທົບ​ຕໍ່​ອາ​ຍຸ​ແບັດ​ເຕີ​ຣີ."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index e195444..cf70d6b 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Pašalinti iš nustatymų"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Ar norite pašalinti sistemos naudotojo sąsajos derinimo priemonę iš nustatymų ir nebenaudoti jokių jos funkcijų?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Programa neįdiegta įrenginyje"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Rodyti laikrodžio sekundes"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Rodyti laikrodžio sekundes būsenos juostoje. Tai gali paveikti akumuliatoriaus naudojimo laiką."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 4350876..5e2db80 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -434,4 +434,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Noņemt no iestatījumiem"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vai noņemt sistēmas saskarnes regulatoru no iestatījumiem un pārtraukt izmantot visas tā funkcijas?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Lietojumprogramma nav instalēta jūsu ierīcē."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Rādīt pulksteņa sekundes"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Statusa joslā rādīt pulksteņa sekundes. Var ietekmēt akumulatora darbības laiku."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 9e7a717..fe781b6 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Отстрани од поставки"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Да се отстрани Адаптерот на УИ на системот од Поставки и да престанат да се користат сите негови функции?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Апликацијата не е инсталирана на уредот"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Прикажи ги секундите на часовникот"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Прикажи ги секундите на часовникот на статусната лента. Може да влијае на траењето на батеријата."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index e941427..6e6fc55 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"ക്രമീകരണത്തിൽ നിന്ന് നീക്കംചെയ്യുക"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"ക്രമീകരണത്തിൽ നിന്ന് സിസ്റ്റം UI ട്യൂണർ നീക്കംചെയ്യുകയും അതിന്റെ ഫീച്ചറുകളെല്ലാം ഉപയോഗിക്കുന്നത് നിർത്തുകയും ചെയ്യണോ?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"നിങ്ങളുടെ ഉപകരണത്തിൽ അപ്ലിക്കേഷൻ ഇൻസ്റ്റാൾ ചെയ്തിട്ടില്ല"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുക"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"സ്റ്റാറ്റസ് ബാറിൽ ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുന്നത് ബാറ്ററിയുടെ ലൈഫിനെ ബാധിക്കാം."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 69a94c2..65250bb 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -431,4 +431,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Тохиргооноос устгах"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Системийн UI Тохируулагчийг тохиргооноос устгаж, үүнтэй холбоотой бүх тохиргоог ашиглахаа болих уу?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Апп-ыг таны төхөөрөмжид суулгаагүй байна"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Цагийн секундыг харуулах"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Статус талбарт цагийн секундыг харуулах. Энэ нь тэжээлийн цэнэгт нөлөөлж болно."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 3184de5..0f71b4b 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"सेटिंग्ज मधून काढा"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"सेटिंग्ज मधून सिस्टीम UI ट्यूनर काढून त्याची सर्व वैशिष्ट्‍ये वापरणे थांबवायचे?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"अनुप्रयोग आपल्या डिव्हाइसवर स्थापित केलेला नाही"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"घड्‍याळ सेकंद दर्शवा"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"स्टेटस बारमध्‍ये घड्‍याळ सेकंद दर्शवा. कदाचित बॅटरी आयुष्‍य प्रभावित होऊ शकते."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index b12046b..596275c 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Alih keluar daripada Tetapan"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Alih keluar Penala UI Sistem daripada Tetapan dan berhenti menggunakan semua cirinya?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplikasi tidak dipasang pada peranti anda"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Tunjukkan saat jam"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Tunjukkan saat jam dalam bar status. Mungkin menjejaskan hayat bateri."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 6f843b0..3147d0c 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"ဆက်တင် အထဲမှ ဖယ်ရှားရန်"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"ဆက်တင် အထဲမှ စနစ် UI ဖမ်းစက်ကို ဖယ်ရှားလျက် ၎င်း၏ အင်္ဂါရပ်များ အားလုံး အသုံးပြုမှု ရပ်တန့်ရမလား?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"အပလီကေးရှင်းကို သင်၏ ကိရိယာထဲသို့ တပ်ဆင်မပေးရသေးပါ။"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"နာရီ စက္ကန့်များကို ပြရန်"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"အခြေအနေပြနေရာမှာ နာရီ စက္ကန့်များကို ပြပါ။ ဘက်ထရီ သက်တမ်းကို အကျိုးသက်ရောက်နိုင်တယ်။"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 3a34cdd..f1bfbe1 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Fjern fra Innstillinger"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vil du fjerne System UI Tuner fra Innstillinger og slutte å bruke alle de tilknyttede funksjonene?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Appen er ikke installert på enheten din"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Vis sekunder på klokken"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statusfeltet på klokken. Det kan påvirke batteritiden."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 5fadbde..461a15f 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"सेटिङहरूबाट हटाउनुहोस्"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"प्रणाली UI ट्युनर सेटिङहरूबाट हटाउने र यसका सबै सुविधाहरू प्रयोग गर्न रोक्ने हो?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"तपाईँको यन्त्रमा अनुप्रयोग स्थापना भएको छैन"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"घडीमा सेकेन्ड देखाउनुहोस्"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"वस्तुस्थिति पट्टीको घडीमा सेकेन्ड देखाउनुहोस्। ब्याट्री आयु प्रभावित हुन सक्छ।"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 9b7e3409..b74f91d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Verwijderen uit Instellingen"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Systeem-UI-tuner uit Instellingen verwijderen en het gebruik van alle functies daarvan stopzetten?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Deze app is niet geïnstalleerd op uw apparaat"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Klokseconden weergeven"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Klokseconden op de statusbalk weergeven. Kan van invloed zijn op de accuduur."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 2d70c8a..06746cc 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"ਸੈਟਿੰਗਜ਼ ਤੋਂ ਹਟਾਓ"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"ਕੀ ਸੈਟਿੰਗਜ਼ ਤੋਂ ਸਿਸਟਮ UI ਟਿਊਨਰ ਨੂੰ ਹਟਾਉਣਾ ਹੈ ਅਤੇ ਇਸਦੀਆਂ ਸਾਰੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਉਪਯੋਗ ਕਰਨ ਤੋਂ ਰੋਕਣਾ ਹੈ?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"ਐਪਲੀਕੇਸ਼ਨ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਤੇ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਬਾਰ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 93fa170..66100c1 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Usuń z Ustawień"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Usunąć Kalibrator System UI z Ustawień i przestać używać wszystkich jego funkcji?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplikacja nie jest zainstalowana na urządzeniu"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Pokaż sekundy na zegarku"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Pokaż sekundy na zegarku na pasku stanu. Może mieć wpływ na czas pracy baterii."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 78eee7b..53cea01 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Remover das configurações"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Remover sintonizador System UI das configurações e parar de usar todos os seus recursos?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"O app não está instalado no seu dispositivo"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do relógio"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 9c221dd..5006413 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Remover das Definições"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Pretende remover o Sintonizador da interface do sistema das Definições e deixar de utilizar todas as respetivas funcionalidades?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"A aplicação não está instalada no dispositivo"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do relógio"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de estado. Pode afetar a autonomia da bateria."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 78eee7b..53cea01 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Remover das configurações"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Remover sintonizador System UI das configurações e parar de usar todos os seus recursos?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"O app não está instalado no seu dispositivo"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Mostrar segundos do relógio"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index e9ff595..d97e16b 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -434,4 +434,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Eliminați din Setări"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Eliminați System UI Tuner din Setări și încetați utilizarea tuturor funcțiilor sale?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplicația nu este instalată pe dispozitiv"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Afișează secundele pe ceas"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Afișează secundele pe ceas în bara de stare. Poate afecta autonomia bateriei."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 8691233..d67ad38 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -437,4 +437,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Удалить из настроек"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Убрать функцию System UI Tuner из меню настроек и прекратить ее работу?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Приложение не установлено на вашем устройстве"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Показывать секунды"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Показывать в строке состояния время с точностью до секунды (заряд батареи может расходоваться быстрее)."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 02533f5..06cb626 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"සැකසීම් වෙතින් ඉවත් කරන්න"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"සැකසීම් වෙතින් පද්ධති UI සුසරකය ඉවත් කර සහ එහි සියලු අංග භාවිතය නවත් වන්නද?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"යෙදුම ඔබේ උපාංගය මත ස්ථාපනය කර නැත"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"ඔරලෝසු තත්පර පෙන්වන්න"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"තත්ත්ව තීරුවෙහි ඔරලෝසු තත්පර පෙන්වන්න. බැටරි ආයු කාලයට බලපෑමට හැකිය."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 522d0a6..037074b 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -437,4 +437,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Odstrániť z Nastavení"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Chcete odstrániť tuner používateľského rozhrania systému z Nastavení a prestať používať všetky jeho funkcie?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplikácia nie je nainštalovaná na zariadení"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Zobraziť sekundy"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Zobrazí sekundy v stavovom riadku. Môže to ovplyvňovať výdrž batérie."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 770844e..31fe5d8 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Odstrani iz nastavitev"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Ali želite odstraniti Uglaševalnik uporabniškega vmesnika sistema iz nastavitev in prenehati uporabljati vse njegove funkcije?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplikacija ni nameščena v napravi"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Prikaz sekund pri uri"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikaže sekunde pri uri v vrstici stanja. To lahko vpliva na čas delovanja pri akumulatorskem napajanju."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 1072b54..ffb8bea 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Hiqe nga Cilësimet"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Të hiqet Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit nga Cilësimet dhe të ndërpritet përdorimi i të gjitha funksioneve të tij?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplikacioni nuk është instaluar në pajisjen tënde."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Trego sekondat e orës"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Trego sekondat e orës në shiritin e statusit. Mund të ndikojë te jeta e baterisë."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 5df6d62..bae0284 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -434,4 +434,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Уклони из Подешавања"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Желите ли да уклоните Тјунер за кориснички интерфејс система из Подешавања и да престанете да користите све његове функције?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Апликација није инсталирана на уређају"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Приказуј секунде на сату"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Секунде на сату се приказују на статусној траци. То може да утиче на трајање батерије."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 807c53e..6588f10 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Ta bort från inställningarna"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Vill du ta bort inställningar för systemgränssnitt från inställningarna och sluta använda alla tillhörande funktioner?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Appen är inte installerad på enheten"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Visa klocksekunder"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Visa klocksekunder i statusfältet. Detta kan påverka batteritiden."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 1bb6c0b..623f12c 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Ondoa kwenye Mipangilio"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Je, ungependa kuondoa Kipokea ishara cha SystemUI kwenye Mipangilio na uache kutumia vipengele vyake vyote?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Programu haijasakinishwa kwenye kifaa chako"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Onyesha sekunde za saa"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Onyesha sekunde za saa katika sehemu ya arifa. Inaweza kuathiri muda wa matumizi ya betri."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 8e64e85..c6cb337 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"அமைப்புகளிலிருந்து அகற்று"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"அமைப்புகளிலிருந்து System UI Tunerஐ அகற்றிவிட்டு, அதன் எல்லா அம்சங்களையும் பயன்படுத்துவதை நிறுத்தவா?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"சாதனத்தில் பயன்பாடு நிறுவப்படவில்லை"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"கடிகார வினாடிகளைக் காட்டு"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"நிலைப் பட்டியில் கடிகார வினாடிகளைக் காட்டும். பேட்டரியின் ஆயுளைக் குறைக்கலாம்."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 36b00f8..c0717c1 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"సెట్టింగ్‌ల నుండి తీసివేయి"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"సిస్టమ్ UI ట్యూనర్‌ను సెట్టింగ్‌ల నుండి తీసివేసి, దాని అన్ని లక్షణాలను ఉపయోగించడం ఆపివేయాలా?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"అనువర్తనం మీ పరికరంలో ఇన్‌స్టాల్ చేయలేదు"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"గడియారం సెకన్లు చూపు"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"స్థితి పట్టీలో గడియారం సెకన్లు చూపుతుంది. బ్యాటరీ శక్తి ప్రభావితం చేయవచ్చు."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 0ef2c66..e16fdd2 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"นำออกจากการตั้งค่า"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"นำตัวรับสัญญาณ UI ระบบออกจากการตั้งค่าและหยุดใช้คุณลักษณะทั้งหมดของตัวรับสัญญาณใช่ไหม"</string>
     <string name="activity_not_found" msgid="348423244327799974">"ยังไม่ได้ติดตั้งแอปพลิเคชันบนอุปกรณ์ของคุณ"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"แสดงวินาทีของนาฬิกา"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"แสดงวินาทีของนาฬิกาในแถบสถานะ อาจส่งผลต่ออายุแบตเตอรี"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index a208c96..d970084 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Alisin sa Mga Setting"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Alisin ang Tuner ng System UI sa Mga Setting at ihinto ang paggamit ng lahat ng feature nito?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Hindi naka-install ang application sa iyong device"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Ipakita ang mga segundo ng orasan"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Ipakita ang mga segundo ng orasan sa status bar. Maaaring makaapekto sa tagal ng baterya."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index d359cf1..b22b4fb 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Ayarlar\'dan kaldır"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Sistem Kullanıcı Arayüzü Ayarlayıcısı Ayarlar\'dan kaldırılsın ve tüm özelliklerinin kullanılması durdurulsun mu?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Uygulama, cihazınızda yüklü değil"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Saatin saniyelerini göster"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Durum çubuğunda saatin saniyelerini gösterir. Pil ömrünü etkileyebilir."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 3e34a1f..5c0966c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Видалити з додатка Налаштування"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Видалити інструмент System UI Tuner із додатка Налаштування та припинити користуватися всіма його функціями?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Додаток не встановлено на вашому пристрої"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Показувати секунди на годиннику"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Показувати секунди на годиннику в рядку стану. Акумулятор може розряджатися швидше."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 650095d..d5683e1 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"ترتیبات سے ہٹائیں"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"‏ترتیبات سے سسٹم UI ٹیونر کو ہٹائیں اور اس کی سبھی خصوصیات کا استعمال بند کریں؟"</string>
     <string name="activity_not_found" msgid="348423244327799974">"ایپلیکیشن آپ کے آلہ پر انسٹال نہیں ہے"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"گھڑی کے سیکنڈز دکھائیں"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"گھڑی کے سیکنڈز اسٹیٹس بار میں دکھائیں۔ اس کا بیٹری کی زندگی پر اثر پڑ سکتا ہے۔"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index e3073bc..e31af6b 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Sozlamalardan olib tashlash"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"System UI Tuner Sozlamalardan olib tashlanib, uning barcha funksiyalaridan foydalanish to‘xtatilsinmi?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Ilova qurilmangizga o‘rnatilmagan"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Soat soniyalari ko‘rsatilsin"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Holat panelida soat soniyalari ko‘rsatilsin. Bu batareya resursiga ta’sir qilishi mumkin."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 4459497..030bbbe 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Xóa khỏi Cài đặt"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Xóa Bộ điều hướng giao diện người dùng hệ thống khỏi Cài đặt và ngừng sử dụng tất cả tính năng của ứng dụng này?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Ứng dụng chưa được cài đặt trên thiết bị của bạn"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Hiển thị giây đồng hồ"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Hiển thị giây đồng hồ trong thanh trạng thái. Có thể ảnh hưởng đến thời lượng pin."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 0272328..b046415 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"从“设置”中移除"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"要将系统界面调谐器从“设置”中移除,并停止使用所有相关功能吗?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"您的设备中未安装此应用"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"显示时钟的秒数"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"在状态栏中显示时钟的秒数。这可能会影响电池的续航时间。"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 8adaeac..d568dba 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"從「設定」移除"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"要從「設定」移除系統使用者介面調諧器,並停止其所有功能嗎?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"尚未在裝置安裝應用程式"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"顯示時鐘秒數"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數,但可能會影響電池壽命。"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 759b585..702ad53 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -435,4 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"從設定中移除"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"要將系統使用者介面調整精靈從設定中移除,並停止使用所有相關功能嗎?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"您的裝置未安裝這個應用程式"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"顯示時鐘秒數"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數。這可能會影響電池續航力。"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 1e7be90..8774036 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -433,4 +433,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Susa kusuka kuzilungiselelo"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Susa isishuni se-UI yesistimu kusuka kuzilungiselelo futhi uyeke ukusebenzisa zonke izici zakhona?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Uhlelo lokusebenza alufakiwe kudivayisi yakho"</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Bonisa amasekhondi wewashi"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Bonisa amasekhondi wewashi kubha yesimo. Ingathinta impilo yebhethri."</string>
 </resources>
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/analytics/LockedPhoneAnalytics.java b/packages/SystemUI/src/com/android/systemui/analytics/LockedPhoneAnalytics.java
new file mode 100644
index 0000000..e458862
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/analytics/LockedPhoneAnalytics.java
@@ -0,0 +1,453 @@
+/*
+ * 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.systemui.analytics;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.systemui.statusbar.StatusBarState;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session;
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.PhoneEvent;
+
+/**
+ * Tracks touch, sensor and phone events when the lockscreen is on. If the phone is unlocked
+ * the data containing these events is saved to a file. This data is collected
+ * to analyze how a human interaction looks like.
+ *
+ * A session starts when the screen is turned on.
+ * A session ends when the screen is turned off or user unlocks the phone.
+ */
+public class LockedPhoneAnalytics implements SensorEventListener {
+    private static final String TAG = "LockedPhoneAnalytics";
+    private static final String ANALYTICS_ENABLE = "locked_phone_analytics_enable";
+    private static final String ENFORCE_BOUNCER = "locked_phone_analytics_enforce_bouncer";
+    private static final String COLLECT_BAD_TOCUHES = "locked_phone_analytics_collect_bad_touches";
+
+    private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
+    public static final boolean DEBUG = false;
+
+    private static final int[] SENSORS = new int[] {
+            Sensor.TYPE_ACCELEROMETER,
+            Sensor.TYPE_GYROSCOPE,
+            Sensor.TYPE_PROXIMITY,
+            Sensor.TYPE_LIGHT,
+            Sensor.TYPE_ROTATION_VECTOR,
+    };
+
+    private final Handler mHandler = new Handler();
+    protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
+        @Override
+        public void onChange(boolean selfChange) {
+            updateConfiguration();
+        }
+    };
+
+    private final SensorManager mSensorManager;
+    private final Context mContext;
+
+    // Err on the side of caution, so logging is not started after a crash even tough the screen
+    // is off.
+    private SensorLoggerSession mCurrentSession = null;
+
+    private boolean mEnableAnalytics = false;
+    private boolean mEnforceBouncer = false;
+    private boolean mTimeoutActive = false;
+    private boolean mCollectBadTouches = false;
+    private boolean mBouncerOn = false;
+    private boolean mCornerSwiping = false;
+    private boolean mTrackingStarted = false;
+
+    private int mState = StatusBarState.SHADE;
+
+    private static LockedPhoneAnalytics sInstance = null;
+
+    private LockedPhoneAnalytics(Context context) {
+        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+        mContext = context;
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(ANALYTICS_ENABLE), false,
+                mSettingsObserver,
+                UserHandle.USER_ALL);
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(ENFORCE_BOUNCER), false,
+                mSettingsObserver,
+                UserHandle.USER_ALL);
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(COLLECT_BAD_TOCUHES), false,
+                mSettingsObserver,
+                UserHandle.USER_ALL);
+
+        updateConfiguration();
+    }
+
+    public static LockedPhoneAnalytics getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new LockedPhoneAnalytics(context);
+        }
+        return sInstance;
+    }
+
+    private void updateConfiguration() {
+        mEnableAnalytics = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
+                mContext.getContentResolver(),
+                ANALYTICS_ENABLE, 0);
+        mEnforceBouncer = mEnableAnalytics && 0 != Settings.Secure.getInt(
+                mContext.getContentResolver(),
+                ENFORCE_BOUNCER, 0);
+        mCollectBadTouches = mEnableAnalytics && 0 != Settings.Secure.getInt(
+                mContext.getContentResolver(),
+                COLLECT_BAD_TOCUHES, 0);
+    }
+
+    private boolean sessionEntrypoint() {
+        if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
+                && mEnableAnalytics && mCurrentSession == null) {
+            onSessionStart();
+            return true;
+        }
+        return false;
+    }
+
+    private void sessionExitpoint(int result) {
+        if (mEnableAnalytics && mCurrentSession != null) {
+            onSessionEnd(result);
+        }
+    }
+
+    private void onSessionStart() {
+        mBouncerOn = false;
+        mCornerSwiping = false;
+        mTrackingStarted = false;
+        mCurrentSession = new SensorLoggerSession(System.currentTimeMillis(), System.nanoTime());
+        for (int sensorType : SENSORS) {
+            Sensor s = mSensorManager.getDefaultSensor(sensorType);
+            if (s != null) {
+                mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
+            }
+        }
+    }
+
+    private void onSessionEnd(int result) {
+        SensorLoggerSession session = mCurrentSession;
+        mCurrentSession = null;
+
+        session.end(System.currentTimeMillis(), result);
+        queueSession(session);
+    }
+
+    private void queueSession(final SensorLoggerSession currentSession) {
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                byte[] b = Session.toByteArray(currentSession.toProto());
+                String dir = mContext.getFilesDir().getAbsolutePath();
+                if (currentSession.getResult() != Session.SUCCESS) {
+                    if (!mCollectBadTouches) {
+                        return;
+                    }
+                    dir += "/bad_touches";
+                } else {
+                    dir += "/good_touches";
+                }
+
+                File file = new File(dir);
+                file.mkdir();
+                File touch = new File(file, "trace_" + System.currentTimeMillis());
+
+                try {
+                    new FileOutputStream(touch).write(b);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+    }
+
+
+    @Override
+    public synchronized void onSensorChanged(SensorEvent event) {
+        if (mEnableAnalytics && mCurrentSession != null) {
+            mCurrentSession.addSensorEvent(event, System.nanoTime());
+            enforceTimeout();
+        }
+    }
+
+    private void enforceTimeout() {
+        if (mTimeoutActive) {
+            if (System.currentTimeMillis() - mCurrentSession.getStartTimestampMillis()
+                    > TIMEOUT_MILLIS) {
+                onSessionEnd(Session.UNKNOWN);
+                if (DEBUG) {
+                    Log.i(TAG, "Analytics timed out.");
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+
+    public boolean shouldEnforceBouncer() {
+        return mEnforceBouncer;
+    }
+
+    public void setStatusBarState(int state) {
+        mState = state;
+    }
+
+    public void onScreenOn() {
+        if (sessionEntrypoint()) {
+            if (DEBUG) {
+                Log.d(TAG, "onScreenOn");
+            }
+            addEvent(PhoneEvent.ON_SCREEN_ON);
+        }
+    }
+
+    public void onScreenOnFromTouch() {
+        if (sessionEntrypoint()) {
+            if (DEBUG) {
+                Log.d(TAG, "onScreenOnFromTouch");
+            }
+            addEvent(PhoneEvent.ON_SCREEN_ON_FROM_TOUCH);
+        }
+    }
+
+    public void onScreenOff() {
+        if (DEBUG) {
+            Log.d(TAG, "onScreenOff");
+        }
+        addEvent(PhoneEvent.ON_SCREEN_OFF);
+        sessionExitpoint(Session.FAILURE);
+    }
+
+    public void onSucccessfulUnlock() {
+        if (DEBUG) {
+            Log.d(TAG, "onSuccessfulUnlock");
+        }
+        addEvent(PhoneEvent.ON_SUCCESSFUL_UNLOCK);
+        sessionExitpoint(Session.SUCCESS);
+    }
+
+    public void onBouncerShown() {
+        if (!mBouncerOn) {
+            if (DEBUG) {
+                Log.d(TAG, "onBouncerShown");
+            }
+            mBouncerOn = true;
+            addEvent(PhoneEvent.ON_BOUNCER_SHOWN);
+        }
+    }
+
+    public void onBouncerHidden() {
+        if (mBouncerOn) {
+            if (DEBUG) {
+                Log.d(TAG, "onBouncerHidden");
+            }
+            mBouncerOn = false;
+            addEvent(PhoneEvent.ON_BOUNCER_HIDDEN);
+        }
+    }
+
+    public void onQsDown() {
+        if (DEBUG) {
+            Log.d(TAG, "onQsDown");
+        }
+        addEvent(PhoneEvent.ON_QS_DOWN);
+    }
+
+    public void setQsExpanded(boolean expanded) {
+        if (DEBUG) {
+            Log.d(TAG, "setQsExpanded = " + expanded);
+        }
+        if (expanded) {
+            addEvent(PhoneEvent.SET_QS_EXPANDED_TRUE);
+        } else {
+            addEvent(PhoneEvent.SET_QS_EXPANDED_FALSE);
+        }
+    }
+
+    public void onTrackingStarted() {
+        if (DEBUG) {
+            Log.d(TAG, "onTrackingStarted");
+        }
+        mTrackingStarted = true;
+        addEvent(PhoneEvent.ON_TRACKING_STARTED);
+    }
+
+    public void onTrackingStopped() {
+        if (mTrackingStarted) {
+            if (DEBUG) {
+                Log.d(TAG, "onTrackingStopped");
+            }
+            mTrackingStarted = false;
+            addEvent(PhoneEvent.ON_TRACKING_STOPPED);
+        }
+    }
+
+    public void onNotificationActive() {
+        if (DEBUG) {
+            Log.d(TAG, "onNotificationActive");
+        }
+        addEvent(PhoneEvent.ON_NOTIFICATION_ACTIVE);
+    }
+
+
+    public void onNotificationDoubleTap() {
+        if (DEBUG) {
+            Log.d(TAG, "onNotificationDoubleTap");
+        }
+        addEvent(PhoneEvent.ON_NOTIFICATION_DOUBLE_TAP);
+    }
+
+    public void setNotificationExpanded() {
+        if (DEBUG) {
+            Log.d(TAG, "setNotificationExpanded");
+        }
+        addEvent(PhoneEvent.SET_NOTIFICATION_EXPANDED);
+    }
+
+    public void onNotificatonStartDraggingDown() {
+        if (DEBUG) {
+            Log.d(TAG, "onNotificationStartDraggingDown");
+        }
+        addEvent(PhoneEvent.ON_NOTIFICATION_START_DRAGGING_DOWN);
+    }
+
+    public void onNotificatonStopDraggingDown() {
+        if (DEBUG) {
+            Log.d(TAG, "onNotificationStopDraggingDown");
+        }
+        addEvent(PhoneEvent.ON_NOTIFICATION_STOP_DRAGGING_DOWN);
+    }
+
+    public void onNotificationDismissed() {
+        if (DEBUG) {
+            Log.d(TAG, "onNotificationDismissed");
+        }
+        addEvent(PhoneEvent.ON_NOTIFICATION_DISMISSED);
+    }
+
+    public void onNotificatonStartDismissing() {
+        if (DEBUG) {
+            Log.d(TAG, "onNotificationStartDismissing");
+        }
+        addEvent(PhoneEvent.ON_NOTIFICATION_START_DISMISSING);
+    }
+
+    public void onNotificatonStopDismissing() {
+        if (DEBUG) {
+            Log.d(TAG, "onNotificationStopDismissing");
+        }
+        addEvent(PhoneEvent.ON_NOTIFICATION_STOP_DISMISSING);
+    }
+
+    public void onCameraOn() {
+        if (DEBUG) {
+            Log.d(TAG, "onCameraOn");
+        }
+        addEvent(PhoneEvent.ON_CAMERA_ON);
+    }
+
+    public void onLeftAffordanceOn() {
+        if (DEBUG) {
+            Log.d(TAG, "onLeftAffordanceOn");
+        }
+        addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_ON);
+    }
+
+    public void onAffordanceSwipingStarted(boolean rightCorner) {
+        if (DEBUG) {
+            Log.d(TAG, "onAffordanceSwipingStarted");
+        }
+        mCornerSwiping = true;
+        if (rightCorner) {
+            addEvent(PhoneEvent.ON_RIGHT_AFFORDANCE_SWIPING_STARTED);
+        } else {
+            addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_SWIPING_STARTED);
+        }
+    }
+
+    public void onAffordanceSwipingAborted() {
+        if (mCornerSwiping) {
+            if (DEBUG) {
+                Log.d(TAG, "onAffordanceSwipingAborted");
+            }
+            mCornerSwiping = false;
+            addEvent(PhoneEvent.ON_AFFORDANCE_SWIPING_ABORTED);
+        }
+    }
+
+    public void onUnlockHintStarted() {
+        if (DEBUG) {
+            Log.d(TAG, "onUnlockHintStarted");
+        }
+        addEvent(PhoneEvent.ON_UNLOCK_HINT_STARTED);
+    }
+
+    public void onCameraHintStarted() {
+        if (DEBUG) {
+            Log.d(TAG, "onCameraHintStarted");
+        }
+        addEvent(PhoneEvent.ON_CAMERA_HINT_STARTED);
+    }
+
+    public void onLeftAffordanceHintStarted() {
+        if (DEBUG) {
+            Log.d(TAG, "onLeftAffordanceHintStarted");
+        }
+        addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_HINT_STARTED);
+    }
+
+    public void onTouchEvent(MotionEvent ev, int width, int height) {
+        if (!mBouncerOn && mCurrentSession != null) {
+            if (DEBUG) {
+                Log.v(TAG, "onTouchEvent(ev.action="
+                        + MotionEvent.actionToString(ev.getAction()) + ")");
+            }
+            mCurrentSession.addMotionEvent(ev);
+            mCurrentSession.setTouchArea(width, height);
+            enforceTimeout();
+        }
+    }
+
+    private void addEvent(int eventType) {
+        if (mEnableAnalytics && mCurrentSession != null) {
+            mCurrentSession.addPhoneEvent(eventType, System.nanoTime());
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
new file mode 100644
index 0000000..09383f6a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
@@ -0,0 +1,160 @@
+/*
+ * 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.systemui.analytics;
+
+import android.os.Build;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import java.util.ArrayList;
+
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session;
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.TouchEvent;
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.SensorEvent;
+import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.PhoneEvent;
+
+/**
+ * Collects touch, sensor and phone events and converts the data to
+ * TouchAnalyticsProto.Session.
+ */
+public class SensorLoggerSession {
+    private static final String TAG = "SensorLoggerSession";
+
+    private final long mStartTimestampMillis;
+    private final long mStartSystemTimeNanos;
+
+    private long mEndTimestampMillis;
+    private int mType;
+
+    private ArrayList<TouchEvent> mMotionEvents = new ArrayList<>();
+    private ArrayList<SensorEvent> mSensorEvents = new ArrayList<>();
+    private ArrayList<PhoneEvent> mPhoneEvents = new ArrayList<>();
+    private int mTouchAreaHeight;
+    private int mTouchAreaWidth;
+    private int mResult = Session.UNKNOWN;
+
+    public SensorLoggerSession(long startTimestampMillis, long startSystemTimeNanos) {
+        mStartTimestampMillis = startTimestampMillis;
+        mStartSystemTimeNanos = startSystemTimeNanos;
+        mType = Session.REAL;
+    }
+
+    public void end(long endTimestampMillis, int result) {
+        mResult = result;
+        mEndTimestampMillis = endTimestampMillis;
+
+        if (LockedPhoneAnalytics.DEBUG) {
+            Log.d(TAG, "Ending session result=" + result + " it lasted for " +
+                    (float) (mEndTimestampMillis - mStartTimestampMillis) / 1000f + "s");
+        }
+    }
+
+    public void addMotionEvent(MotionEvent motionEvent) {
+        TouchEvent event = motionEventToProto(motionEvent);
+        mMotionEvents.add(event);
+    }
+
+    public void addSensorEvent(android.hardware.SensorEvent eventOrig, long systemTimeNanos) {
+        SensorEvent event = sensorEventToProto(eventOrig, systemTimeNanos);
+        mSensorEvents.add(event);
+    }
+
+    public void addPhoneEvent(int eventType, long systemTimeNanos) {
+        PhoneEvent event = phoneEventToProto(eventType, systemTimeNanos);
+        mPhoneEvents.add(event);
+    }
+
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("Session{");
+        sb.append("mStartTimestampMillis=").append(mStartTimestampMillis);
+        sb.append(", mStartSystemTimeNanos=").append(mStartSystemTimeNanos);
+        sb.append(", mEndTimestampMillis=").append(mEndTimestampMillis);
+        sb.append(", mResult=").append(mResult);
+        sb.append(", mTouchAreaHeight=").append(mTouchAreaHeight);
+        sb.append(", mTouchAreaWidth=").append(mTouchAreaWidth);
+        sb.append(", mMotionEvents=[size=").append(mMotionEvents.size()).append("]");
+        sb.append(", mSensorEvents=[size=").append(mSensorEvents.size()).append("]");
+        sb.append(", mPhoneEvents=[size=").append(mPhoneEvents.size()).append("]");
+        sb.append('}');
+        return sb.toString();
+    }
+
+    public Session toProto() {
+        Session proto = new Session();
+        proto.setStartTimestampMillis(mStartTimestampMillis);
+        proto.setDurationMillis(mEndTimestampMillis - mStartTimestampMillis);
+        proto.setBuild(Build.FINGERPRINT);
+        proto.setResult(mResult);
+        proto.setType(mType);
+        proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);
+        proto.touchEvents = mMotionEvents.toArray(proto.touchEvents);
+        proto.phoneEvents = mPhoneEvents.toArray(proto.phoneEvents);
+        proto.setTouchAreaWidth(mTouchAreaWidth);
+        proto.setTouchAreaHeight(mTouchAreaHeight);
+        return proto;
+    }
+
+    private PhoneEvent phoneEventToProto(int eventType, long sysTimeNanos) {
+        PhoneEvent proto = new PhoneEvent();
+        proto.setType(eventType);
+        proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos);
+        return proto;
+    }
+
+    private SensorEvent sensorEventToProto(android.hardware.SensorEvent ev, long sysTimeNanos) {
+        SensorEvent proto = new SensorEvent();
+        proto.setType(ev.sensor.getType());
+        proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos);
+        proto.setTimestamp(ev.timestamp);
+        proto.values = ev.values.clone();
+        return proto;
+    }
+
+    private TouchEvent motionEventToProto(MotionEvent ev) {
+        int count = ev.getPointerCount();
+        TouchEvent proto = new TouchEvent();
+        proto.setTimeOffsetNanos(ev.getEventTimeNano() - mStartSystemTimeNanos);
+        proto.setAction(ev.getActionMasked());
+        proto.setActionIndex(ev.getActionIndex());
+        proto.pointers = new TouchEvent.Pointer[count];
+        for (int i = 0; i < count; i++) {
+            TouchEvent.Pointer p = new TouchEvent.Pointer();
+            p.setX(ev.getX(i));
+            p.setY(ev.getY(i));
+            p.setSize(ev.getSize(i));
+            p.setPressure(ev.getPressure(i));
+            p.setId(ev.getPointerId(i));
+            proto.pointers[i] = p;
+        }
+        return proto;
+    }
+
+    public void setTouchArea(int width, int height) {
+        mTouchAreaWidth = width;
+        mTouchAreaHeight = height;
+    }
+
+    public int getResult() {
+        return mResult;
+    }
+
+    public long getStartTimestampMillis() {
+        return mStartTimestampMillis;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index aafa991..12d5f36 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -69,6 +69,7 @@
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.phone.FingerprintUnlockController;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -531,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)) {
@@ -1240,6 +1241,7 @@
                 case START_KEYGUARD_EXIT_ANIM:
                     StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
                     handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration);
+                    LockedPhoneAnalytics.getInstance(mContext).onSucccessfulUnlock();
                     break;
                 case KEYGUARD_DONE_PENDING_TIMEOUT:
                     Log.w(TAG, "Timeout while waiting for activity drawn!");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 7f17885..c1dfec3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -34,6 +34,7 @@
 import android.view.animation.PathInterpolator;
 
 import com.android.systemui.R;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
 
 /**
  * Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer}
@@ -128,6 +129,7 @@
     private final int mNormalColor;
     private final int mLowPriorityColor;
     private boolean mIsBelowSpeedBump;
+    private LockedPhoneAnalytics mLockedPhoneAnalytics;
 
     public ActivatableNotificationView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -151,6 +153,7 @@
                 R.color.notification_ripple_color_low_priority);
         mNormalRippleColor = context.getColor(
                 R.color.notification_ripple_untinted_color);
+        mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
     }
 
     @Override
@@ -219,6 +222,7 @@
                         makeActive();
                         postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
                     } else {
+                        mLockedPhoneAnalytics.onNotificationDoubleTap();
                         boolean performed = performClick();
                         if (performed) {
                             removeCallbacks(mTapTimeoutRunnable);
@@ -238,6 +242,7 @@
     }
 
     private void makeActive() {
+        mLockedPhoneAnalytics.onNotificationActive();
         startActivateAnimation(false /* reverse */);
         mActivated = true;
         if (mOnActivatedListener != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index a55256d..de6c4b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -91,6 +91,7 @@
 import com.android.internal.util.NotificationColorUtil;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.DejankUtils;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SwipeHelper;
@@ -135,6 +136,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 +1068,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 +1152,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 +1266,9 @@
              case MSG_SHOW_PREV_AFFILIATED_TASK:
                   showRecentsPreviousAffiliatedTask();
                   break;
+             case MSG_SHOW_KEYBOARD_SHORTCUTS_MENU:
+                  showKeyboardShortcuts();
+                  break;
             }
         }
     }
@@ -1609,6 +1625,15 @@
             final PendingIntent intent = sbn.getNotification().contentIntent;
             final String notificationKey = sbn.getKey();
 
+            // Mark notification for one frame.
+            row.setJustClicked(true);
+            DejankUtils.postAfterTraversal(new Runnable() {
+                @Override
+                public void run() {
+                    row.setJustClicked(false);
+                }
+            });
+
             if (NOTIFICATION_CLICK_DEBUG) {
                 Log.d(TAG, "Clicked on content of " + notificationKey);
             }
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/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 15a092c..e2304c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -29,6 +29,7 @@
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.Gefingerpoken;
 import com.android.systemui.R;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
 
 /**
  * A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
@@ -54,6 +55,7 @@
     private ExpandableView mStartingChild;
     private Interpolator mInterpolator;
     private float mLastHeight;
+    private LockedPhoneAnalytics mLockedPhoneAnalytics;
 
     public DragDownHelper(Context context, View host, ExpandHelper.Callback callback,
             DragDownCallback dragDownCallback) {
@@ -65,6 +67,7 @@
         mCallback = callback;
         mDragDownCallback = dragDownCallback;
         mHost = host;
+        mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
     }
 
     @Override
@@ -84,6 +87,7 @@
             case MotionEvent.ACTION_MOVE:
                 final float h = y - mInitialTouchY;
                 if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) {
+                    mLockedPhoneAnalytics.onNotificatonStartDraggingDown();
                     mDraggingDown = true;
                     captureStartingChild(mInitialTouchX, mInitialTouchY);
                     mInitialTouchY = y;
@@ -201,6 +205,7 @@
     }
 
     private void stopDragging() {
+        mLockedPhoneAnalytics.onNotificatonStopDraggingDown();
         if (mStartingChild != null) {
             cancelExpansion(mStartingChild);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index b88e5ca..2f6aec7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -34,6 +34,7 @@
 import android.widget.ImageView;
 
 import com.android.systemui.R;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
@@ -109,6 +110,9 @@
                     !mChildrenExpanded);
         }
     };
+    private LockedPhoneAnalytics mLockedPhoneAnalytics;
+
+    private boolean mJustClicked;
 
     public NotificationContentView getPrivateLayout() {
         return mPrivateLayout;
@@ -301,12 +305,28 @@
         return mHeadsUpHeight;
     }
 
+    /**
+     * Mark whether this notification was just clicked, i.e. the user has just clicked this
+     * notification in this frame.
+     */
+    public void setJustClicked(boolean justClicked) {
+        mJustClicked = justClicked;
+    }
+
+    /**
+     * @return true if this notification has been clicked in this frame, false otherwise
+     */
+    public boolean wasJustClicked() {
+        return mJustClicked;
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
 
     public ExpandableNotificationRow(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
     }
 
     /**
@@ -494,6 +514,7 @@
      * @param userExpanded whether the user wants this notification to be expanded
      */
     public void setUserExpanded(boolean userExpanded) {
+        mLockedPhoneAnalytics.setNotificationExpanded();
         if (userExpanded && !mExpandable) return;
         final boolean wasExpanded = isExpanded();
         mHasUserChangedExpansion = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 28d4a42ef..4e69999 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -183,8 +183,11 @@
                 mStatusBarKeyguardViewManager.animateCollapsePanels(
                         FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
                 break;
-            case MODE_WAKE_AND_UNLOCK:
             case MODE_WAKE_AND_UNLOCK_PULSING:
+                mPhoneStatusBar.updateMediaMetaData(false /* metaDataChanged */);
+                // Fall through.
+            case MODE_WAKE_AND_UNLOCK:
+                mStatusBarWindowManager.setStatusBarFocusable(false);
                 mDozeScrimController.abortPulsing();
                 mKeyguardViewMediator.onWakeAndUnlocking();
                 mScrimController.setWakeAndUnlocking();
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 8b96e5f..cbd23bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -31,6 +31,7 @@
 import com.android.keyguard.R;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.DejankUtils;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
 
 import static com.android.keyguard.KeyguardHostView.OnDismissAction;
 import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
@@ -49,10 +50,11 @@
     private ViewGroup mRoot;
     private boolean mShowingSoon;
     private int mBouncerPromptReason;
+    private LockedPhoneAnalytics mLockedPhoneAnalytics;
     private KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
             new KeyguardUpdateMonitorCallback() {
                 @Override
-                public void onStrongAuthTimeoutExpiredChanged(int userId) {
+                public void onStrongAuthStateChanged(int userId) {
                     mBouncerPromptReason = mCallback.getBouncerPromptReason();
                 }
             };
@@ -66,9 +68,11 @@
         mContainer = container;
         mWindowManager = windowManager;
         KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
+        mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(mContext);
     }
 
     public void show(boolean resetSecuritySelection) {
+        mLockedPhoneAnalytics.onBouncerShown();
         ensureView();
         if (resetSecuritySelection) {
             // showPrimarySecurityScreen() updates the current security method. This is needed in
@@ -128,6 +132,7 @@
     }
 
     public void hide(boolean destroyView) {
+        mLockedPhoneAnalytics.onBouncerHidden();
         cancelShowRunnable();
          if (mKeyguardView != null) {
             mKeyguardView.cancelDismissAction();
@@ -157,6 +162,7 @@
     public void reset() {
         cancelShowRunnable();
         inflateView();
+        mLockedPhoneAnalytics.onBouncerHidden();
     }
 
     public void onScreenTurnedOff() {
@@ -244,6 +250,7 @@
 
             // We need to show it in case it is secure. If not, it will get dismissed in any case.
             mRoot.setVisibility(View.VISIBLE);
+            mLockedPhoneAnalytics.onBouncerShown();
             mKeyguardView.requestFocus();
             mKeyguardView.onResume();
             return true;
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 710c335..24ae47d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -56,6 +56,7 @@
 import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -203,6 +204,7 @@
     private int mLastOrientation = -1;
     private boolean mClosingWithAlphaFadeOut;
     private boolean mHeadsUpAnimatingAway;
+    private LockedPhoneAnalytics mLockedPhoneAnalytics;
 
     private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
         @Override
@@ -219,6 +221,7 @@
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setWillNotDraw(!DEBUG);
+        mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
     }
 
     public void setStatusBar(PhoneStatusBar bar) {
@@ -820,6 +823,7 @@
     private void handleQsDown(MotionEvent event) {
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN
                 && shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
+            mLockedPhoneAnalytics.onQsDown();
             mQsTracking = true;
             onQsExpansionStarted();
             mInitialHeightOnTouch = mQsExpansionHeight;
@@ -987,6 +991,7 @@
             mQsExpanded = expanded;
             updateQsState();
             requestPanelHeightUpdate();
+            mLockedPhoneAnalytics.setQsExpanded(expanded);
             mNotificationStackScroller.setInterceptDelegateEnabled(expanded);
             mStatusBar.setQsExpanded(expanded);
             mQsPanel.setExpanded(expanded);
@@ -1313,6 +1318,10 @@
                     R.string.accessibility_desc_quick_settings));
             mLastAnnouncementWasQuickSettings = true;
         }
+        if (mQsFullyExpanded && mLockedPhoneAnalytics.shouldEnforceBouncer()) {
+            mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
+                    false /* dismissShade */, true /* afterKeyguardGone */);
+        }
         if (DEBUG) {
             invalidate();
         }
@@ -1840,6 +1849,7 @@
 
     @Override
     protected void onTrackingStarted() {
+        mLockedPhoneAnalytics.onTrackingStarted();
         super.onTrackingStarted();
         if (mQsFullyExpanded) {
             mQsExpandImmediate = true;
@@ -1853,6 +1863,7 @@
 
     @Override
     protected void onTrackingStopped(boolean expand) {
+        mLockedPhoneAnalytics.onTrackingStopped();
         super.onTrackingStopped(expand);
         if (expand) {
             mNotificationStackScroller.setOverScrolledPixels(
@@ -1951,11 +1962,35 @@
         if (start) {
             EventLogTags.writeSysuiLockscreenGesture(
                     EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER, lengthDp, velocityDp);
-            mKeyguardBottomArea.launchLeftAffordance();
+
+            mLockedPhoneAnalytics.onLeftAffordanceOn();
+            if (mLockedPhoneAnalytics.shouldEnforceBouncer()) {
+                mStatusBar.executeRunnableDismissingKeyguard(new Runnable() {
+                    @Override
+                    public void run() {
+                        mKeyguardBottomArea.launchLeftAffordance();
+                    }
+                }, null, true /* dismissShade */, false /* afterKeyguardGone */);
+            }
+            else {
+                mKeyguardBottomArea.launchLeftAffordance();
+            }
         } else {
             EventLogTags.writeSysuiLockscreenGesture(
                     EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA, lengthDp, velocityDp);
-            mSecureCameraLaunchManager.startSecureCameraLaunch();
+
+            mLockedPhoneAnalytics.onCameraOn();
+            if (mLockedPhoneAnalytics.shouldEnforceBouncer()) {
+                mStatusBar.executeRunnableDismissingKeyguard(new Runnable() {
+                    @Override
+                    public void run() {
+                        mSecureCameraLaunchManager.startSecureCameraLaunch();
+                    }
+                }, null, true /* dismissShade */, false /* afterKeyguardGone */);
+            }
+            else {
+                mSecureCameraLaunchManager.startSecureCameraLaunch();
+            }
         }
         mStatusBar.startLaunchTransitionTimeout();
         mBlockTouches = true;
@@ -1999,6 +2034,7 @@
 
     @Override
     public void onSwipingStarted(boolean rightIcon) {
+        mLockedPhoneAnalytics.onAffordanceSwipingStarted(rightIcon);
         boolean camera = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon
                 : rightIcon;
         if (camera) {
@@ -2012,6 +2048,7 @@
 
     @Override
     public void onSwipingAborted() {
+        mLockedPhoneAnalytics.onAffordanceSwipingAborted();
         mKeyguardBottomArea.unbindCameraPrewarmService(false /* launched */);
     }
 
@@ -2388,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 b794353..278a7e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -130,6 +130,7 @@
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.SpeedBumpView;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
 import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
 import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -155,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;
 
@@ -232,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;
@@ -588,6 +590,7 @@
     private HashSet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new HashSet<>();
     private RankingMap mLatestRankingMap;
     private boolean mNoAnimationOnNextBarModeChange;
+    private LockedPhoneAnalytics mLockedPhoneAnalytics;
 
     @Override
     public void start() {
@@ -635,6 +638,7 @@
         notifyUserAboutHiddenNotifications();
 
         mScreenPinningRequest = new ScreenPinningRequest(mContext);
+        mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(mContext);
     }
 
     // ================================================================================
@@ -1720,7 +1724,9 @@
 
         final boolean hasArtwork = artworkBitmap != null;
 
-        if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) && mState != StatusBarState.SHADE) {
+        if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) && mState != StatusBarState.SHADE
+                && mFingerprintUnlockController.getMode()
+                        != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
             // time to show some art!
             if (mBackdrop.getVisibility() != View.VISIBLE) {
                 mBackdrop.setVisibility(View.VISIBLE);
@@ -1775,31 +1781,40 @@
                 if (DEBUG_MEDIA) {
                     Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
                 }
-                mBackdrop.animate()
-                        // Never let the alpha become zero - otherwise the RenderNode
-                        // won't draw anything and uninitialized memory will show through
-                        // if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in libhwui.
-                        .alpha(0.002f)
-                        .setInterpolator(mBackdropInterpolator)
-                        .setDuration(300)
-                        .setStartDelay(0)
-                        .withEndAction(new Runnable() {
-                            @Override
-                            public void run() {
-                                mBackdrop.setVisibility(View.GONE);
-                                mBackdropFront.animate().cancel();
-                                mBackdropBack.animate().cancel();
-                                mHandler.post(mHideBackdropFront);
-                            }
-                        });
-                if (mKeyguardFadingAway) {
-                    mBackdrop.animate()
+                if (mFingerprintUnlockController.getMode()
+                        == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
 
-                            // Make it disappear faster, as the focus should be on the activity behind.
-                            .setDuration(mKeyguardFadingAwayDuration / 2)
-                            .setStartDelay(mKeyguardFadingAwayDelay)
-                            .setInterpolator(mLinearInterpolator)
-                            .start();
+                    // We are unlocking directly - no animation!
+                    mBackdrop.setVisibility(View.GONE);
+                } else {
+                    mBackdrop.animate()
+                            // Never let the alpha become zero - otherwise the RenderNode
+                            // won't draw anything and uninitialized memory will show through
+                            // if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in
+                            // libhwui.
+                            .alpha(0.002f)
+                            .setInterpolator(mBackdropInterpolator)
+                            .setDuration(300)
+                            .setStartDelay(0)
+                            .withEndAction(new Runnable() {
+                                @Override
+                                public void run() {
+                                    mBackdrop.setVisibility(View.GONE);
+                                    mBackdropFront.animate().cancel();
+                                    mBackdropBack.animate().cancel();
+                                    mHandler.post(mHideBackdropFront);
+                                }
+                            });
+                    if (mKeyguardFadingAway) {
+                        mBackdrop.animate()
+
+                                // Make it disappear faster, as the focus should be on the activity
+                                // behind.
+                                .setDuration(mKeyguardFadingAwayDuration / 2)
+                                .setStartDelay(mKeyguardFadingAwayDelay)
+                                .setInterpolator(mLinearInterpolator)
+                                .start();
+                    }
                 }
             }
         }
@@ -2461,8 +2476,12 @@
                         || mStatusBarMode == MODE_LIGHTS_OUT_TRANSPARENT);
                 boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
                 boolean light = (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
-
-                mIconController.setIconsDark(allowLight && light);
+                boolean animate = mFingerprintUnlockController == null
+                        || (mFingerprintUnlockController.getMode()
+                                != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
+                        && mFingerprintUnlockController.getMode()
+                                != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK);
+                mIconController.setIconsDark(allowLight && light, animate);
             }
             // restore the recents bit
             if (wasRecentsVisible) {
@@ -3478,14 +3497,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();
     }
 
@@ -3523,11 +3534,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();
         }
@@ -3539,6 +3563,7 @@
             mQSPanel.refreshAllTiles();
         }
         mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+        mNotificationPanel.setAlpha(1f);
         return staying;
     }
 
@@ -3755,6 +3780,7 @@
         }
         mState = state;
         mGroupManager.setStatusBarState(state);
+        mLockedPhoneAnalytics.setStatusBarState(state);
         mStatusBarWindowManager.setStatusBarState(state);
         updateDozing();
     }
@@ -3776,6 +3802,7 @@
     }
 
     public void onUnlockHintStarted() {
+        mLockedPhoneAnalytics.onUnlockHintStarted();
         mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock);
     }
 
@@ -3785,14 +3812,17 @@
     }
 
     public void onCameraHintStarted() {
+        mLockedPhoneAnalytics.onCameraHintStarted();
         mKeyguardIndicationController.showTransientIndication(R.string.camera_hint);
     }
 
     public void onVoiceAssistHintStarted() {
+        mLockedPhoneAnalytics.onLeftAffordanceHintStarted();
         mKeyguardIndicationController.showTransientIndication(R.string.voice_hint);
     }
 
     public void onPhoneHintStarted() {
+        mLockedPhoneAnalytics.onLeftAffordanceHintStarted();
         mKeyguardIndicationController.showTransientIndication(R.string.phone_hint);
     }
 
@@ -3867,7 +3897,7 @@
             row.setUserExpanded(true);
         }
         boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId)
-                || !mShowLockscreenNotifications;
+                || !mShowLockscreenNotifications || mLockedPhoneAnalytics.shouldEnforceBouncer();
         if (isLockscreenPublicMode() && fullShadeNeedsBouncer) {
             mLeaveOpenOnKeyguardHide = true;
             showBouncer();
@@ -3912,6 +3942,7 @@
         mDeviceInteractive = false;
         mWakeUpComingFromTouch = false;
         mWakeUpTouchLocation = null;
+        mLockedPhoneAnalytics.onScreenOff();
         mStackScroller.setAnimationsEnabled(false);
         updateVisibleToUser();
     }
@@ -3921,6 +3952,7 @@
         mStackScroller.setAnimationsEnabled(true);
         mNotificationPanel.setTouchDisabled(false);
         updateVisibleToUser();
+        mLockedPhoneAnalytics.onScreenOn();
     }
 
     public void onScreenTurningOn() {
@@ -4049,6 +4081,7 @@
             mWakeUpTouchLocation = new PointF(event.getX(), event.getY());
             mNotificationPanel.setTouchDisabled(false);
             mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
+            mLockedPhoneAnalytics.onScreenOnFromTouch();
         }
     }
 
@@ -4071,8 +4104,9 @@
     public void appTransitionStarting(long startTime, long duration) {
 
         // Use own timings when Keyguard is going away, see keyguardGoingAway and
-        // setKeyguardFadingAway
-        if (!mKeyguardFadingAway) {
+        // setKeyguardFadingAway. When duration is 0, skip this one because no animation is really
+        // playing.
+        if (!mKeyguardFadingAway && duration > 0) {
             mIconController.appTransitionStarting(startTime, duration);
         }
         if (mIconPolicy != null) {
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/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 067e50e..5de1c13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -335,8 +335,10 @@
         }
     }
 
-    public void setIconsDark(boolean dark) {
-        if (mTransitionPending) {
+    public void setIconsDark(boolean dark, boolean animate) {
+        if (!animate) {
+            setIconTintInternal(dark ? 1.0f : 0.0f);
+        } else if (mTransitionPending) {
             deferIconTintChange(dark ? 1.0f : 0.0f);
         } else if (mTransitionDeferring) {
             animateIconTint(dark ? 1.0f : 0.0f,
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/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 0e22aa8..bbf981f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -39,6 +39,7 @@
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 
@@ -55,12 +56,14 @@
 
     private PhoneStatusBar mService;
     private final Paint mTransparentSrcPaint = new Paint();
+    private LockedPhoneAnalytics mLockedPhoneAnalytics;
 
     public StatusBarWindowView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setMotionEventSplittingEnabled(false);
         mTransparentSrcPaint.setColor(0);
         mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+        mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
     }
 
     @Override
@@ -197,6 +200,7 @@
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
+        mLockedPhoneAnalytics.onTouchEvent(ev, getWidth(), getHeight());
         if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
             // Disallow new pointers while the brightness mirror is visible. This is so that you
             // can't touch anything other than the brightness slider while the mirror is showing
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/phone/touch_analytics.proto b/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
new file mode 100644
index 0000000..afc8f77
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
@@ -0,0 +1,136 @@
+/*
+ * 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
+ */
+
+syntax = "proto2";
+
+package systemui;
+
+option java_package = "com.android.systemui.statusbar.phone";
+option java_outer_classname = "TouchAnalyticsProto";
+
+message Session {
+    message TouchEvent {
+        message BoundingBox {
+            optional float width = 1;
+            optional float height = 2;
+        }
+
+        enum Action {
+            // Keep in sync with MotionEvent.
+            DOWN = 0;
+            UP = 1;
+            MOVE = 2;
+            CANCEL = 3;
+            OUTSIDE = 4;
+            POINTER_DOWN = 5;
+            POINTER_UP = 6;
+        }
+
+        message Pointer {
+            optional float x = 1;
+            optional float y = 2;
+            optional float size = 3;
+            optional float pressure = 4;
+            optional int32 id = 5;
+            optional float removed_length = 6;
+            optional BoundingBox removed_boundingBox = 7;
+        }
+
+        optional uint64 timeOffsetNanos = 1;
+        optional Action action = 2;
+        optional int32 actionIndex = 3;
+        repeated Pointer pointers = 4;
+        optional bool removed_redacted = 5;
+        optional BoundingBox removed_boundingBox = 6;
+    }
+
+    message SensorEvent {
+        enum Type {
+            ACCELEROMETER = 1;
+            GYROSCOPE = 4;
+            LIGHT = 5;
+            PROXIMITY = 8;
+            ROTATION_VECTOR = 11;
+        }
+
+        optional Type type = 1;
+        optional uint64 timeOffsetNanos = 2;
+        repeated float values = 3;
+        optional uint64 timestamp = 4;
+    }
+
+    message PhoneEvent {
+        enum Type {
+            ON_SCREEN_ON = 0;
+            ON_SCREEN_ON_FROM_TOUCH = 1;
+            ON_SCREEN_OFF = 2;
+            ON_SUCCESSFUL_UNLOCK = 3;
+            ON_BOUNCER_SHOWN = 4;
+            ON_BOUNCER_HIDDEN = 5;
+            ON_QS_DOWN = 6;
+            SET_QS_EXPANDED_TRUE = 7;
+            SET_QS_EXPANDED_FALSE = 8;
+            ON_TRACKING_STARTED = 9;
+            ON_TRACKING_STOPPED = 10;
+            ON_NOTIFICATION_ACTIVE = 11;
+            ON_NOTIFICATION_INACTIVE = 12;
+            ON_NOTIFICATION_DOUBLE_TAP = 13;
+            SET_NOTIFICATION_EXPANDED = 14;
+            RESET_NOTIFICATION_EXPANDED = 15;
+            ON_NOTIFICATION_START_DRAGGING_DOWN = 16;
+            ON_NOTIFICATION_STOP_DRAGGING_DOWN = 17;
+            ON_NOTIFICATION_DISMISSED = 18;
+            ON_NOTIFICATION_START_DISMISSING = 19;
+            ON_NOTIFICATION_STOP_DISMISSING = 20;
+            ON_RIGHT_AFFORDANCE_SWIPING_STARTED = 21;
+            ON_LEFT_AFFORDANCE_SWIPING_STARTED = 22;
+            ON_AFFORDANCE_SWIPING_ABORTED = 23;
+            ON_CAMERA_ON = 24;
+            ON_LEFT_AFFORDANCE_ON = 25;
+            ON_UNLOCK_HINT_STARTED = 26;
+            ON_CAMERA_HINT_STARTED = 27;
+            ON_LEFT_AFFORDANCE_HINT_STARTED = 28;
+        }
+
+        optional Type type = 1;
+        optional uint64 timeOffsetNanos = 2;
+    }
+
+    enum Result {
+        FAILURE = 0;
+        SUCCESS = 1;
+        UNKNOWN = 2;
+    }
+
+    enum Type {
+        RESERVED_1 = 0;
+        RESERVED_2 = 1;
+        RANDOM_WAKEUP = 2;
+        REAL = 3;
+    }
+
+    optional uint64 startTimestampMillis = 1;
+    optional uint64 durationMillis = 2;
+    optional string build = 3;
+    optional Result result = 4;
+    repeated TouchEvent touchEvents = 5;
+    repeated SensorEvent sensorEvents = 6;
+
+    optional int32 touchAreaWidth = 9;
+    optional int32 touchAreaHeight = 10;
+    optional Type type = 11;
+    repeated PhoneEvent phoneEvents = 12;
+}
\ No newline at end of file
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/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 6af9854..6d791bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -178,7 +178,8 @@
         mCurrentUserId = newUserId;
         if (mUserManager.getUserInfo(newUserId).isRestricted()) {
             // VPN for a restricted profile is routed through its owner user
-            mVpnUserId = UserHandle.USER_OWNER;
+            // TODO: http://b/22950929
+            mVpnUserId = UserHandle.USER_SYSTEM;
         } else {
             mVpnUserId = mCurrentUserId;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
index 753a7f7..56f6564 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
@@ -34,6 +34,7 @@
     boolean hasDelays;
     boolean hasGoToFullShadeEvent;
     boolean hasDarkEvent;
+    boolean hasHeadsUpDisappearClickEvent;
     int darkAnimationOriginIndex;
 
     public AnimationFilter animateAlpha() {
@@ -106,6 +107,10 @@
                 hasDarkEvent = true;
                 darkAnimationOriginIndex = ev.darkAnimationOriginIndex;
             }
+            if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
+                    .ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
+                hasHeadsUpDisappearClickEvent = true;
+            }
         }
     }
 
@@ -135,6 +140,7 @@
         hasDelays = false;
         hasGoToFullShadeEvent = false;
         hasDarkEvent = false;
+        hasHeadsUpDisappearClickEvent = false;
         darkAnimationOriginIndex =
                 NotificationStackScrollLayout.AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 82c1aa8..a1d73d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -47,6 +47,7 @@
 import com.android.systemui.statusbar.SpeedBumpView;
 import com.android.systemui.statusbar.StackScrollerDecorView;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.analytics.LockedPhoneAnalytics;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.phone.ScrimController;
@@ -231,6 +232,7 @@
     private boolean mForceNoOverlappingRendering;
     private NotificationOverflowContainer mOverflowContainer;
     private final ArrayList<Pair<ExpandableNotificationRow, Boolean>> mTmpList = new ArrayList<>();
+    private LockedPhoneAnalytics mLockedPhoneAnalytics;
 
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -264,6 +266,7 @@
             mDebugPaint.setStrokeWidth(2);
             mDebugPaint.setStyle(Paint.Style.STROKE);
         }
+        mLockedPhoneAnalytics = LockedPhoneAnalytics.getInstance(context);
     }
 
     @Override
@@ -595,6 +598,12 @@
             veto.performClick();
         }
         if (DEBUG) Log.v(TAG, "onChildDismissed: " + v);
+
+        mLockedPhoneAnalytics.onNotificationDismissed();
+        if (mLockedPhoneAnalytics.shouldEnforceBouncer()) {
+            mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
+                    false /* dismissShade */, true /* afterKeyguardGone */);
+        }
     }
 
     @Override
@@ -622,6 +631,7 @@
     }
 
     public void onBeginDrag(View v) {
+        mLockedPhoneAnalytics.onNotificatonStartDismissing();
         setSwipingInProgress(true);
         mAmbientState.onBeginDrag(v);
         if (mAnimationsEnabled && (mIsExpanded || !isPinnedHeadsUp(v))) {
@@ -648,6 +658,7 @@
     }
 
     public void onDragCancelled(View v) {
+        mLockedPhoneAnalytics.onNotificatonStopDismissing();
         setSwipingInProgress(false);
     }
 
@@ -1915,7 +1926,9 @@
             boolean onBottom = false;
             boolean pinnedAndClosed = row.isPinned() && !mIsExpanded;
             if (!mIsExpanded && !isHeadsUp) {
-                type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
+                type = row.wasJustClicked()
+                        ? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+                        : AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
             } else {
                 StackViewState viewState = mCurrentStackScrollState.getViewStateForView(row);
                 if (viewState == null) {
@@ -3016,6 +3029,15 @@
                         .animateY()
                         .animateZ(),
 
+                // ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+                new AnimationFilter()
+                        .animateAlpha()
+                        .animateHeight()
+                        .animateTopInset()
+                        .animateY()
+                        .animateZ()
+                        .hasDelays(),
+
                 // ANIMATION_TYPE_HEADS_UP_OTHER
                 new AnimationFilter()
                         .animateAlpha()
@@ -3087,6 +3109,9 @@
                 // ANIMATION_TYPE_HEADS_UP_DISAPPEAR
                 StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
 
+                // ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+                StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR,
+
                 // ANIMATION_TYPE_HEADS_UP_OTHER
                 StackStateAnimator.ANIMATION_DURATION_STANDARD,
 
@@ -3110,8 +3135,9 @@
         static final int ANIMATION_TYPE_GROUP_EXPANSION_CHANGED = 13;
         static final int ANIMATION_TYPE_HEADS_UP_APPEAR = 14;
         static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR = 15;
-        static final int ANIMATION_TYPE_HEADS_UP_OTHER = 16;
-        static final int ANIMATION_TYPE_EVERYTHING = 17;
+        static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK = 16;
+        static final int ANIMATION_TYPE_HEADS_UP_OTHER = 17;
+        static final int ANIMATION_TYPE_EVERYTHING = 18;
 
         static final int DARK_ANIMATION_ORIGIN_INDEX_ABOVE = -1;
         static final int DARK_ANIMATION_ORIGIN_INDEX_BELOW = -2;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 82064a7..cf696a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -127,7 +127,7 @@
         mCollapseSecondCardPadding = context.getResources().getDimensionPixelSize(
                 R.dimen.notification_collapse_second_card_padding);
         mScaleDimmed = context.getResources().getDisplayMetrics().densityDpi
-                >= DisplayMetrics.DENSITY_XXHIGH;
+                >= DisplayMetrics.DENSITY_420;
     }
 
     public boolean shouldScaleDimmed() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 97c7d30..b4ab48a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -54,6 +54,7 @@
     public static final int ANIMATION_DELAY_PER_ELEMENT_DARK = 24;
     public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
     public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE_CHILDREN = 3;
+    public static final int ANIMATION_DELAY_HEADS_UP = 120;
 
     private static final int TAG_ANIMATOR_TRANSLATION_Y = R.id.translation_y_animator_tag;
     private static final int TAG_ANIMATOR_TRANSLATION_Z = R.id.translation_z_animator_tag;
@@ -320,6 +321,9 @@
         if (mAnimationFilter.hasGoToFullShadeEvent) {
             return calculateDelayGoToFullShade(viewState);
         }
+        if (mAnimationFilter.hasHeadsUpDisappearClickEvent) {
+            return ANIMATION_DELAY_HEADS_UP;
+        }
         long minDelay = 0;
         for (NotificationStackScrollLayout.AnimationEvent event : mNewEvents) {
             long delayPerElement = ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING;
@@ -890,7 +894,9 @@
                 mHeadsUpAppearChildren.add(changingView);
                 finalState.applyState(changingView, mTmpState);
             } else if (event.animationType == NotificationStackScrollLayout
-                    .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR) {
+                            .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR ||
+                    event.animationType == NotificationStackScrollLayout
+                            .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
                 mHeadsUpDisappearChildren.add(changingView);
                 if (mHostLayout.indexOfChild(changingView) == -1) {
                     // This notification was actually removed, so we need to add it to the overlay
@@ -900,7 +906,11 @@
                     // We temporarily enable Y animations, the real filter will be combined
                     // afterwards anyway
                     mAnimationFilter.animateY = true;
-                    startViewAnimations(changingView, mTmpState, 0,
+                    startViewAnimations(changingView, mTmpState,
+                            event.animationType == NotificationStackScrollLayout
+                                    .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
+                                            ? ANIMATION_DELAY_HEADS_UP
+                                            : 0,
                             ANIMATION_DURATION_HEADS_UP_DISAPPEAR);
                     mChildrenToClearFromOverlay.add(changingView);
                 }
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/Android.mk b/packages/SystemUI/tests/Android.mk
index 6a7201c..d6d17cb 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -17,9 +17,14 @@
 
 LOCAL_MODULE_TAGS := tests
 
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_PROTOC_FLAGS := -I$(LOCAL_PATH)/..
+LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
+
 LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages com.android.systemui:com.android.keyguard
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     $(call all-java-files-under, ../src) \
+    $(call all-proto-files-under, ../src) \
     src/com/android/systemui/EventLogTags.logtags
 
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
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/MountService.java b/services/core/java/com/android/server/MountService.java
index 0d64540..72cece3 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -165,6 +165,8 @@
         public void onBootPhase(int phase) {
             if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                 mMountService.systemReady();
+            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+                mMountService.bootCompleted();
             }
         }
 
@@ -405,6 +407,7 @@
     private final NativeDaemonConnector mCryptConnector;
 
     private volatile boolean mSystemReady = false;
+    private volatile boolean mBootCompleted = false;
     private volatile boolean mDaemonConnected = false;
 
     private PackageManagerService mPms;
@@ -1244,7 +1247,9 @@
 
         mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
 
-        if (isBroadcastWorthy(vol)) {
+        // Do not broadcast before boot has completed to avoid launching the
+        // processes that receive the intent unnecessarily.
+        if (mBootCompleted && isBroadcastWorthy(vol)) {
             final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
             intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
             intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
@@ -1429,6 +1434,10 @@
         mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
     }
 
+    private void bootCompleted() {
+        mBootCompleted = true;
+    }
+
     private String getDefaultPrimaryStorageUuid() {
         if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) {
             return StorageManager.UUID_PRIMARY_PHYSICAL;
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..965f5b6 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, info.initialLayout);
+        }
         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..5c4fd13
--- /dev/null
+++ b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
@@ -0,0 +1,303 @@
+/*
+ * 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 static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.annotation.Nullable;
+import android.content.pm.ActivityInfo;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.Slog;
+import android.view.Display;
+import android.view.Gravity;
+
+import java.util.ArrayList;
+
+/**
+ * Determines where a launching task should be positioned and sized on the display.
+ *
+ * The positioner is fairly simple. For the new task it tries default position based on the gravity
+ * and compares corners of the task with corners of existing tasks. If some two pairs of corners are
+ * sufficiently close enough, it shifts the bounds of the new task and tries again. When it exhausts
+ * all possible shifts, it gives up and puts the task in the original position.
+ */
+class LaunchingTaskPositioner {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "LaunchingTaskPositioner" : TAG_AM;
+
+    // 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;
+
+    // Used to indicate if positioning algorithm is allowed to restart from the beginning, when it
+    // reaches the end of stack bounds.
+    private static final boolean ALLOW_RESTART = true;
+
+    private static final int SHIFT_POLICY_DIAGONAL_DOWN = 1;
+    private static final int SHIFT_POLICY_HORIZONTAL_RIGHT = 2;
+    private static final int SHIFT_POLICY_HORIZONTAL_LEFT = 3;
+
+    private boolean mDefaultStartBoundsConfigurationSet = false;
+    private final Rect mAvailableRect = new Rect();
+    private final Rect mTmpProposal = new Rect();
+    private final Rect mTmpOriginal = 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.
+     * @param initialLayout Optional information from the client about how it would like to be sized
+     *                      and positioned.
+     */
+    void updateDefaultBounds(TaskRecord task, ArrayList<TaskRecord> tasks,
+            @Nullable ActivityInfo.InitialLayout initialLayout) {
+        if (!mDefaultStartBoundsConfigurationSet) {
+            return;
+        }
+        if (initialLayout == null) {
+            positionCenter(task, tasks, mDefaultFreeformWidth, mDefaultFreeformHeight);
+            return;
+        }
+        int width = getFinalWidth(initialLayout);
+        int height = getFinalHeight(initialLayout);
+        int verticalGravity = initialLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
+        int horizontalGravity = initialLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+        if (verticalGravity == Gravity.TOP) {
+            if (horizontalGravity == Gravity.RIGHT) {
+                positionTopRight(task, tasks, width, height);
+            } else {
+                positionTopLeft(task, tasks, width, height);
+            }
+        } else if (verticalGravity == Gravity.BOTTOM) {
+            if (horizontalGravity == Gravity.RIGHT) {
+                positionBottomRight(task, tasks, width, height);
+            } else {
+                positionBottomLeft(task, tasks, width, height);
+            }
+        } else {
+            // Some fancy gravity setting that we don't support yet. We just put the activity in the
+            // center.
+            Slog.w(TAG, "Received unsupported gravity: " + initialLayout.gravity
+                    + ", positioning in the center instead.");
+            positionCenter(task, tasks, width, height);
+        }
+    }
+
+    private int getFinalWidth(ActivityInfo.InitialLayout initialLayout) {
+        int width = mDefaultFreeformWidth;
+        if (initialLayout.width > 0) {
+            width = initialLayout.width;
+        }
+        if (initialLayout.widthFraction > 0) {
+            width = (int) (mAvailableRect.width() * initialLayout.widthFraction);
+        }
+        return width;
+    }
+
+    private int getFinalHeight(ActivityInfo.InitialLayout initialLayout) {
+        int height = mDefaultFreeformHeight;
+        if (initialLayout.height > 0) {
+            height = initialLayout.height;
+        }
+        if (initialLayout.heightFraction > 0) {
+            height = (int) (mAvailableRect.height() * initialLayout.heightFraction);
+        }
+        return height;
+    }
+
+    private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+            int height) {
+        mTmpProposal.set(mAvailableRect.left, mAvailableRect.bottom - height,
+                mAvailableRect.left + width, mAvailableRect.bottom);
+        position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT);
+    }
+
+    private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+            int height) {
+        mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.bottom - height,
+                mAvailableRect.right, mAvailableRect.bottom);
+        position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT);
+    }
+
+    private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+            int height) {
+        mTmpProposal.set(mAvailableRect.left, mAvailableRect.top,
+                mAvailableRect.left + width, mAvailableRect.top + height);
+        position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT);
+    }
+
+    private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+            int height) {
+        mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.top,
+                mAvailableRect.right, mAvailableRect.top + height);
+        position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT);
+    }
+
+    private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+            int height) {
+        mTmpProposal.set(mDefaultFreeformStartX, mDefaultFreeformStartY,
+                mDefaultFreeformStartX + width, mDefaultFreeformStartY + height);
+        position(task, tasks, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN);
+    }
+
+    private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect proposal,
+            boolean allowRestart, int shiftPolicy) {
+        mTmpOriginal.set(proposal);
+        boolean restarted = false;
+        while (boundsConflict(proposal, tasks)) {
+            // Unfortunately there is already a task at that spot, so we need to look for some
+            // other place.
+            shiftStartingPoint(proposal, shiftPolicy);
+            if (shiftedToFar(proposal, shiftPolicy)) {
+                // We don't want the task to go outside of the stack, because it won't look
+                // nice. Depending on the starting point we either restart, or immediately give up.
+                if (!allowRestart) {
+                    proposal.set(mTmpOriginal);
+                    break;
+                }
+                // We must have started not from the top. Let's restart from there because there
+                // might be some space there.
+                proposal.set(mAvailableRect.left, mAvailableRect.top,
+                        mAvailableRect.left + proposal.width(),
+                        mAvailableRect.top + proposal.height());
+                restarted = true;
+            }
+            if (restarted && (proposal.left > mDefaultFreeformStartX
+                    || proposal.top > 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.
+                proposal.set(mTmpOriginal);
+                break;
+            }
+        }
+        task.setInitialBounds(proposal);
+    }
+
+    private boolean shiftedToFar(Rect start, int shiftPolicy) {
+        switch (shiftPolicy) {
+            case SHIFT_POLICY_HORIZONTAL_LEFT:
+                return start.left < mAvailableRect.left;
+            case SHIFT_POLICY_HORIZONTAL_RIGHT:
+                return start.right > mAvailableRect.right;
+            default: // SHIFT_POLICY_DIAGONAL_DOWN
+                return start.right > mAvailableRect.right || start.bottom > mAvailableRect.bottom;
+        }
+    }
+
+    private void shiftStartingPoint(Rect posposal, int shiftPolicy) {
+        switch (shiftPolicy) {
+            case SHIFT_POLICY_HORIZONTAL_LEFT:
+                posposal.offset(-mDefaultFreeformStepHorizontal, 0);
+                break;
+            case SHIFT_POLICY_HORIZONTAL_RIGHT:
+                posposal.offset(mDefaultFreeformStepHorizontal, 0);
+                break;
+            default: // SHIFT_POLICY_DIAGONAL_DOWN:
+                posposal.offset(mDefaultFreeformStepHorizontal, mDefaultFreeformStepVertical);
+                break;
+        }
+    }
+
+    private static boolean boundsConflict(Rect proposal, ArrayList<TaskRecord> tasks) {
+        for (int i = tasks.size() - 1; i >= 0; i--) {
+            TaskRecord task = tasks.get(i);
+            if (!task.mActivities.isEmpty() && task.mBounds != null) {
+                Rect bounds = task.mBounds;
+                if (closeLeftTopCorner(proposal, bounds) || closeRightTopCorner(proposal, bounds)
+                        || closeLeftBottomCorner(proposal, bounds)
+                        || closeRightBottomCorner(proposal, bounds)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static final boolean closeLeftTopCorner(Rect first, Rect second) {
+        return Math.abs(first.left - second.left) < BOUNDS_CONFLICT_MIN_DISTANCE
+                && Math.abs(first.top - second.top) < BOUNDS_CONFLICT_MIN_DISTANCE;
+    }
+
+    private static final boolean closeRightTopCorner(Rect first, Rect second) {
+        return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
+                && Math.abs(first.top - second.top) < BOUNDS_CONFLICT_MIN_DISTANCE;
+    }
+
+    private static final boolean closeLeftBottomCorner(Rect first, Rect second) {
+        return Math.abs(first.left - second.left) < BOUNDS_CONFLICT_MIN_DISTANCE
+                && Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
+    }
+
+    private static final boolean closeRightBottomCorner(Rect first, Rect second) {
+        return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
+                && Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
+    }
+
+    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..712b8cc 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(Rect rect) {
+        if (mBounds == null) {
+            mBounds = new Rect();
+        }
+        mBounds.set(rect);
+        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/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java
index 0be24f4..f82454a 100644
--- a/services/core/java/com/android/server/camera/CameraService.java
+++ b/services/core/java/com/android/server/camera/CameraService.java
@@ -23,13 +23,17 @@
 import android.content.pm.UserInfo;
 import android.hardware.ICameraService;
 import android.hardware.ICameraServiceProxy;
+import android.nfc.INfcAdapter;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Binder;
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserManager;
+import android.os.SystemProperties;
 import android.util.Slog;
+import android.util.ArraySet;
 
 import com.android.server.ServiceThread;
 import com.android.server.SystemService;
@@ -44,8 +48,10 @@
  *
  * @hide
  */
-public class CameraService extends SystemService implements Handler.Callback {
+public class CameraService extends SystemService
+        implements Handler.Callback, IBinder.DeathRecipient {
     private static final String TAG = "CameraService_proxy";
+    private static final boolean DEBUG = false;
 
     /**
      * This must match the ICameraService.aidl definition
@@ -58,6 +64,16 @@
     public static final int NO_EVENT = 0; // NOOP
     public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle
 
+    // State arguments to use with the notifyCameraState call from camera service:
+    public static final int CAMERA_STATE_OPEN = 0;
+    public static final int CAMERA_STATE_ACTIVE = 1;
+    public static final int CAMERA_STATE_IDLE = 2;
+    public static final int CAMERA_STATE_CLOSED = 3;
+
+    // Flags arguments to NFC adapter to enable/disable NFC
+    public static final int DISABLE_POLLING_FLAGS = 0x1000;
+    public static final int ENABLE_POLLING_FLAGS = 0x0000;
+
     // Handler message codes
     private static final int MSG_SWITCH_USER = 1;
 
@@ -72,6 +88,17 @@
     private Set<Integer> mEnabledCameraUsers;
     private int mLastUser;
 
+    private ICameraService mCameraServiceRaw;
+
+    private final ArraySet<String> mActiveCameraIds = new ArraySet<>();
+
+    private static final String NFC_NOTIFICATION_PROP = "ro.camera.notify_nfc";
+    private static final String NFC_SERVICE_BINDER_NAME = "nfc";
+    private static final IBinder nfcInterfaceToken = new Binder();
+
+    private final boolean mNotifyNfc;
+    private int mActiveCameraCount = 0;
+
     private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -102,6 +129,14 @@
         public void pingForUserUpdate() {
             notifySwitchWithRetries(30);
         }
+
+        @Override
+        public void notifyCameraState(String cameraId, int newCameraState) {
+            String state = cameraStateToString(newCameraState);
+            if (DEBUG) Slog.v(TAG, "Camera " + cameraId + " state now " + state);
+
+            updateActivityCount(cameraId, newCameraState);
+        }
     };
 
     public CameraService(Context context) {
@@ -110,6 +145,9 @@
         mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, /*allowTo*/false);
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper(), this);
+
+        mNotifyNfc = SystemProperties.getInt(NFC_NOTIFICATION_PROP, 0) > 0;
+        if (DEBUG) Slog.v(TAG, "Notify NFC behavior is " + (mNotifyNfc ? "active" : "disabled"));
     }
 
     @Override
@@ -161,13 +199,32 @@
         }
     }
 
+    /**
+     * Handle the death of the native camera service
+     */
+    @Override
+    public void binderDied() {
+        if (DEBUG) Slog.w(TAG, "Native camera service has died");
+        synchronized(mLock) {
+            mCameraServiceRaw = null;
+
+            // All cameras reset to idle on camera service death
+            boolean wasEmpty = mActiveCameraIds.isEmpty();
+            mActiveCameraIds.clear();
+
+            if ( mNotifyNfc && !wasEmpty ) {
+                notifyNfcService(/*enablePolling*/ true);
+            }
+        }
+    }
+
     private void switchUserLocked(int userHandle) {
         Set<Integer> currentUserHandles = getEnabledUserHandles(userHandle);
         mLastUser = userHandle;
         if (mEnabledCameraUsers == null || !mEnabledCameraUsers.equals(currentUserHandles)) {
             // Some user handles have been added or removed, update mediaserver.
             mEnabledCameraUsers = currentUserHandles;
-            notifyMediaserver(USER_SWITCHED, currentUserHandles);
+            notifyMediaserverLocked(USER_SWITCHED, currentUserHandles);
         }
     }
 
@@ -187,7 +244,7 @@
             if (mEnabledCameraUsers == null) {
                 return;
             }
-            if (notifyMediaserver(USER_SWITCHED, mEnabledCameraUsers)) {
+            if (notifyMediaserverLocked(USER_SWITCHED, mEnabledCameraUsers)) {
                 retries = 0;
             }
         }
@@ -199,19 +256,27 @@
                 RETRY_DELAY_TIME);
     }
 
-    private boolean notifyMediaserver(int eventType, Set<Integer> updatedUserHandles) {
+    private boolean notifyMediaserverLocked(int eventType, Set<Integer> updatedUserHandles) {
         // Forward the user switch event to the native camera service running in the mediaserver
         // process.
-        IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
-        if (cameraServiceBinder == null) {
-            Slog.w(TAG, "Could not notify mediaserver, camera service not available.");
-            return false; // Camera service not active, cannot evict user clients.
+        if (mCameraServiceRaw == null) {
+            IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
+            if (cameraServiceBinder == null) {
+                Slog.w(TAG, "Could not notify mediaserver, camera service not available.");
+                return false; // Camera service not active, cannot evict user clients.
+            }
+            try {
+                cameraServiceBinder.linkToDeath(this, /*flags*/ 0);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Could not link to death of native camera service");
+                return false;
+            }
+
+            mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
         }
 
-        ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
-
         try {
-            cameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles));
+            mCameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles));
         } catch (RemoteException e) {
             Slog.w(TAG, "Could not notify mediaserver, remote exception: " + e);
             // Not much we can do if camera service is dead.
@@ -220,6 +285,44 @@
         return true;
     }
 
+    private void updateActivityCount(String cameraId, int newCameraState) {
+        synchronized(mLock) {
+            boolean wasEmpty = mActiveCameraIds.isEmpty();
+            switch (newCameraState) {
+                case CAMERA_STATE_OPEN:
+                    break;
+                case CAMERA_STATE_ACTIVE:
+                    mActiveCameraIds.add(cameraId);
+                    break;
+                case CAMERA_STATE_IDLE:
+                case CAMERA_STATE_CLOSED:
+                    mActiveCameraIds.remove(cameraId);
+                    break;
+            }
+            boolean isEmpty = mActiveCameraIds.isEmpty();
+            if ( mNotifyNfc && (wasEmpty != isEmpty) ) {
+                notifyNfcService(isEmpty);
+            }
+        }
+    }
+
+    private void notifyNfcService(boolean enablePolling) {
+
+        IBinder nfcServiceBinder = getBinderService(NFC_SERVICE_BINDER_NAME);
+        if (nfcServiceBinder == null) {
+            Slog.w(TAG, "Could not connect to NFC service to notify it of camera state");
+            return;
+        }
+        INfcAdapter nfcAdapterRaw = INfcAdapter.Stub.asInterface(nfcServiceBinder);
+        int flags = enablePolling ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS;
+        if (DEBUG) Slog.v(TAG, "Setting NFC reader mode to flags " + flags);
+        try {
+            nfcAdapterRaw.setReaderMode(nfcInterfaceToken, null, flags, null);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Could not notify NFC service, remote exception: " + e);
+        }
+    }
+
     private static int[] toArray(Collection<Integer> c) {
         int len = c.size();
         int[] ret = new int[len];
@@ -229,4 +332,15 @@
         }
         return ret;
     }
+
+    private static String cameraStateToString(int newCameraState) {
+        switch (newCameraState) {
+            case CAMERA_STATE_OPEN: return "CAMERA_STATE_OPEN";
+            case CAMERA_STATE_ACTIVE: return "CAMERA_STATE_ACTIVE";
+            case CAMERA_STATE_IDLE: return "CAMERA_STATE_IDLE";
+            case CAMERA_STATE_CLOSED: return "CAMERA_STATE_CLOSED";
+            default: break;
+        }
+        return "CAMERA_STATE_UNKNOWN";
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 2846185..3df3cd0 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -146,7 +146,8 @@
         } catch (RemoteException e) {
             Log.wtf(TAG, "Problem registering observer", e);
         }
-        if (userHandle == UserHandle.USER_OWNER) {
+        // TODO: http://b/22950929
+        if (userHandle == UserHandle.USER_SYSTEM) {
             // Owner's VPN also needs to handle restricted users
             mUserIntentReceiver = new BroadcastReceiver() {
                 @Override
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index befa311..932662f 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -764,6 +764,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
+                    MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
                     startAuthentication(token, opId, effectiveGroupId, receiver, flags, restricted);
                 }
             });
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 57ca552..5c60a61 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -2200,14 +2200,18 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         StringBuilder s = new StringBuilder();
-        s.append("  mFixInterval=").append(mFixInterval).append("\n");
-        s.append("  mDisableGps (battery saver mode)=").append(mDisableGps).append("\n");
-        s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
-        if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
+        s.append("  mFixInterval=").append(mFixInterval).append('\n');
+        s.append("  mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
+        s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
+        s.append(" ( ");
+        if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");
         if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
         if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
         if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
         if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
+        if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING ");
+        if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS ");
+        if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES ");
         s.append(")\n");
 
         s.append(native_get_internal_state());
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..f5f494a 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;
@@ -4644,7 +4644,7 @@
             if (result == null) {
                 result = new CrossProfileDomainInfo();
                 result.resolveInfo =
-                        createForwardingResolveInfo(null, sourceUserId, parentUserId);
+                        createForwardingResolveInfo(new IntentFilter(), sourceUserId, parentUserId);
                 result.bestDomainVerificationStatus = status;
             } else {
                 result.bestDomainVerificationStatus = bestDomainVerificationStatus(status,
@@ -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 fe205e5..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;
 
@@ -627,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;
@@ -636,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();
@@ -1238,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);
     }
 
@@ -1273,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 da23f45..b935f5a 100644
--- a/services/core/java/com/android/server/policy/StatusBarController.java
+++ b/services/core/java/com/android/server/policy/StatusBarController.java
@@ -72,7 +72,9 @@
                         if (statusbar != null) {
                             long startTime = calculateStatusBarTransitionStartTime(openAnimation,
                                     closeAnimation);
-                            statusbar.appTransitionStarting(startTime, TRANSITION_DURATION);
+                            long duration = closeAnimation != null || openAnimation != null
+                                    ? TRANSITION_DURATION : 0;
+                            statusbar.appTransitionStarting(startTime, duration);
                         }
                     } catch (RemoteException e) {
                         Slog.e(mTag, "RemoteException when app transition is starting", e);
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/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 946043a..7b4c2a0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -114,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;
@@ -177,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;
@@ -581,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;
@@ -636,6 +598,7 @@
     final InputManagerService mInputManager;
     final DisplayManagerInternal mDisplayManagerInternal;
     final DisplayManager mDisplayManager;
+    final Display[] mDisplays;
 
     // Who is holding the screen on.
     Session mHoldingScreenOn;
@@ -806,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();
@@ -909,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);
         }
 
@@ -990,6 +953,8 @@
 
         updateCircularDisplayMaskIfNeeded();
         showEmulatorDisplayOverlayIfNeeded();
+
+        mWallpaperControllerLocked = new WallpaperController(this);
     }
 
     public InputMonitor getInputMonitor() {
@@ -1769,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,
@@ -2563,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.
@@ -2865,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) {
@@ -2985,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) {
@@ -3295,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.
@@ -3353,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();
@@ -3632,7 +2968,7 @@
             wtoken = new WindowToken(this, token, type, true);
             mTokenMap.put(token, wtoken);
             if (type == TYPE_WALLPAPER) {
-                mWallpaperTokens.add(wtoken);
+                mWallpaperControllerLocked.addWallpaperToken(wtoken);
             }
         }
     }
@@ -3688,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*/);
@@ -4438,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
@@ -5864,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) {
@@ -5886,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!");
 
@@ -6297,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();
@@ -7667,7 +7005,9 @@
     }
 
     public void displayReady() {
-        displayReady(Display.DEFAULT_DISPLAY);
+        for (Display display : mDisplays) {
+            displayReady(display.getDisplayId());
+        }
 
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDefaultDisplayContentLocked();
@@ -8293,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();
                         }
                     }
@@ -8919,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;
@@ -9220,338 +8557,322 @@
      * @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();
-
-            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;
-            }
-
-            // 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();
-                }
-            }
-
-            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.
-            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();
-        }
-
-        return changes;
+        return true;
     }
 
     private void createThumbnailAppAnimator(int transit, AppWindowToken appToken,
@@ -9646,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();
@@ -9970,7 +9288,7 @@
 
                     if ((displayContent.pendingLayoutChanges &
                             WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
-                            adjustWallpaperWindowsLocked()) {
+                            mWallpaperControllerLocked.adjustWallpaperWindows()) {
                         assignLayersLocked(windows);
                         displayContent.layoutNeeded = true;
                     }
@@ -10042,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;
@@ -10296,7 +9614,7 @@
                 if (mInputMethodWindow == win) {
                     mInputMethodWindow = null;
                 }
-                if (win == mWallpaperTarget) {
+                if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
                     wallpaperDestroyed = true;
                 }
                 win.mWinAnimator.destroySurfaceLocked();
@@ -10313,7 +9631,7 @@
                 if (!token.hasVisible) {
                     exitingTokens.remove(i);
                     if (token.windowType == TYPE_WALLPAPER) {
-                        mWallpaperTokens.remove(token);
+                        mWallpaperControllerLocked.removeWallpaperToken(token);
                     }
                 }
             }
@@ -10460,8 +9778,8 @@
                     ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
                     " mHasSurface=" + win.mHasSurface +
                     " drawState=" + win.mWinAnimator.mDrawState);
-            if (win.mRemoved || !win.mHasSurface) {
-                // Window has been removed; no draw will now happen, so stop waiting.
+            if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
+                // Window has been removed or hidden; no draw will now happen, so stop waiting.
                 if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win);
                 mWaitingForDrawn.remove(win);
             } else if (win.hasDrawnLw()) {
@@ -11220,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:");
@@ -11434,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);
@@ -12007,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..109e627 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
@@ -1589,8 +1590,6 @@
         final int left = ((int) shownFrame.left) - attrs.surfaceInsets.left;
         final int top = ((int) shownFrame.top) - attrs.surfaceInsets.top;
         if (mSurfaceX != left || mSurfaceY != top) {
-            mSurfaceX = left;
-            mSurfaceY = top;
             if (mAnimating) {
                 // If this window (or its app token) is animating, then the position
                 // of the surface will be re-computed on the next animation frame.
@@ -1598,6 +1597,8 @@
                 // transformation is being applied by the animation.
                 return;
             }
+            mSurfaceX = left;
+            mSurfaceY = top;
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
             SurfaceControl.openTransaction();
             try {
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/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 2d47c24..86f5ed7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -38,7 +38,8 @@
 
     @Override
     public void setUp() throws Exception {
-        mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+        super.setUp();
+        mUserManager = UserManager.get(getContext());
         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
         getContext().registerReceiver(new BroadcastReceiver() {
             @Override
@@ -64,14 +65,18 @@
     private void removeExistingUsers() {
         List<UserInfo> list = mUserManager.getUsers();
         for (UserInfo user : list) {
-            if (user.id != UserHandle.USER_OWNER) {
+            // Keep system and primary user.
+            // We do not have to keep primary user, but in split system user mode, we need it
+            // until http://b/22976637 is fixed.  Right now in split system user mode, you need to
+            // switch to primary user and run tests under primary user.
+            if (user.id != UserHandle.USER_SYSTEM && !user.isPrimary()) {
                 removeUser(user.id);
             }
         }
     }
 
-    public void testHasPrimary() throws Exception {
-        assertTrue(findUser(0));
+    public void testHasSystemUser() throws Exception {
+        assertTrue(findUser(UserHandle.USER_SYSTEM));
     }
 
     public void testAddUser() throws Exception {
@@ -122,10 +127,11 @@
 
     // Make sure only one managed profile can be created
     public void testAddManagedProfile() throws Exception {
+        final int primaryUserId = mUserManager.getPrimaryUser().id;
         UserInfo userInfo1 = createProfileForUser("Managed 1",
-                UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
+                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
         UserInfo userInfo2 = createProfileForUser("Managed 2",
-                UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
+                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
         assertNotNull(userInfo1);
         assertNull(userInfo2);
         // Verify that current user is not a managed profile
@@ -133,17 +139,18 @@
     }
 
     public void testGetUserCreationTime() throws Exception {
+        final int primaryUserId = mUserManager.getPrimaryUser().id;
         UserInfo profile = createProfileForUser("Managed 1",
-                UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
+                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
         assertNotNull(profile);
         assertTrue("creationTime must be set when the profile is created",
                 profile.creationTime > 0);
         assertEquals(profile.creationTime, mUserManager.getUserCreationTime(
                 new UserHandle(profile.id)));
 
-        long ownerCreationTime = mUserManager.getUserInfo(UserHandle.USER_OWNER).creationTime;
+        long ownerCreationTime = mUserManager.getUserInfo(primaryUserId).creationTime;
         assertEquals(ownerCreationTime, mUserManager.getUserCreationTime(
-                new UserHandle(UserHandle.USER_OWNER)));
+                new UserHandle(primaryUserId)));
 
         try {
             int noSuchUserId = 100500;
@@ -177,11 +184,11 @@
     }
 
     public void testSerialNumber() {
-        UserInfo user1 = createUser("User 1", UserInfo.FLAG_RESTRICTED);
+        UserInfo user1 = createUser("User 1", 0);
         int serialNumber1 = user1.serialNumber;
         assertEquals(serialNumber1, mUserManager.getUserSerialNumber(user1.id));
         assertEquals(user1.id, mUserManager.getUserHandle(serialNumber1));
-        UserInfo user2 = createUser("User 2", UserInfo.FLAG_RESTRICTED);
+        UserInfo user2 = createUser("User 2", 0);
         int serialNumber2 = user2.serialNumber;
         assertFalse(serialNumber1 == serialNumber2);
         assertEquals(serialNumber2, mUserManager.getUserSerialNumber(user2.id));
@@ -203,17 +210,15 @@
     }
 
     public void testRestrictions() {
-        List<UserInfo> users = mUserManager.getUsers();
-        if (users.size() > 1) {
-            Bundle restrictions = new Bundle();
-            restrictions.putBoolean(UserManager.DISALLOW_INSTALL_APPS, true);
-            restrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, false);
-            mUserManager.setUserRestrictions(restrictions, new UserHandle(users.get(1).id));
-            Bundle stored = mUserManager.getUserRestrictions(new UserHandle(users.get(1).id));
-            assertEquals(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI), false);
-            assertEquals(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS), false);
-            assertEquals(stored.getBoolean(UserManager.DISALLOW_INSTALL_APPS), true);
-        }
+        UserInfo testUser = createUser("User 1", 0);
+        Bundle restrictions = new Bundle();
+        restrictions.putBoolean(UserManager.DISALLOW_INSTALL_APPS, true);
+        restrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, false);
+        mUserManager.setUserRestrictions(restrictions, new UserHandle(testUser.id));
+        Bundle stored = mUserManager.getUserRestrictions(new UserHandle(testUser.id));
+        assertEquals(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI), false);
+        assertEquals(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS), false);
+        assertEquals(stored.getBoolean(UserManager.DISALLOW_INSTALL_APPS), true);
     }
 
     private void removeUser(int userId) {
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);