Merge "Fix issue #25673462: Shamu update from MMB29J -> 29K does not complete"
diff --git a/api/current.txt b/api/current.txt
index cca8293..6208640 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4795,7 +4795,7 @@
     method public android.graphics.drawable.Icon getLargeIcon();
     method public android.graphics.drawable.Icon getSmallIcon();
     method public java.lang.String getSortKey();
-    method public android.app.Notification.Topic[] getTopics();
+    method public android.app.Notification.Topic getTopic();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
     field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -4960,7 +4960,6 @@
     method public android.app.Notification.Builder addAction(android.app.Notification.Action);
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
-    method public android.app.Notification.Builder addTopic(android.app.Notification.Topic);
     method public android.app.Notification build();
     method public android.app.Notification.Builder extend(android.app.Notification.Extender);
     method public android.os.Bundle getExtras();
@@ -5009,6 +5008,7 @@
     method public android.app.Notification.Builder setSubText(java.lang.CharSequence);
     method public android.app.Notification.Builder setTicker(java.lang.CharSequence);
     method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
+    method public android.app.Notification.Builder setTopic(android.app.Notification.Topic);
     method public android.app.Notification.Builder setUsesChronometer(boolean);
     method public android.app.Notification.Builder setVibrate(long[]);
     method public android.app.Notification.Builder setVisibility(int);
@@ -5166,10 +5166,12 @@
   }
 
   public static class NotificationManager.Policy implements android.os.Parcelable {
-    ctor public NotificationManager.Policy(int, int, int);
+    ctor public deprecated NotificationManager.Policy(int, int, int);
+    ctor public NotificationManager.Policy(int, int, int, int);
     method public int describeContents();
     method public static java.lang.String priorityCategoriesToString(int);
     method public static java.lang.String prioritySendersToString(int);
+    method public static java.lang.String suppressedEffectsToString(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.NotificationManager.Policy> CREATOR;
     field public static final int PRIORITY_CATEGORY_CALLS = 8; // 0x8
@@ -5180,9 +5182,13 @@
     field public static final int PRIORITY_SENDERS_ANY = 0; // 0x0
     field public static final int PRIORITY_SENDERS_CONTACTS = 1; // 0x1
     field public static final int PRIORITY_SENDERS_STARRED = 2; // 0x2
+    field public static final int SUPPRESSED_EFFECTS_UNSET = -1; // 0xffffffff
+    field public static final int SUPPRESSED_EFFECT_LIGHTS = 1; // 0x1
+    field public static final int SUPPRESSED_EFFECT_PEEK = 2; // 0x2
     field public final int priorityCallSenders;
     field public final int priorityCategories;
     field public final int priorityMessageSenders;
+    field public final int suppressedVisualEffects;
   }
 
   public final class PendingIntent implements android.os.Parcelable {
@@ -28994,12 +29000,15 @@
     field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
     field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
+    field public static final int SUPPRESSED_EFFECT_LIGHTS = 1; // 0x1
+    field public static final int SUPPRESSED_EFFECT_PEEK = 2; // 0x2
   }
 
   public static class NotificationListenerService.Ranking {
     ctor public NotificationListenerService.Ranking();
     method public java.lang.String getKey();
     method public int getRank();
+    method public int getSuppressedVisualEffects();
     method public boolean isAmbient();
     method public boolean matchesInterruptionFilter();
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 3946d4a..fc11f34 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4913,7 +4913,7 @@
     method public android.graphics.drawable.Icon getLargeIcon();
     method public android.graphics.drawable.Icon getSmallIcon();
     method public java.lang.String getSortKey();
-    method public android.app.Notification.Topic[] getTopics();
+    method public android.app.Notification.Topic getTopic();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
     field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -5078,7 +5078,6 @@
     method public android.app.Notification.Builder addAction(android.app.Notification.Action);
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
-    method public android.app.Notification.Builder addTopic(android.app.Notification.Topic);
     method public android.app.Notification build();
     method public android.app.Notification.Builder extend(android.app.Notification.Extender);
     method public android.os.Bundle getExtras();
@@ -5127,6 +5126,7 @@
     method public android.app.Notification.Builder setSubText(java.lang.CharSequence);
     method public android.app.Notification.Builder setTicker(java.lang.CharSequence);
     method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
+    method public android.app.Notification.Builder setTopic(android.app.Notification.Topic);
     method public android.app.Notification.Builder setUsesChronometer(boolean);
     method public android.app.Notification.Builder setVibrate(long[]);
     method public android.app.Notification.Builder setVisibility(int);
@@ -5284,10 +5284,12 @@
   }
 
   public static class NotificationManager.Policy implements android.os.Parcelable {
-    ctor public NotificationManager.Policy(int, int, int);
+    ctor public deprecated NotificationManager.Policy(int, int, int);
+    ctor public NotificationManager.Policy(int, int, int, int);
     method public int describeContents();
     method public static java.lang.String priorityCategoriesToString(int);
     method public static java.lang.String prioritySendersToString(int);
+    method public static java.lang.String suppressedEffectsToString(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.NotificationManager.Policy> CREATOR;
     field public static final int PRIORITY_CATEGORY_CALLS = 8; // 0x8
@@ -5298,9 +5300,13 @@
     field public static final int PRIORITY_SENDERS_ANY = 0; // 0x0
     field public static final int PRIORITY_SENDERS_CONTACTS = 1; // 0x1
     field public static final int PRIORITY_SENDERS_STARRED = 2; // 0x2
+    field public static final int SUPPRESSED_EFFECTS_UNSET = -1; // 0xffffffff
+    field public static final int SUPPRESSED_EFFECT_LIGHTS = 1; // 0x1
+    field public static final int SUPPRESSED_EFFECT_PEEK = 2; // 0x2
     field public final int priorityCallSenders;
     field public final int priorityCategories;
     field public final int priorityMessageSenders;
+    field public final int suppressedVisualEffects;
   }
 
   public final class PendingIntent implements android.os.Parcelable {
@@ -31113,6 +31119,8 @@
     field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
     field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
+    field public static final int SUPPRESSED_EFFECT_LIGHTS = 1; // 0x1
+    field public static final int SUPPRESSED_EFFECT_PEEK = 2; // 0x2
     field public static final int TRIM_FULL = 0; // 0x0
     field public static final int TRIM_LIGHT = 1; // 0x1
   }
@@ -31121,6 +31129,7 @@
     ctor public NotificationListenerService.Ranking();
     method public java.lang.String getKey();
     method public int getRank();
+    method public int getSuppressedVisualEffects();
     method public boolean isAmbient();
     method public boolean matchesInterruptionFilter();
   }
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 0745537..c0cc566 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -248,6 +248,7 @@
             } else if (mTransitioningViews != null) {
                 mTransitioningViews.addAll(mSharedElements);
             }
+            moveSharedElementsFromOverlay();
             mSharedElementNames.clear();
             mSharedElements.clear();
             mAllSharedElementNames.clear();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0b77be3..390c280 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1466,10 +1466,10 @@
                 };
     }
 
-    private Topic[] topics;
+    private Topic topic;
 
-    public Topic[] getTopics() {
-        return topics;
+    public Topic getTopic() {
+        return topic;
     }
 
     /**
@@ -1599,7 +1599,9 @@
 
         color = parcel.readInt();
 
-        topics = parcel.createTypedArray(Topic.CREATOR); // may be null
+        if (parcel.readInt() != 0) {
+            topic = Topic.CREATOR.createFromParcel(parcel);
+        }
     }
 
     @Override
@@ -1700,11 +1702,8 @@
 
         that.color = this.color;
 
-        if (this.topics != null) {
-            that.topics = new Topic[this.topics.length];
-            for(int i=0; i<this.topics.length; i++) {
-                that.topics[i] = this.topics[i].clone();
-            }
+        if (this.topic != null) {
+            that.topic = this.topic.clone();
         }
 
         if (!heavy) {
@@ -1878,7 +1877,12 @@
 
         parcel.writeInt(color);
 
-        parcel.writeTypedArray(topics, 0); // null ok
+        if (topic != null) {
+            parcel.writeInt(1);
+            topic.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
     }
 
     /**
@@ -2008,17 +2012,9 @@
             sb.append(" publicVersion=");
             sb.append(publicVersion.toString());
         }
-        if (topics != null) {
-            sb.append("topics=[");
-            int N = topics.length;
-            if (N > 0) {
-                for (int i = 0; i < N-1; i++) {
-                    sb.append(topics[i]);
-                    sb.append(',');
-                }
-                sb.append(topics[N-1]);
-            }
-            sb.append("]");
+        if (topic != null) {
+            sb.append("topic=");
+            sb.append(topic.toString());
         }
         sb.append(")");
         return sb.toString();
@@ -2136,7 +2132,6 @@
         private ArrayList<String> mPersonList = new ArrayList<String>();
         private NotificationColorUtil mColorUtil;
         private boolean mColorUtilInited = false;
-        private List<Topic> mTopics = new ArrayList<>();
 
         /**
          * The user that built the notification originally.
@@ -2187,10 +2182,6 @@
                     Collections.addAll(mPersonList, mN.extras.getStringArray(EXTRA_PEOPLE));
                 }
 
-                if (mN.getTopics() != null) {
-                    Collections.addAll(mTopics, mN.getTopics());
-                }
-
                 String templateClass = mN.extras.getString(EXTRA_TEMPLATE);
                 if (!TextUtils.isEmpty(templateClass)) {
                     final Class<? extends Style> styleClass
@@ -2962,15 +2953,15 @@
         }
 
         /**
-         * Add a topic to this notification. Topics are typically displayed in Notification
+         * Sets the topic of this notification. Topics are typically displayed in Notification
          * settings.
          * <p>
          * Every topic must have an id and a textual label.
          *
          * @param topic The topic to add.
          */
-        public Builder addTopic(Topic topic) {
-            mTopics.add(topic);
+        public Builder setTopic(Topic topic) {
+            mN.topic = topic;
             return this;
         }
 
@@ -3280,12 +3271,16 @@
          * Construct a RemoteViews for the final big notification layout.
          */
         public RemoteViews makeBigContentView() {
-            if (mStyle != null) {
+            if (mN.bigContentView != null) {
+                return mN.bigContentView;
+            } else if (mStyle != null) {
                 final RemoteViews styleView = mStyle.makeBigContentView();
                 if (styleView != null) {
                     return styleView;
                 }
-            } else if (mActions.size() == 0) return null;
+            } else if (mActions.size() == 0) {
+                return null;
+            }
 
             return applyStandardTemplateWithActions(getBigBaseLayoutResource());
         }
@@ -3294,12 +3289,17 @@
          * Construct a RemoteViews for the final heads-up notification layout.
          */
         public RemoteViews makeHeadsUpContentView() {
-            if (mStyle != null) {
-                final RemoteViews styleView = mStyle.makeHeadsUpContentView();
-                if (styleView != null) {
-                    return styleView;
-                }
-            } else if (mActions.size() == 0) return null;
+            if (mN.headsUpContentView != null) {
+                return mN.headsUpContentView;
+            } else if (mStyle != null) {
+                    final RemoteViews styleView = mStyle.makeHeadsUpContentView();
+                    if (styleView != null) {
+                        return styleView;
+                    }
+            } else if (mActions.size() == 0) {
+                return null;
+            }
+
 
             return applyStandardTemplateWithActions(getBigBaseLayoutResource());
         }
@@ -3452,10 +3452,6 @@
                 mN.extras.putStringArray(EXTRA_PEOPLE,
                         mPersonList.toArray(new String[mPersonList.size()]));
             }
-            if (mTopics.size() > 0) {
-                mN.topics = new Topic[mTopics.size()];
-                mTopics.toArray(mN.topics);
-            }
             return mN;
         }
 
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 07b4d39..043c503 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -610,15 +610,39 @@
          * PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED */
         public final int priorityMessageSenders;
 
+        public static final int SUPPRESSED_EFFECTS_UNSET = -1;
+        public static final int SUPPRESSED_EFFECT_LIGHTS = 1 << 0;
+        public static final int SUPPRESSED_EFFECT_PEEK = 1 << 1;
+
+        private static final int[] ALL_SUPPRESSED_EFFECTS = {
+                SUPPRESSED_EFFECT_LIGHTS,
+                SUPPRESSED_EFFECT_PEEK,
+        };
+
+        /**
+         * Visual effects to suppress for a notification that is filtered by Do Not Disturb mode.
+         * Bitmask of SUPPRESSED_EFFECT_* constants.
+         */
+        public final int suppressedVisualEffects;
+
+
+        @Deprecated
         public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders) {
+            this(priorityCategories, priorityCallSenders, priorityMessageSenders,
+                    SUPPRESSED_EFFECTS_UNSET);
+        }
+
+        public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders,
+                int suppressedVisualEffects) {
             this.priorityCategories = priorityCategories;
             this.priorityCallSenders = priorityCallSenders;
             this.priorityMessageSenders = priorityMessageSenders;
+            this.suppressedVisualEffects = suppressedVisualEffects;
         }
 
         /** @hide */
         public Policy(Parcel source) {
-            this(source.readInt(), source.readInt(), source.readInt());
+            this(source.readInt(), source.readInt(), source.readInt(), source.readInt());
         }
 
         @Override
@@ -626,6 +650,7 @@
             dest.writeInt(priorityCategories);
             dest.writeInt(priorityCallSenders);
             dest.writeInt(priorityMessageSenders);
+            dest.writeInt(suppressedVisualEffects);
         }
 
         @Override
@@ -635,7 +660,8 @@
 
         @Override
         public int hashCode() {
-            return Objects.hash(priorityCategories, priorityCallSenders, priorityMessageSenders);
+            return Objects.hash(priorityCategories, priorityCallSenders, priorityMessageSenders,
+                    suppressedVisualEffects);
         }
 
         @Override
@@ -645,7 +671,8 @@
             final Policy other = (Policy) o;
             return other.priorityCategories == priorityCategories
                     && other.priorityCallSenders == priorityCallSenders
-                    && other.priorityMessageSenders == priorityMessageSenders;
+                    && other.priorityMessageSenders == priorityMessageSenders
+                    && other.suppressedVisualEffects == suppressedVisualEffects;
         }
 
         @Override
@@ -654,9 +681,29 @@
                     + "priorityCategories=" + priorityCategoriesToString(priorityCategories)
                     + ",priorityCallSenders=" + prioritySendersToString(priorityCallSenders)
                     + ",priorityMessageSenders=" + prioritySendersToString(priorityMessageSenders)
+                    + ",suppressedVisualEffects="
+                    + suppressedEffectsToString(suppressedVisualEffects)
                     + "]";
         }
 
+        public static String suppressedEffectsToString(int effects) {
+            if (effects <= 0) return "";
+            final StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < ALL_SUPPRESSED_EFFECTS.length; i++) {
+                final int effect = ALL_SUPPRESSED_EFFECTS[i];
+                if ((effects & effect) != 0) {
+                    if (sb.length() > 0) sb.append(',');
+                    sb.append(effectToString(effect));
+                }
+                effects &= ~effect;
+            }
+            if (effects != 0) {
+                if (sb.length() > 0) sb.append(',');
+                sb.append("UNKNOWN_").append(effects);
+            }
+            return sb.toString();
+        }
+
         public static String priorityCategoriesToString(int priorityCategories) {
             if (priorityCategories == 0) return "";
             final StringBuilder sb = new StringBuilder();
@@ -675,6 +722,15 @@
             return sb.toString();
         }
 
+        private static String effectToString(int effect) {
+            switch (effect) {
+                case SUPPRESSED_EFFECT_LIGHTS: return "SUPPRESSED_EFFECT_LIGHTS";
+                case SUPPRESSED_EFFECT_PEEK: return "SUPPRESSED_EFFECT_PEEK";
+                case SUPPRESSED_EFFECTS_UNSET: return "SUPPRESSED_EFFECTS_UNSET";
+                default: return "UNKNOWN_" + effect;
+            }
+        }
+
         private static String priorityCategoryToString(int priorityCategory) {
             switch (priorityCategory) {
                 case PRIORITY_CATEGORY_REMINDERS: return "PRIORITY_CATEGORY_REMINDERS";
diff --git a/core/java/android/security/net/config/ApplicationConfig.java b/core/java/android/security/net/config/ApplicationConfig.java
index b627641..48359d47 100644
--- a/core/java/android/security/net/config/ApplicationConfig.java
+++ b/core/java/android/security/net/config/ApplicationConfig.java
@@ -144,4 +144,18 @@
             return sInstance;
         }
     }
+
+    /** @hide */
+    public static ApplicationConfig getPlatformDefault() {
+        return new ApplicationConfig(new ConfigSource() {
+            @Override
+            public NetworkSecurityConfig getDefaultConfig() {
+                return NetworkSecurityConfig.DEFAULT;
+            }
+            @Override
+            public Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs() {
+                return null;
+            }
+        });
+    }
 }
diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java
index 8906f9b..9eab80c 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfig.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfig.java
@@ -16,11 +16,14 @@
 
 package android.security.net.config;
 
+import android.util.ArrayMap;
 import android.util.ArraySet;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.net.ssl.X509TrustManager;
@@ -57,12 +60,24 @@
             if (mAnchors != null) {
                 return mAnchors;
             }
-            Set<TrustAnchor> anchors = new ArraySet<TrustAnchor>();
+            // Merge trust anchors based on the X509Certificate.
+            // If we see the same certificate in two TrustAnchors, one with overridesPins and one
+            // without, the one with overridesPins wins.
+            Map<X509Certificate, TrustAnchor> anchorMap = new ArrayMap<>();
             for (CertificatesEntryRef ref : mCertificatesEntryRefs) {
-                anchors.addAll(ref.getTrustAnchors());
+                Set<TrustAnchor> anchors = ref.getTrustAnchors();
+                for (TrustAnchor anchor : anchors) {
+                    if (anchor.overridesPins) {
+                        anchorMap.put(anchor.certificate, anchor);
+                    } else if (!anchorMap.containsKey(anchor.certificate)) {
+                        anchorMap.put(anchor.certificate, anchor);
+                    }
+                }
             }
+            ArraySet<TrustAnchor> anchors = new ArraySet<TrustAnchor>(anchorMap.size());
+            anchors.addAll(anchorMap.values());
             mAnchors = anchors;
-            return anchors;
+            return mAnchors;
         }
     }
 
diff --git a/core/java/android/security/net/config/NetworkSecurityConfigProvider.java b/core/java/android/security/net/config/NetworkSecurityConfigProvider.java
index ca8cdae..ac762ef 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfigProvider.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfigProvider.java
@@ -16,13 +16,21 @@
 
 package android.security.net.config;
 
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.util.Log;
+import java.security.Security;
 import java.security.Provider;
 
 /** @hide */
 public final class NetworkSecurityConfigProvider extends Provider {
-
-    private static String PREFIX =
+    private static final String LOG_TAG = "NetworkSecurityConfig";
+    private static final String PREFIX =
             NetworkSecurityConfigProvider.class.getPackage().getName() + ".";
+    public static final String META_DATA_NETWORK_SECURITY_CONFIG =
+            "android.security.net.config";
+    private static final boolean DBG = true;
 
     public NetworkSecurityConfigProvider() {
         // TODO: More clever name than this
@@ -30,4 +38,43 @@
         put("TrustManagerFactory.PKIX", PREFIX + "RootTrustManagerFactorySpi");
         put("Alg.Alias.TrustManagerFactory.X509", "PKIX");
     }
+
+    public static void install(Context context) {
+        ApplicationInfo info = null;
+        // TODO: This lookup shouldn't be done in the app startup path, it should be done lazily.
+        try {
+            info = context.getPackageManager().getApplicationInfo(context.getPackageName(),
+                    PackageManager.GET_META_DATA);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new RuntimeException("Failed to look up ApplicationInfo", e);
+        }
+        int configResourceId = 0;
+        if (info != null && info.metaData != null) {
+            configResourceId = info.metaData.getInt(META_DATA_NETWORK_SECURITY_CONFIG);
+        }
+
+        ApplicationConfig config;
+        if (configResourceId != 0) {
+            boolean debugBuild = (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+            if (DBG) {
+                Log.d(LOG_TAG, "Using Network Security Config from resource "
+                        + context.getResources().getResourceEntryName(configResourceId)
+                        + " debugBuild: " + debugBuild);
+            }
+            ConfigSource source = new XmlConfigSource(context, configResourceId, debugBuild);
+            config = new ApplicationConfig(source);
+        } else {
+            if (DBG) {
+                Log.d(LOG_TAG, "No Network Security Config specified, using platform default");
+            }
+            config = ApplicationConfig.getPlatformDefault();
+        }
+
+        ApplicationConfig.setDefaultInstance(config);
+        int pos = Security.insertProviderAt(new NetworkSecurityConfigProvider(), 1);
+        if (pos != 1) {
+            throw new RuntimeException("Failed to install provider as highest priority provider."
+                    + " Provider was installed at position " + pos);
+        }
+    }
 }
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 7e7b5fc..ee97e8e 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -108,6 +108,11 @@
      * This does not change the interruption filter, only the effects. **/
     public static final int HINT_HOST_DISABLE_EFFECTS = 1;
 
+    public static final int SUPPRESSED_EFFECT_LIGHTS =
+            NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
+    public static final int SUPPRESSED_EFFECT_PEEK =
+            NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+
     /**
      * The full trim of the StatusBarNotification including all its features.
      *
@@ -822,6 +827,7 @@
         private boolean mIsAmbient;
         private boolean mMatchesInterruptionFilter;
         private int mVisibilityOverride;
+        private int mSuppressedVisualEffects;
 
         public Ranking() {}
 
@@ -861,6 +867,14 @@
             return mVisibilityOverride;
         }
 
+        /**
+         * Returns the type(s) of visual effects that should be suppressed for this notification.
+         * See {@link #SUPPRESSED_EFFECT_LIGHTS}, {@link #SUPPRESSED_EFFECT_PEEK}}.
+         */
+        public int getSuppressedVisualEffects() {
+            return mSuppressedVisualEffects;
+        }
+
 
         /**
          * Returns whether the notification matches the user's interruption
@@ -874,12 +888,14 @@
         }
 
         private void populate(String key, int rank, boolean isAmbient,
-                boolean matchesInterruptionFilter, int visibilityOverride) {
+                boolean matchesInterruptionFilter, int visibilityOverride,
+                int suppressedVisualEffects) {
             mKey = key;
             mRank = rank;
             mIsAmbient = isAmbient;
             mMatchesInterruptionFilter = matchesInterruptionFilter;
             mVisibilityOverride = visibilityOverride;
+            mSuppressedVisualEffects = suppressedVisualEffects;
         }
     }
 
@@ -896,6 +912,7 @@
         private ArrayMap<String,Integer> mRanks;
         private ArraySet<Object> mIntercepted;
         private ArrayMap<String, Integer> mVisibilityOverrides;
+        private ArrayMap<String, Integer> mSuppressedVisualEffects;
 
         private RankingMap(NotificationRankingUpdate rankingUpdate) {
             mRankingUpdate = rankingUpdate;
@@ -921,7 +938,7 @@
         public boolean getRanking(String key, Ranking outRanking) {
             int rank = getRank(key);
             outRanking.populate(key, rank, isAmbient(key), !isIntercepted(key),
-                    getVisibilityOverride(key));
+                    getVisibilityOverride(key), getSuppressedVisualEffects(key));
             return rank >= 0;
         }
 
@@ -959,11 +976,24 @@
                     buildVisibilityOverridesLocked();
                 }
             }
-            Integer overide = mVisibilityOverrides.get(key);
-            if (overide == null) {
+            Integer override = mVisibilityOverrides.get(key);
+            if (override == null) {
                 return Ranking.VISIBILITY_NO_OVERRIDE;
             }
-            return overide.intValue();
+            return override.intValue();
+        }
+
+        private int getSuppressedVisualEffects(String key) {
+            synchronized (this) {
+                if (mSuppressedVisualEffects == null) {
+                    buildSuppressedVisualEffectsLocked();
+                }
+            }
+            Integer suppressed = mSuppressedVisualEffects.get(key);
+            if (suppressed == null) {
+                return 0;
+            }
+            return suppressed.intValue();
         }
 
         // Locked by 'this'
@@ -992,6 +1022,15 @@
             }
         }
 
+        // Locked by 'this'
+        private void buildSuppressedVisualEffectsLocked() {
+            Bundle suppressedBundle = mRankingUpdate.getSuppressedVisualEffects();
+            mSuppressedVisualEffects = new ArrayMap<>(suppressedBundle.size());
+            for (String key: suppressedBundle.keySet()) {
+                mSuppressedVisualEffects.put(key, suppressedBundle.getInt(key));
+            }
+        }
+
         // ----------- Parcelable
 
         @Override
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index 6fba900..1282fb1 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -28,13 +28,15 @@
     private final String[] mInterceptedKeys;
     private final int mFirstAmbientIndex;
     private final Bundle mVisibilityOverrides;
+    private final Bundle mSuppressedVisualEffects;
 
     public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
-            Bundle visibilityOverrides, int firstAmbientIndex) {
+            Bundle visibilityOverrides, int firstAmbientIndex, Bundle suppressedVisualEffects) {
         mKeys = keys;
         mFirstAmbientIndex = firstAmbientIndex;
         mInterceptedKeys = interceptedKeys;
         mVisibilityOverrides = visibilityOverrides;
+        mSuppressedVisualEffects = suppressedVisualEffects;
     }
 
     public NotificationRankingUpdate(Parcel in) {
@@ -42,6 +44,7 @@
         mFirstAmbientIndex = in.readInt();
         mInterceptedKeys = in.readStringArray();
         mVisibilityOverrides = in.readBundle();
+        mSuppressedVisualEffects = in.readBundle();
     }
 
     @Override
@@ -55,6 +58,7 @@
         out.writeInt(mFirstAmbientIndex);
         out.writeStringArray(mInterceptedKeys);
         out.writeBundle(mVisibilityOverrides);
+        out.writeBundle(mSuppressedVisualEffects);
     }
 
     public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -83,4 +87,8 @@
     public Bundle getVisibilityOverrides() {
         return mVisibilityOverrides;
     }
+
+    public Bundle getSuppressedVisualEffects() {
+        return mSuppressedVisualEffects;
+    }
 }
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 82f1b28..b3399d0 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -77,6 +77,8 @@
     private static final boolean DEFAULT_ALLOW_REMINDERS = true;
     private static final boolean DEFAULT_ALLOW_EVENTS = true;
     private static final boolean DEFAULT_ALLOW_REPEAT_CALLERS = false;
+    private static final boolean DEFAULT_ALLOW_PEEK = true;
+    private static final boolean DEFAULT_ALLOW_LIGHTS = true;
 
     private static final int XML_VERSION = 2;
     private static final String ZEN_TAG = "zen";
@@ -91,6 +93,8 @@
     private static final String ALLOW_ATT_MESSAGES_FROM = "messagesFrom";
     private static final String ALLOW_ATT_REMINDERS = "reminders";
     private static final String ALLOW_ATT_EVENTS = "events";
+    private static final String ALLOW_ATT_PEEK = "peek";
+    private static final String ALLOW_ATT_LIGHTS = "lights";
 
     private static final String CONDITION_TAG = "condition";
     private static final String CONDITION_ATT_COMPONENT = "component";
@@ -122,6 +126,8 @@
     public int allowCallsFrom = DEFAULT_SOURCE;
     public int allowMessagesFrom = DEFAULT_SOURCE;
     public int user = UserHandle.USER_SYSTEM;
+    public boolean allowPeek = DEFAULT_ALLOW_PEEK;
+    public boolean allowLights = DEFAULT_ALLOW_LIGHTS;
 
     public ZenRule manualRule;
     public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>();
@@ -148,6 +154,8 @@
                 automaticRules.put(ids[i], rules[i]);
             }
         }
+        allowPeek = source.readInt() == 1;
+        allowLights = source.readInt() == 1;
     }
 
     @Override
@@ -175,22 +183,26 @@
         } else {
             dest.writeInt(0);
         }
+        dest.writeInt(allowPeek ? 1 : 0);
+        dest.writeInt(allowLights ? 1 : 0);
     }
 
     @Override
     public String toString() {
         return new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[')
-            .append("user=").append(user)
-            .append(",allowCalls=").append(allowCalls)
-            .append(",allowRepeatCallers=").append(allowRepeatCallers)
-            .append(",allowMessages=").append(allowMessages)
-            .append(",allowCallsFrom=").append(sourceToString(allowCallsFrom))
-            .append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom))
-            .append(",allowReminders=").append(allowReminders)
-            .append(",allowEvents=").append(allowEvents)
-            .append(",automaticRules=").append(automaticRules)
-            .append(",manualRule=").append(manualRule)
-            .append(']').toString();
+                .append("user=").append(user)
+                .append(",allowCalls=").append(allowCalls)
+                .append(",allowRepeatCallers=").append(allowRepeatCallers)
+                .append(",allowMessages=").append(allowMessages)
+                .append(",allowCallsFrom=").append(sourceToString(allowCallsFrom))
+                .append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom))
+                .append(",allowReminders=").append(allowReminders)
+                .append(",allowEvents=").append(allowEvents)
+                .append(",allowPeek=").append(allowPeek)
+                .append(",allowLights=").append(allowLights)
+                .append(",automaticRules=").append(automaticRules)
+                .append(",manualRule=").append(manualRule)
+                .append(']').toString();
     }
 
     private Diff diff(ZenModeConfig to) {
@@ -222,6 +234,12 @@
         if (allowEvents != to.allowEvents) {
             d.addLine("allowEvents", allowEvents, to.allowEvents);
         }
+        if (allowPeek != to.allowPeek) {
+            d.addLine("allowPeek", allowPeek, to.allowPeek);
+        }
+        if (allowLights != to.allowLights) {
+            d.addLine("allowLights", allowLights, to.allowLights);
+        }
         final ArraySet<String> allRules = new ArraySet<>();
         addKeys(allRules, automaticRules);
         addKeys(allRules, to.automaticRules);
@@ -319,6 +337,8 @@
                 && other.allowMessagesFrom == allowMessagesFrom
                 && other.allowReminders == allowReminders
                 && other.allowEvents == allowEvents
+                && other.allowPeek == allowPeek
+                && other.allowLights == allowLights
                 && other.user == user
                 && Objects.equals(other.automaticRules, automaticRules)
                 && Objects.equals(other.manualRule, manualRule);
@@ -327,7 +347,8 @@
     @Override
     public int hashCode() {
         return Objects.hash(allowCalls, allowRepeatCallers, allowMessages, allowCallsFrom,
-                allowMessagesFrom, allowReminders, allowEvents, user, automaticRules, manualRule);
+                allowMessagesFrom, allowReminders, allowEvents, allowPeek, allowLights,
+                user, automaticRules, manualRule);
     }
 
     private static String toDayList(int[] days) {
@@ -412,6 +433,8 @@
                         rt.allowCallsFrom = DEFAULT_SOURCE;
                         rt.allowMessagesFrom = DEFAULT_SOURCE;
                     }
+                    rt.allowPeek = safeBoolean(parser, ALLOW_ATT_PEEK, DEFAULT_ALLOW_PEEK);
+                    rt.allowLights = safeBoolean(parser, ALLOW_ATT_LIGHTS, DEFAULT_ALLOW_LIGHTS);
                 } else if (MANUAL_TAG.equals(tag)) {
                     rt.manualRule = readRuleXml(parser);
                 } else if (AUTOMATIC_TAG.equals(tag)) {
@@ -440,6 +463,8 @@
         out.attribute(null, ALLOW_ATT_EVENTS, Boolean.toString(allowEvents));
         out.attribute(null, ALLOW_ATT_CALLS_FROM, Integer.toString(allowCallsFrom));
         out.attribute(null, ALLOW_ATT_MESSAGES_FROM, Integer.toString(allowMessagesFrom));
+        out.attribute(null, ALLOW_ATT_PEEK, Boolean.toString(allowPeek));
+        out.attribute(null, ALLOW_ATT_LIGHTS, Boolean.toString(allowLights));
         out.endTag(null, ALLOW_TAG);
 
         if (manualRule != null) {
@@ -611,9 +636,17 @@
         if (allowRepeatCallers) {
             priorityCategories |= Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
         }
+        int suppressedVisualEffects = 0;
+        if (!allowPeek) {
+            suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_PEEK;
+        }
+        if (!allowLights) {
+            suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_LIGHTS;
+        }
         priorityCallSenders = sourceToPrioritySenders(allowCallsFrom, priorityCallSenders);
         priorityMessageSenders = sourceToPrioritySenders(allowMessagesFrom, priorityMessageSenders);
-        return new Policy(priorityCategories, priorityCallSenders, priorityMessageSenders);
+        return new Policy(priorityCategories, priorityCallSenders, priorityMessageSenders,
+                suppressedVisualEffects);
     }
 
     private static int sourceToPrioritySenders(int source, int def) {
@@ -645,6 +678,10 @@
         allowCallsFrom = prioritySendersToSource(policy.priorityCallSenders, allowCallsFrom);
         allowMessagesFrom = prioritySendersToSource(policy.priorityMessageSenders,
                 allowMessagesFrom);
+        if (policy.suppressedVisualEffects != Policy.SUPPRESSED_EFFECTS_UNSET) {
+            allowPeek = (policy.suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_PEEK) == 0;
+            allowLights = (policy.suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_LIGHTS) == 0;
+        }
     }
 
     public static Condition toTimeCondition(Context context, int minutesFromNow, int userHandle) {
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 88e9a95..b61706e 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -24,6 +24,7 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
+import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
@@ -142,6 +143,10 @@
     private Bitmap mBitmap;
     private float mHotSpotX;
     private float mHotSpotY;
+    // The bitmaps for the additional frame of animated pointer icon. Note that the first frame
+    // will be stored in mBitmap.
+    private Bitmap mBitmapFrames[];
+    private int mDurationPerFrame;
 
     private PointerIcon(int style) {
         mStyle = style;
@@ -472,6 +477,36 @@
         } else {
             drawable = context.getDrawable(bitmapRes);
         }
+        if (drawable instanceof AnimationDrawable) {
+            // Extract animation frame bitmaps.
+            final AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
+            final int frames = animationDrawable.getNumberOfFrames();
+            drawable = animationDrawable.getFrame(0);
+            if (frames == 1) {
+                Log.w(TAG, "Animation icon with single frame -- simply treating the first "
+                        + "frame as a normal bitmap icon.");
+            } else {
+                // Assumes they have the exact duration.
+                mDurationPerFrame = animationDrawable.getDuration(0);
+                mBitmapFrames = new Bitmap[frames - 1];
+                final int width = drawable.getIntrinsicWidth();
+                final int height = drawable.getIntrinsicHeight();
+                for (int i = 1; i < frames; ++i) {
+                    Drawable drawableFrame = animationDrawable.getFrame(i);
+                    if (!(drawableFrame instanceof BitmapDrawable)) {
+                        throw new IllegalArgumentException("Frame of an animated pointer icon "
+                                + "must refer to a bitmap drawable.");
+                    }
+                    if (drawableFrame.getIntrinsicWidth() != width ||
+                        drawableFrame.getIntrinsicHeight() != height) {
+                        throw new IllegalArgumentException("The bitmap size of " + i + "-th frame "
+                                + "is different. All frames should have the exact same size and "
+                                + "share the same hotspot.");
+                    }
+                    mBitmapFrames[i - 1] = ((BitmapDrawable)drawableFrame).getBitmap();
+                }
+            }
+        }
         if (!(drawable instanceof BitmapDrawable)) {
             throw new IllegalArgumentException("<pointer-icon> bitmap attribute must "
                     + "refer to a bitmap drawable.");
@@ -509,8 +544,7 @@
             case STYLE_HELP:
                 return com.android.internal.R.styleable.Pointer_pointerIconHelp;
             case STYLE_WAIT:
-                // falls back to the default icon because no animation support.
-                return com.android.internal.R.styleable.Pointer_pointerIconArrow;
+                return com.android.internal.R.styleable.Pointer_pointerIconWait;
             case STYLE_CELL:
                 return com.android.internal.R.styleable.Pointer_pointerIconCell;
             case STYLE_CROSSHAIR:
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 461506b..de4d439 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6329,8 +6329,8 @@
 
         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
 
-        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
-                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
+        outRect.set(Math.round(position.left), Math.round(position.top),
+                Math.round(position.right), Math.round(position.bottom));
     }
 
     /**
@@ -18548,8 +18548,8 @@
             position[1] -= vr.mCurScrollY;
         }
 
-        inOutLocation[0] = (int) (position[0] + 0.5f);
-        inOutLocation[1] = (int) (position[1] + 0.5f);
+        inOutLocation[0] = Math.round(position[0]);
+        inOutLocation[1] = Math.round(position[1]);
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index db978a6..25df004 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5114,10 +5114,10 @@
                     transformMatrix = childMatrix;
                 }
                 transformMatrix.mapRect(boundingRect);
-                dirty.set((int) (boundingRect.left - 0.5f),
-                        (int) (boundingRect.top - 0.5f),
-                        (int) (boundingRect.right + 0.5f),
-                        (int) (boundingRect.bottom + 0.5f));
+                dirty.set((int) Math.floor(boundingRect.left),
+                        (int) Math.floor(boundingRect.top),
+                        (int) Math.ceil(boundingRect.right),
+                        (int) Math.ceil(boundingRect.bottom));
             }
 
             do {
@@ -5154,10 +5154,10 @@
                         RectF boundingRect = attachInfo.mTmpTransformRect;
                         boundingRect.set(dirty);
                         m.mapRect(boundingRect);
-                        dirty.set((int) (boundingRect.left - 0.5f),
-                                (int) (boundingRect.top - 0.5f),
-                                (int) (boundingRect.right + 0.5f),
-                                (int) (boundingRect.bottom + 0.5f));
+                        dirty.set((int) Math.floor(boundingRect.left),
+                                (int) Math.floor(boundingRect.top),
+                                (int) Math.ceil(boundingRect.right),
+                                (int) Math.ceil(boundingRect.bottom));
                     }
                 }
             } while (parent != null);
@@ -5457,8 +5457,8 @@
                 position[0] = offset.x;
                 position[1] = offset.y;
                 child.getMatrix().mapPoints(position);
-                offset.x = (int) (position[0] + 0.5f);
-                offset.y = (int) (position[1] + 0.5f);
+                offset.x = Math.round(position[0]);
+                offset.y = Math.round(position[1]);
             }
             offset.x += dx;
             offset.y += dy;
@@ -5485,8 +5485,8 @@
             rectIsVisible = rect.intersect(mClipBounds.left, mClipBounds.top, mClipBounds.right,
                     mClipBounds.bottom);
         }
-        r.set((int) (rect.left + 0.5f), (int) (rect.top + 0.5f), (int) (rect.right + 0.5f),
-                (int) (rect.bottom + 0.5f));
+        r.set((int) Math.floor(rect.left), (int) Math.floor(rect.top),
+                (int) Math.ceil(rect.right), (int) Math.ceil(rect.bottom));
         if (rectIsVisible && mParent != null) {
             rectIsVisible = mParent.getChildVisibleRect(this, r, offset);
         }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 122b83a..9428f44 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -23,6 +23,7 @@
 import com.android.internal.view.IInputMethodManager;
 import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.InputBindResult;
+import com.android.internal.view.InputMethodClient;
 
 import android.annotation.RequiresPermission;
 import android.content.Context;
@@ -440,8 +441,11 @@
                 }
                 case MSG_UNBIND: {
                     final int sequence = msg.arg1;
+                    @InputMethodClient.UnbindReason
+                    final int reason = msg.arg2;
                     if (DEBUG) {
-                        Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence);
+                        Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence +
+                                " reason=" + InputMethodClient.getUnbindReason(reason));
                     }
                     final boolean startInput;
                     synchronized (mH) {
@@ -569,8 +573,8 @@
         }
 
         @Override
-        public void onUnbindMethod(int sequence) {
-            mH.sendMessage(mH.obtainMessage(MSG_UNBIND, sequence, 0));
+        public void onUnbindMethod(int sequence, @InputMethodClient.UnbindReason int unbindReason) {
+            mH.sendMessage(mH.obtainMessage(MSG_UNBIND, sequence, unbindReason));
         }
 
         @Override
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index 5eea252..47df4e8 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -177,8 +177,7 @@
 
     public void onConfigurationChanged(Configuration newConfig) {
         if (!mMaxItemsSet) {
-            mMaxItems = mContext.getResources().getInteger(
-                    com.android.internal.R.integer.max_action_buttons);
+            mMaxItems = ActionBarPolicy.get(mContext).getMaxActionButtons();
         }
         if (mMenu != null) {
             mMenu.onItemsChanged(true);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b5d994d..3e6d121 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3366,10 +3366,17 @@
     }
 
     /**
-     * Sets whether the movement method will automatically be set to
-     * {@link LinkMovementMethod} if {@link #setAutoLinkMask} has been
-     * set to nonzero and links are detected in {@link #setText}.
-     * The default is true.
+     * Sets whether the movement method will automatically be set to {@link LinkMovementMethod}
+     * after {@link #setText} or {@link #append} is called. The movement method is set if one of the
+     * following is true:
+     * <ul>
+     * <li>{@link #setAutoLinkMask} has been set to nonzero and links are detected in
+     * {@link #setText} or {@link #append}.
+     * <li>The input for {@link #setText} or {@link #append} contains a {@link ClickableSpan}.
+     * </ul>
+     *
+     * <p>This function does not have an immediate effect, movement method will be set only after a
+     * call to {@link #setText} or {@link #append}. The default is true.</p>
      *
      * @attr ref android.R.styleable#TextView_linksClickable
      */
@@ -3379,10 +3386,14 @@
     }
 
     /**
-     * Returns whether the movement method will automatically be set to
-     * {@link LinkMovementMethod} if {@link #setAutoLinkMask} has been
-     * set to nonzero and links are detected in {@link #setText}.
-     * The default is true.
+     * Returns whether the movement method will automatically be set to {@link LinkMovementMethod}
+     * after {@link #setText} or {@link #append} is called.
+     *
+     * See {@link #setLinksClickable} for details.
+     *
+     * <p>The default is true.</p>
+     *
+     * @see #setLinksClickable
      *
      * @attr ref android.R.styleable#TextView_linksClickable
      */
@@ -3976,13 +3987,19 @@
 
         ((Editable) mText).append(text, start, end);
 
+        boolean hasClickableSpans = false;
         if (mAutoLinkMask != 0) {
-            boolean linksWereAdded = Linkify.addLinks((Spannable) mText, mAutoLinkMask);
-            // Do not change the movement method for text that support text selection as it
-            // would prevent an arbitrary cursor displacement.
-            if (linksWereAdded && mLinksClickable && !textCanBeSelected()) {
-                setMovementMethod(LinkMovementMethod.getInstance());
-            }
+            hasClickableSpans = Linkify.addLinks((Spannable) mText, mAutoLinkMask);
+        } else if (mLinksClickable && text instanceof Spanned) {
+            ClickableSpan[] clickableSpans =
+                    ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
+            hasClickableSpans = clickableSpans != null && clickableSpans.length > 0;
+        }
+
+        // Do not change the movement method for text that supports text selection as it
+        // would prevent an arbitrary cursor displacement.
+        if (hasClickableSpans && mLinksClickable && !textCanBeSelected()) {
+            setMovementMethod(LinkMovementMethod.getInstance());
         }
     }
 
@@ -4327,6 +4344,7 @@
             text = TextUtils.stringOrSpannedString(text);
         }
 
+        boolean hasClickableSpans = false;
         if (mAutoLinkMask != 0) {
             Spannable s2;
 
@@ -4336,22 +4354,32 @@
                 s2 = mSpannableFactory.newSpannable(text);
             }
 
-            if (Linkify.addLinks(s2, mAutoLinkMask)) {
+            hasClickableSpans = Linkify.addLinks(s2, mAutoLinkMask);
+            if (hasClickableSpans) {
                 text = s2;
-                type = (type == BufferType.EDITABLE) ? BufferType.EDITABLE : BufferType.SPANNABLE;
+            }
+        } else if (mLinksClickable && text instanceof Spanned) {
+            ClickableSpan[] clickableSpans =
+                    ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
+            hasClickableSpans = clickableSpans != null && clickableSpans.length > 0;
+            if (hasClickableSpans && !(text instanceof Spannable)) {
+                text = mSpannableFactory.newSpannable(text);
+            }
+        }
 
-                /*
-                 * We must go ahead and set the text before changing the
-                 * movement method, because setMovementMethod() may call
-                 * setText() again to try to upgrade the buffer type.
-                 */
-                mText = text;
+        if (hasClickableSpans) {
+            type = (type == BufferType.EDITABLE) ? BufferType.EDITABLE : BufferType.SPANNABLE;
+            /*
+             * We must go ahead and set the text before changing the
+             * movement method, because setMovementMethod() may call
+             * setText() again to try to upgrade the buffer type.
+             */
+            mText = text;
 
-                // Do not change the movement method for text that support text selection as it
-                // would prevent an arbitrary cursor displacement.
-                if (mLinksClickable && !textCanBeSelected()) {
-                    setMovementMethod(LinkMovementMethod.getInstance());
-                }
+            // Do not change the movement method for text that supports text selection as it
+            // would prevent an arbitrary cursor displacement.
+            if (mLinksClickable && !textCanBeSelected()) {
+                setMovementMethod(LinkMovementMethod.getInstance());
             }
         }
 
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 38ce033..b523b84 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -198,14 +198,7 @@
 
         mAllowAutoAdvance = true;
 
-        // Updates mHourFormat variables used below.
-        updateHourFormat(mLocale, mIs24Hour);
-
-        // Update hour text field.
-        final int minHour = mHourFormatStartsAtZero ? 0 : 1;
-        final int maxHour = (mIs24Hour ? 23 : 11) + minHour;
-        mHourView.setRange(minHour, maxHour);
-        mHourView.setShowLeadingZeroes(mHourFormatShowLeadingZero);
+        updateHourFormat();
 
         // Initialize with current time.
         mTempCalendar = Calendar.getInstance(mLocale);
@@ -232,15 +225,14 @@
     }
 
     /**
-     * Determines how the hour should be formatted and updates member variables
-     * related to hour formatting.
-     *
-     * @param locale the locale in which the view is displayed
-     * @param is24Hour whether the view is in 24-hour (hour-of-day) mode
+     * Updates hour formatting based on the current locale and 24-hour mode.
+     * <p>
+     * Determines how the hour should be formatted, sets member variables for
+     * leading zero and starting hour, and sets the hour view's presentation.
      */
-    private void updateHourFormat(Locale locale, boolean is24Hour) {
+    private void updateHourFormat() {
         final String bestDateTimePattern = DateFormat.getBestDateTimePattern(
-                locale, is24Hour ? "Hm" : "hm");
+                mLocale, mIs24Hour ? "Hm" : "hm");
         final int lengthPattern = bestDateTimePattern.length();
         boolean showLeadingZero = false;
         char hourFormat = '\0';
@@ -258,6 +250,12 @@
 
         mHourFormatShowLeadingZero = showLeadingZero;
         mHourFormatStartsAtZero = hourFormat == 'K' || hourFormat == 'H';
+
+        // Update hour text field.
+        final int minHour = mHourFormatStartsAtZero ? 0 : 1;
+        final int maxHour = (mIs24Hour ? 23 : 11) + minHour;
+        mHourView.setRange(minHour, maxHour);
+        mHourView.setShowLeadingZeroes(mHourFormatShowLeadingZero);
     }
 
     private static final CharSequence obtainVerbatim(String text) {
@@ -456,6 +454,7 @@
             mIs24Hour = is24Hour;
             mInitialHourOfDay = getHour();
 
+            updateHourFormat();
             updateUI(mRadialTimePickerView.getCurrentItemShowing());
         }
     }
@@ -655,6 +654,10 @@
 
     /**
      * Converts hour-of-day (0-23) time into a localized hour number.
+     * <p>
+     * The localized value may be in the range (0-23), (1-24), (0-11), or
+     * (1-12) depending on the locale. This method does not handle leading
+     * zeroes.
      *
      * @param hourOfDay the hour-of-day (0-23)
      * @return a localized hour number
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 2c5e50c..08c7935 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -30,6 +30,9 @@
     public static final int QS_LOCK_TILE = 257;
     public static final int QS_USER_TILE = 258;
     public static final int QS_BATTERY_TILE = 259;
+    public static final int NOTIFICATION_ZEN_MODE_VISUAL_INTERRUPTIONS = 260;
+    public static final int ACTION_ZEN_ALLOW_PEEK = 261;
+    public static final int ACTION_ZEN_ALLOW_LIGHTS = 262;
 
     public static void visible(Context context, int category) throws IllegalArgumentException {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
new file mode 100644
index 0000000..b101733
--- /dev/null
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.policy;
+
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Looper;
+import android.view.Choreographer;
+import android.view.DisplayListCanvas;
+import android.view.RenderNode;
+import android.view.ThreadedRenderer;
+import android.view.View;
+
+/**
+ * The thread which draws a fill in background while the app is resizing in areas where the app
+ * content draw is lagging behind the resize operation.
+ * It starts with the creation and it ends once someone calls destroy().
+ * Any size changes can be passed by a call to setTargetRect will passed to the thread and
+ * executed via the Choreographer.
+ * @hide
+ */
+public class BackdropFrameRenderer extends Thread implements Choreographer.FrameCallback {
+
+    private DecorView mDecorView;
+
+    // This is containing the last requested size by a resize command. Note that this size might
+    // or might not have been applied to the output already.
+    private final Rect mTargetRect = new Rect();
+
+    // The render nodes for the multi threaded renderer.
+    private ThreadedRenderer mRenderer;
+    private RenderNode mFrameAndBackdropNode;
+
+    private final Rect mOldTargetRect = new Rect();
+    private final Rect mNewTargetRect = new Rect();
+    private Choreographer mChoreographer;
+
+    // Cached size values from the last render for the case that the view hierarchy is gone
+    // during a configuration change.
+    private int mLastContentWidth;
+    private int mLastContentHeight;
+    private int mLastCaptionHeight;
+    private int mLastXOffset;
+    private int mLastYOffset;
+
+    // Whether to report when next frame is drawn or not.
+    private boolean mReportNextDraw;
+
+    private Drawable mCaptionBackgroundDrawable;
+    private Drawable mResizingBackgroundDrawable;
+
+    public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
+            Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable) {
+        setName("ResizeFrame");
+
+        mRenderer = renderer;
+        onResourcesLoaded(decorView, resizingBackgroundDrawable, captionBackgroundDrawable);
+
+        // Create a render node for the content and frame backdrop
+        // which can be resized independently from the content.
+        mFrameAndBackdropNode = RenderNode.create("FrameAndBackdropNode", null);
+
+        mRenderer.addRenderNode(mFrameAndBackdropNode, true);
+
+        // Set the initial bounds and draw once so that we do not get a broken frame.
+        mTargetRect.set(initialBounds);
+        synchronized (this) {
+            changeWindowSizeLocked(initialBounds);
+        }
+
+        // Kick off our draw thread.
+        start();
+    }
+
+    void onResourcesLoaded(DecorView decorView, Drawable resizingBackgroundDrawable,
+            Drawable captionBackgroundDrawableDrawable) {
+        mDecorView = decorView;
+        mResizingBackgroundDrawable = resizingBackgroundDrawable;
+        mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable;
+    }
+
+    /**
+     * Call this function asynchronously when the window size has been changed. The change will
+     * be picked up once per frame and the frame will be re-rendered accordingly.
+     * @param newTargetBounds The new target bounds.
+     */
+    public void setTargetRect(Rect newTargetBounds) {
+        synchronized (this) {
+            mTargetRect.set(newTargetBounds);
+            // Notify of a bounds change.
+            pingRenderLocked();
+        }
+    }
+
+    /**
+     * The window got replaced due to a configuration change.
+     */
+    public void onConfigurationChange() {
+        synchronized (this) {
+            if (mRenderer != null) {
+                // Enforce a window redraw.
+                mOldTargetRect.set(0, 0, 0, 0);
+                pingRenderLocked();
+            }
+        }
+    }
+
+    /**
+     * All resources of the renderer will be released. This function can be called from the
+     * the UI thread as well as the renderer thread.
+     */
+    public void releaseRenderer() {
+        synchronized (this) {
+            if (mRenderer != null) {
+                // Invalidate the current content bounds.
+                mRenderer.setContentDrawBounds(0, 0, 0, 0);
+
+                // Remove the render node again
+                // (see comment above - better to do that only once).
+                mRenderer.removeRenderNode(mFrameAndBackdropNode);
+
+                mRenderer = null;
+
+                // Exit the renderer loop.
+                pingRenderLocked();
+            }
+        }
+    }
+
+    @Override
+    public void run() {
+        try {
+            Looper.prepare();
+            synchronized (this) {
+                mChoreographer = Choreographer.getInstance();
+
+                // Draw at least once.
+                mChoreographer.postFrameCallback(this);
+            }
+            Looper.loop();
+        } finally {
+            releaseRenderer();
+        }
+        synchronized (this) {
+            // Make sure no more messages are being sent.
+            mChoreographer = null;
+        }
+    }
+
+    /**
+     * The implementation of the FrameCallback.
+     * @param frameTimeNanos The time in nanoseconds when the frame started being rendered,
+     * in the {@link System#nanoTime()} timebase.  Divide this value by {@code 1000000}
+     */
+    @Override
+    public void doFrame(long frameTimeNanos) {
+        synchronized (this) {
+            if (mRenderer == null) {
+                reportDrawIfNeeded();
+                // Tell the looper to stop. We are done.
+                Looper.myLooper().quit();
+                return;
+            }
+            mNewTargetRect.set(mTargetRect);
+            if (!mNewTargetRect.equals(mOldTargetRect) || mReportNextDraw) {
+                mOldTargetRect.set(mNewTargetRect);
+                changeWindowSizeLocked(mNewTargetRect);
+            }
+        }
+    }
+
+    /**
+     * The content is about to be drawn and we got the location of where it will be shown.
+     * If a "changeWindowSizeLocked" call has already been processed, we will re-issue the call
+     * if the previous call was ignored since the size was unknown.
+     * @param xOffset The x offset where the content is drawn to.
+     * @param yOffset The y offset where the content is drawn to.
+     * @param xSize The width size of the content. This should not be 0.
+     * @param ySize The height of the content.
+     * @return true if a frame should be requested after the content is drawn; false otherwise.
+     */
+    public boolean onContentDrawn(int xOffset, int yOffset, int xSize, int ySize) {
+        synchronized (this) {
+            final boolean firstCall = mLastContentWidth == 0;
+            // The current content buffer is drawn here.
+            mLastContentWidth = xSize;
+            mLastContentHeight = ySize - mLastCaptionHeight;
+            mLastXOffset = xOffset;
+            mLastYOffset = yOffset;
+
+            mRenderer.setContentDrawBounds(
+                    mLastXOffset,
+                    mLastYOffset,
+                    mLastXOffset + mLastContentWidth,
+                    mLastYOffset + mLastCaptionHeight + mLastContentHeight);
+            // If this was the first call and changeWindowSizeLocked got already called prior
+            // to us, we should re-issue a changeWindowSizeLocked now.
+            return firstCall
+                    && (mLastCaptionHeight != 0 || !mDecorView.isShowingCaption());
+        }
+    }
+
+    public void onRequestDraw(boolean reportNextDraw) {
+        synchronized (this) {
+            mReportNextDraw = reportNextDraw;
+            mOldTargetRect.set(0, 0, 0, 0);
+            pingRenderLocked();
+        }
+    }
+
+    /**
+     * Resizing the frame to fit the new window size.
+     * @param newBounds The window bounds which needs to be drawn.
+     */
+    private void changeWindowSizeLocked(Rect newBounds) {
+
+        // While a configuration change is taking place the view hierarchy might become
+        // inaccessible. For that case we remember the previous metrics to avoid flashes.
+        // Note that even when there is no visible caption, the caption child will exist.
+        final int captionHeight = mDecorView.getCaptionHeight();
+        // The caption height will probably never dynamically change while we are resizing.
+        // Once set to something other then 0 it should be kept that way.
+        if (captionHeight != 0) {
+            // Remember the height of the caption.
+            mLastCaptionHeight = captionHeight;
+        }
+
+        // Make sure that the other thread has already prepared the render draw calls for the
+        // content. If any size is 0, we have to wait for it to be drawn first.
+        if ((mLastCaptionHeight == 0 && mDecorView.isShowingCaption()) ||
+                mLastContentWidth == 0 || mLastContentHeight == 0) {
+            return;
+        }
+
+        // Since the surface is spanning the entire screen, we have to add the start offset of
+        // the bounds to get to the surface location.
+        final int left = mLastXOffset + newBounds.left;
+        final int top = mLastYOffset + newBounds.top;
+        final int width = newBounds.width();
+        final int height = newBounds.height();
+
+        mFrameAndBackdropNode.setLeftTopRightBottom(left, top, left + width, top + height);
+
+        // Draw the caption and content backdrops in to our render node.
+        final DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
+        mCaptionBackgroundDrawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
+        mCaptionBackgroundDrawable.draw(canvas);
+
+        // The backdrop: clear everything with the background. Clipping is done elsewhere.
+        mResizingBackgroundDrawable.setBounds(0, mLastCaptionHeight, left + width, top + height);
+        mResizingBackgroundDrawable.draw(canvas);
+        mFrameAndBackdropNode.end(canvas);
+
+        // We need to render the node explicitly
+        mRenderer.drawRenderNode(mFrameAndBackdropNode);
+
+        reportDrawIfNeeded();
+    }
+
+    /** Notify view root that a frame has been drawn by us, if it has requested so. */
+    private void reportDrawIfNeeded() {
+        if (mReportNextDraw) {
+            if (mDecorView.isAttachedToWindow()) {
+                mDecorView.getViewRootImpl().reportDrawFinish();
+            }
+            mReportNextDraw = false;
+        }
+    }
+
+    /**
+     * Sends a message to the renderer to wake up and perform the next action which can be
+     * either the next rendering or the self destruction if mRenderer is null.
+     * Note: This call must be synchronized.
+     */
+    private void pingRenderLocked() {
+        if (mChoreographer != null) {
+            mChoreographer.postFrameCallback(this);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 4f38ff3..077cebc 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -26,6 +26,7 @@
 import com.android.internal.widget.ActionBarContextView;
 import com.android.internal.widget.BackgroundFallback;
 import com.android.internal.widget.FloatingToolbar;
+import com.android.internal.widget.NonClientDecorView;
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
@@ -38,6 +39,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.os.RemoteException;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.TypedValue;
@@ -46,14 +48,17 @@
 import android.view.Gravity;
 import android.view.InputQueue;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
+import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewStub;
 import android.view.ViewTreeObserver;
 import android.view.Window;
+import android.view.WindowCallbacks;
 import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
@@ -63,6 +68,8 @@
 import android.widget.FrameLayout;
 import android.widget.PopupWindow;
 
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.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;
@@ -72,8 +79,11 @@
 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 
-class DecorView extends FrameLayout implements RootViewSurfaceTaker {
+/** @hide */
+public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
     private static final String TAG = "DecorView";
 
     private static final boolean SWEEP_OPEN_MENU = false;
@@ -151,6 +161,21 @@
     private Rect mTempRect;
     private Rect mOutsets = new Rect();
 
+    // This is the non client decor view for the window, containing the caption and window control
+    // buttons. The visibility of this decor depends on the workspace and the window type.
+    // If the window type does not require such a view, this member might be null.
+    NonClientDecorView mNonClientDecorView;
+
+    // The non client decor needs to adapt to the used workspace. Since querying and changing the
+    // workspace is expensive, this is the workspace value the window is currently set up for.
+    int mWorkspaceId;
+
+    private boolean mWindowResizeCallbacksAdded = false;
+
+    public BackdropFrameRenderer mBackdropFrameRenderer = null;
+    private Drawable mResizingBackgroundDrawable;
+    private Drawable mCaptionBackgroundDrawable;
+
     DecorView(Context context, int featureId, PhoneWindow window) {
         super(context);
         mFeatureId = featureId;
@@ -326,7 +351,7 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
         int action = event.getAction();
-        if (mHasNonClientDecor && mWindow.mNonClientDecorView.mVisible) {
+        if (mHasNonClientDecor && mNonClientDecorView.mVisible) {
             // Don't dispatch ACTION_DOWN to the non client decor if the window is
             // resizable and the event was (starting) outside the window.
             // Window resizing events should be handled by WindowManager.
@@ -1209,6 +1234,17 @@
              */
             mWindow.openPanelsAfterRestore();
         }
+
+        if (!mWindowResizeCallbacksAdded) {
+            // If there is no window callback installed there was no window set before. Set it now.
+            // Note that our ViewRootImpl object will not change.
+            getViewRootImpl().addWindowCallbacks(this);
+            mWindowResizeCallbacksAdded = true;
+        } else if (mBackdropFrameRenderer != null) {
+            // We are resizing and this call happened due to a configuration change. Tell the
+            // renderer about it.
+            mBackdropFrameRenderer.onConfigurationChange();
+        }
     }
 
     @Override
@@ -1240,6 +1276,11 @@
         if (st != null && st.menu != null && mFeatureId < 0) {
             st.menu.close();
         }
+
+        if (mWindowResizeCallbacksAdded) {
+            getViewRootImpl().removeWindowCallbacks(this);
+            mWindowResizeCallbacksAdded = false;
+        }
     }
 
     @Override
@@ -1483,19 +1524,245 @@
      * @return Returns true when the window has a shadow created by the non client decor.
      **/
     private boolean windowHasShadow() {
-        return windowHasNonClientDecor() && ActivityManager.StackId
-                .hasWindowShadow(mWindow.mWorkspaceId);
+        return windowHasNonClientDecor() && ActivityManager.StackId.hasWindowShadow(mWorkspaceId);
     }
 
     void setWindow(PhoneWindow phoneWindow) {
         mWindow = phoneWindow;
         Context context = getContext();
         if (context instanceof DecorContext) {
-            DecorContext decorContex = (DecorContext) context;
-            decorContex.setPhoneWindow(mWindow);
+            DecorContext decorContext = (DecorContext) context;
+            decorContext.setPhoneWindow(mWindow);
         }
     }
 
+    void onConfigurationChanged() {
+        if (mNonClientDecorView != null) {
+            int workspaceId = getWorkspaceId();
+            if (mWorkspaceId != workspaceId) {
+                mWorkspaceId = workspaceId;
+                // We might have to change the kind of surface before we do anything else.
+                mNonClientDecorView.onConfigurationChanged(
+                        ActivityManager.StackId.hasWindowDecor(mWorkspaceId),
+                        ActivityManager.StackId.hasWindowShadow(mWorkspaceId));
+                enableNonClientDecor(ActivityManager.StackId.hasWindowDecor(workspaceId));
+            }
+        }
+    }
+
+    View onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
+        mWorkspaceId = getWorkspaceId();
+
+        mResizingBackgroundDrawable = getResizingBackgroundDrawable(
+                mWindow.mBackgroundResource, mWindow.mBackgroundFallbackResource);
+        mCaptionBackgroundDrawable =
+                getContext().getDrawable(R.drawable.non_client_decor_title_focused);
+
+        if (mBackdropFrameRenderer != null) {
+            mBackdropFrameRenderer.onResourcesLoaded(
+                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable);
+        }
+
+        mNonClientDecorView = createNonClientDecorView(inflater);
+        final View root = inflater.inflate(layoutResource, null);
+        if (mNonClientDecorView != null) {
+            if (mNonClientDecorView.getParent() == null) {
+                addView(mNonClientDecorView,
+                        new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+            }
+            mNonClientDecorView.addView(root,
+                    new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+        } else {
+            addView(root, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+        }
+        mContentRoot = (ViewGroup) root;
+        return root;
+    }
+
+    // Free floating overlapping windows require a non client decor with a caption and shadow..
+    private NonClientDecorView createNonClientDecorView(LayoutInflater inflater) {
+        NonClientDecorView nonClientDecorView = null;
+        for (int i = getChildCount() - 1; i >= 0 && nonClientDecorView == null; i--) {
+            View view = getChildAt(i);
+            if (view instanceof NonClientDecorView) {
+                // The decor was most likely saved from a relaunch - so reuse it.
+                nonClientDecorView = (NonClientDecorView) view;
+                removeViewAt(i);
+            }
+        }
+        final WindowManager.LayoutParams attrs = mWindow.getAttributes();
+        boolean isApplication = attrs.type == TYPE_BASE_APPLICATION ||
+                attrs.type == TYPE_APPLICATION;
+        // Only a non floating application window on one of the allowed workspaces can get a non
+        // client decor.
+        final boolean hasNonClientDecor = ActivityManager.StackId.hasWindowDecor(mWorkspaceId);
+        if (!mWindow.isFloating() && isApplication && hasNonClientDecor) {
+            // Dependent on the brightness of the used title we either use the
+            // dark or the light button frame.
+            if (nonClientDecorView == null) {
+                Context context = getContext();
+                TypedValue value = new TypedValue();
+                context.getTheme().resolveAttribute(R.attr.colorPrimary, value, true);
+                inflater = inflater.from(context);
+                if (Color.luminance(value.data) < 0.5) {
+                    nonClientDecorView = (NonClientDecorView) inflater.inflate(
+                            R.layout.non_client_decor_dark, null);
+                } else {
+                    nonClientDecorView = (NonClientDecorView) inflater.inflate(
+                            R.layout.non_client_decor_light, null);
+                }
+            }
+            nonClientDecorView.setPhoneWindow(mWindow,
+                    ActivityManager.StackId.hasWindowDecor(mWorkspaceId),
+                    ActivityManager.StackId.hasWindowShadow(mWorkspaceId));
+        } else {
+            nonClientDecorView = null;
+        }
+
+        // Tell the decor if it has a visible non client decor.
+        enableNonClientDecor(nonClientDecorView != null && hasNonClientDecor);
+        return nonClientDecorView;
+    }
+
+    /**
+     * Returns the color used to fill areas the app has not rendered content to yet when the
+     * user is resizing the window of an activity in multi-window mode.
+     */
+    private Drawable getResizingBackgroundDrawable(int backgroundRes, int backgroundFallbackRes) {
+        final Context context = getContext();
+
+        if (backgroundRes != 0) {
+            final Drawable drawable = context.getDrawable(backgroundRes);
+            if (drawable != null) {
+                return drawable;
+            }
+        }
+
+        if (backgroundFallbackRes != 0) {
+            final Drawable fallbackDrawable = context.getDrawable(backgroundFallbackRes);
+            if (fallbackDrawable != null) {
+                return fallbackDrawable;
+            }
+        }
+
+        // We shouldn't really get here as the background fallback should be always available since
+        // it is defaulted by the system.
+        Log.w(TAG, "Failed to find background drawable for PhoneWindow=" + mWindow);
+        return null;
+    }
+
+    /**
+     * Returns the Id of the workspace which contains this window.
+     * Note that if no workspace can be determined - which usually means that it was not
+     * created for an activity - the fullscreen workspace ID will be returned.
+     * @return Returns the workspace stack id which contains this window.
+     **/
+    private int getWorkspaceId() {
+        int workspaceId = INVALID_STACK_ID;
+        final Window.WindowControllerCallback callback = mWindow.getWindowControllerCallback();
+        if (callback != null) {
+            try {
+                workspaceId = callback.getWindowStackId();
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Failed to get the workspace ID of a PhoneWindow.");
+            }
+        }
+        if (workspaceId == INVALID_STACK_ID) {
+            return FULLSCREEN_WORKSPACE_STACK_ID;
+        }
+        return workspaceId;
+    }
+
+    void clearContentView() {
+        if (mNonClientDecorView != null) {
+            if (mNonClientDecorView.getChildCount() > 1) {
+                mNonClientDecorView.removeViewAt(1);
+            }
+        } else {
+            // This window doesn't have non client decor, so we need to just remove the
+            // children of the decor view.
+            removeAllViews();
+        }
+    }
+
+    @Override
+    public void onWindowSizeIsChanging(Rect newBounds) {
+        if (mBackdropFrameRenderer != null) {
+            mBackdropFrameRenderer.setTargetRect(newBounds);
+        }
+    }
+
+    @Override
+    public void onWindowDragResizeStart(Rect initialBounds) {
+        if (mWindow.isDestroyed()) {
+            // If the owner's window is gone, we should not be able to come here anymore.
+            releaseThreadedRenderer();
+            return;
+        }
+        if (mBackdropFrameRenderer != null) {
+            return;
+        }
+        final ThreadedRenderer renderer = (ThreadedRenderer) getHardwareRenderer();
+        if (renderer != null) {
+            mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
+                    initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable);
+
+            // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
+            // If we want to get the shadow shown while resizing, we would need to elevate a new
+            // element which owns the caption and has the elevation.
+            updateElevation();
+        }
+    }
+
+    @Override
+    public void onWindowDragResizeEnd() {
+        releaseThreadedRenderer();
+    }
+
+    @Override
+    public boolean onContentDrawn(int offsetX, int offsetY, int sizeX, int sizeY) {
+        if (mBackdropFrameRenderer == null) {
+            return false;
+        }
+        return mBackdropFrameRenderer.onContentDrawn(offsetX, offsetY, sizeX, sizeY);
+    }
+
+    @Override
+    public void onRequestDraw(boolean reportNextDraw) {
+        if (mBackdropFrameRenderer != null) {
+            mBackdropFrameRenderer.onRequestDraw(reportNextDraw);
+        } else if (reportNextDraw) {
+            // If render thread is gone, just report immediately.
+            if (isAttachedToWindow()) {
+                getViewRootImpl().reportDrawFinish();
+            }
+        }
+    }
+
+    /** Release the renderer thread which is usually done when the user stops resizing. */
+    private void releaseThreadedRenderer() {
+        if (mBackdropFrameRenderer != null) {
+            mBackdropFrameRenderer.releaseRenderer();
+            mBackdropFrameRenderer = null;
+            // Bring the shadow back.
+            updateElevation();
+        }
+    }
+
+    private void updateElevation() {
+        if (mNonClientDecorView != null) {
+            mNonClientDecorView.updateElevation();
+        }
+    }
+
+    boolean isShowingCaption() {
+        return mNonClientDecorView != null && mNonClientDecorView.isShowingDecor();
+    }
+
+    int getCaptionHeight() {
+        return isShowingCaption() ? mNonClientDecorView.getDecorCaptionHeight() : 0;
+    }
+
     private static class ColorViewState {
         View view = null;
         int targetVisibility = View.INVISIBLE;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index c427149..6e7e5cf 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -16,13 +16,10 @@
 
 package com.android.internal.policy;
 
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowManager.LayoutParams.*;
 
-import android.app.ActivityManager.StackId;
 import android.app.ActivityManagerNative;
 import android.app.SearchManager;
 import android.os.UserHandle;
@@ -60,7 +57,6 @@
 import com.android.internal.view.menu.MenuPresenter;
 import com.android.internal.view.menu.MenuView;
 import com.android.internal.widget.DecorContentParent;
-import com.android.internal.widget.NonClientDecorView;
 import com.android.internal.widget.SwipeDismissLayout;
 
 import android.app.ActivityManager;
@@ -72,7 +68,6 @@
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.graphics.Color;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.media.session.MediaController;
@@ -149,15 +144,6 @@
     // view is requested, so we need to force the recreating without introducing an infinite loop.
     private boolean mForceDecorInstall = false;
 
-    // This is the non client decor view for the window, containing the caption and window control
-    // buttons. The visibility of this decor depends on the workspace and the window type.
-    // If the window type does not require such a view, this member might be null.
-    NonClientDecorView mNonClientDecorView;
-
-    // The non client decor needs to adapt to the used workspace. Since querying and changing the
-    // workspace is expensive, this is the workspace value the window is currently set up for.
-    int mWorkspaceId;
-
     // This is the view in which the window contents are placed. It is either
     // mDecor itself, or a child of mDecor where the contents go.
     ViewGroup mContentParent;
@@ -220,12 +206,12 @@
 
     private ProgressBar mHorizontalProgressBar;
 
-    private int mBackgroundResource = 0;
-    private int mBackgroundFallbackResource = 0;
+    int mBackgroundResource = 0;
+    int mBackgroundFallbackResource = 0;
 
     private Drawable mBackgroundDrawable;
 
-    private boolean mLoadEleveation = true;
+    private boolean mLoadElevation = true;
     private float mElevation;
 
     /** Whether window content should be clipped to the background outline. */
@@ -305,7 +291,7 @@
         if (preservedWindow != null) {
             mDecor = (DecorView) preservedWindow.getDecorView();
             mElevation = preservedWindow.getElevation();
-            mLoadEleveation = false;
+            mLoadElevation = false;
             mForceDecorInstall = true;
             // If we're preserving window, carry over the app token from the preserved
             // window, as we'll be skipping the addView in handleResumeActivity(), and
@@ -478,15 +464,10 @@
         }
     }
 
+    @Override
     public void clearContentView() {
-        if (mNonClientDecorView != null) {
-            if (mNonClientDecorView.getChildCount() > 1) {
-                mNonClientDecorView.removeViewAt(1);
-            }
-        } else {
-            // This window doesn't have non client decor, so we need to just remove the children
-            // of the decor view.
-            mDecor.removeAllViews();
+        if (mDecor != null) {
+            mDecor.clearContentView();
         }
     }
 
@@ -700,15 +681,8 @@
                 }
             }
         }
-        if (mNonClientDecorView != null) {
-            int workspaceId = getWorkspaceId();
-            if (mWorkspaceId != workspaceId) {
-                mWorkspaceId = workspaceId;
-                // We might have to change the kind of surface before we do anything else.
-                mNonClientDecorView.phoneWindowUpdated(StackId.hasWindowDecor(mWorkspaceId),
-                        StackId.hasWindowShadow(mWorkspaceId));
-                mDecor.enableNonClientDecor(StackId.hasWindowDecor(workspaceId));
-            }
+        if (mDecor != null) {
+            mDecor.onConfigurationChanged();
         }
     }
 
@@ -2511,7 +2485,7 @@
                             + Integer.toHexString(mFrameResource));
                 }
             }
-            if (mLoadEleveation) {
+            if (mLoadElevation) {
                 mElevation = a.getDimension(R.styleable.Window_windowElevation, 0);
             }
             mClipToOutline = a.getBoolean(R.styleable.Window_windowClipToOutline, false);
@@ -2581,19 +2555,7 @@
         }
 
         mDecor.startChanging();
-
-        mNonClientDecorView = createNonClientDecorView();
-        View in = mLayoutInflater.inflate(layoutResource, null);
-        if (mNonClientDecorView != null) {
-            if (mNonClientDecorView.getParent() == null) {
-                decor.addView(mNonClientDecorView,
-                        new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
-            }
-            mNonClientDecorView.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
-        } else {
-            decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
-        }
-        decor.mContentRoot = (ViewGroup) in;
+        final View in = mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
 
         ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
         if (contentParent == null) {
@@ -2648,50 +2610,6 @@
         return contentParent;
     }
 
-    // Free floating overlapping windows require a non client decor with a caption and shadow..
-    private NonClientDecorView createNonClientDecorView() {
-        NonClientDecorView nonClientDecorView = null;
-        for (int i = mDecor.getChildCount() - 1; i >= 0 && nonClientDecorView == null; i--) {
-            View view = mDecor.getChildAt(i);
-            if (view instanceof NonClientDecorView) {
-                // The decor was most likely saved from a relaunch - so reuse it.
-                nonClientDecorView = (NonClientDecorView) view;
-                mDecor.removeViewAt(i);
-            }
-        }
-        final WindowManager.LayoutParams attrs = getAttributes();
-        boolean isApplication = attrs.type == TYPE_BASE_APPLICATION ||
-                attrs.type == TYPE_APPLICATION;
-        mWorkspaceId = getWorkspaceId();
-        // Only a non floating application window on one of the allowed workspaces can get a non
-        // client decor.
-        if (!isFloating() && isApplication && StackId.isStaticStack(mWorkspaceId)) {
-            // Dependent on the brightness of the used title we either use the
-            // dark or the light button frame.
-            if (nonClientDecorView == null) {
-                Context context = mDecor.getContext();
-                TypedValue value = new TypedValue();
-                context.getTheme().resolveAttribute(R.attr.colorPrimary, value, true);
-                LayoutInflater inflater = mLayoutInflater.from(context);
-                if (Color.luminance(value.data) < 0.5) {
-                    nonClientDecorView = (NonClientDecorView) inflater.inflate(
-                            R.layout.non_client_decor_dark, null);
-                } else {
-                    nonClientDecorView = (NonClientDecorView) inflater.inflate(
-                            R.layout.non_client_decor_light, null);
-                }
-            }
-            nonClientDecorView.setPhoneWindow(this, StackId.hasWindowDecor(mWorkspaceId),
-                    StackId.hasWindowShadow(mWorkspaceId), getResizingBackgroundDrawable(),
-                    mDecor.getContext().getDrawable(R.drawable.non_client_decor_title_focused));
-        }
-        // Tell the decor if it has a visible non client decor.
-        mDecor.enableNonClientDecor(
-                nonClientDecorView != null&& StackId.hasWindowDecor(mWorkspaceId));
-
-        return nonClientDecorView;
-    }
-
     /** @hide */
     public void alwaysReadCloseOnTouchAttr() {
         mAlwaysReadCloseOnTouchAttr = true;
@@ -3819,28 +3737,6 @@
         mIsStartingWindow = isStartingWindow;
     }
 
-    /**
-     * Returns the Id of the workspace which contains this window.
-     * Note that if no workspace can be determined - which usually means that it was not
-     * created for an activity - the fullscreen workspace ID will be returned.
-     * @return Returns the workspace stack id which contains this window.
-     **/
-    private int getWorkspaceId() {
-        int workspaceId = INVALID_STACK_ID;
-        WindowControllerCallback callback = getWindowControllerCallback();
-        if (callback != null) {
-            try {
-                workspaceId = callback.getWindowStackId();
-            } catch (RemoteException ex) {
-                Log.e(TAG, "Failed to get the workspace ID of a PhoneWindow.");
-            }
-        }
-        if (workspaceId == INVALID_STACK_ID) {
-            return FULLSCREEN_WORKSPACE_STACK_ID;
-        }
-        return workspaceId;
-    }
-
     @Override
     public void setTheme(int resid) {
         mTheme = resid;
@@ -3851,31 +3747,4 @@
             }
         }
     }
-
-    /**
-     * Returns the color used to fill areas the app has not rendered content to yet when the user
-     * is resizing the window of an activity in multi-window mode.
-     * */
-    private Drawable getResizingBackgroundDrawable() {
-        final Context context = mDecor.getContext();
-
-        if (mBackgroundResource != 0) {
-            final Drawable drawable = context.getDrawable(mBackgroundResource);
-            if (drawable != null) {
-                return drawable;
-            }
-        }
-
-        if (mBackgroundFallbackResource != 0) {
-            final Drawable fallbackDrawable = context.getDrawable(mBackgroundFallbackResource);
-            if (fallbackDrawable != null) {
-                return fallbackDrawable;
-            }
-        }
-
-        // We shouldn't really get here as the background fallback should be always available since
-        // it is defaulted by the system.
-        Log.w(TAG, "Failed to find background drawable for PhoneWindow=" + this);
-        return null;
-    }
 }
diff --git a/core/java/com/android/internal/view/ActionBarPolicy.java b/core/java/com/android/internal/view/ActionBarPolicy.java
index bee59dc..007ab29 100644
--- a/core/java/com/android/internal/view/ActionBarPolicy.java
+++ b/core/java/com/android/internal/view/ActionBarPolicy.java
@@ -19,6 +19,7 @@
 import com.android.internal.R;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.os.Build;
@@ -38,10 +39,29 @@
         mContext = context;
     }
 
+    /**
+     * Returns the maximum number of action buttons that should be permitted within an action
+     * bar/action mode. This will be used to determine how many showAsAction="ifRoom" items can fit.
+     * "always" items can override this.
+     */
     public int getMaxActionButtons() {
-        return mContext.getResources().getInteger(R.integer.max_action_buttons);
+        final Configuration config = mContext.getResources().getConfiguration();
+        final int width = config.screenWidthDp;
+        final int height = config.screenHeightDp;
+        final int smallest = config.smallestScreenWidthDp;
+        if (smallest > 600 || (width > 960 && height > 720) || (width > 720 && height > 960)) {
+            // For values-w600dp, values-sw600dp and values-xlarge.
+            return 5;
+        } else if (width >= 500 || (width > 640 && height > 480) || (width > 480 && height > 640)) {
+            // For values-w500dp and values-large.
+            return 4;
+        } else if (width >= 360) {
+            // For values-w360dp.
+            return 3;
+        } else {
+            return 2;
+        }
     }
-
     public boolean showsOverflowMenuButton() {
         return true;
     }
diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl
index 89d36ff..81056f2 100644
--- a/core/java/com/android/internal/view/IInputMethodClient.aidl
+++ b/core/java/com/android/internal/view/IInputMethodClient.aidl
@@ -25,7 +25,8 @@
 oneway interface IInputMethodClient {
     void setUsingInputMethod(boolean state);
     void onBindMethod(in InputBindResult res);
-    void onUnbindMethod(int sequence);
+    // unbindReason corresponds to InputMethodClient.UnbindReason.
+    void onUnbindMethod(int sequence, int unbindReason);
     void setActive(boolean active);
     void setUserActionNotificationSequenceNumber(int sequenceNumber);
 }
diff --git a/core/java/com/android/internal/view/InputMethodClient.java b/core/java/com/android/internal/view/InputMethodClient.java
new file mode 100644
index 0000000..a035343
--- /dev/null
+++ b/core/java/com/android/internal/view/InputMethodClient.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+public final class InputMethodClient {
+    public static final int UNBIND_REASON_UNSPECIFIED = 0;
+    public static final int UNBIND_REASON_SWITCH_CLIENT = 1;
+    public static final int UNBIND_REASON_SWITCH_IME = 2;
+    public static final int UNBIND_REASON_DISCONNECT_IME = 3;
+    public static final int UNBIND_REASON_NO_IME = 4;
+    public static final int UNBIND_REASON_SWITCH_IME_FAILED = 5;
+    public static final int UNBIND_REASON_RESET_IME = 6;
+
+    @Retention(SOURCE)
+    @IntDef({UNBIND_REASON_UNSPECIFIED, UNBIND_REASON_SWITCH_CLIENT, UNBIND_REASON_SWITCH_IME,
+            UNBIND_REASON_DISCONNECT_IME, UNBIND_REASON_NO_IME, UNBIND_REASON_SWITCH_IME_FAILED,
+            UNBIND_REASON_RESET_IME})
+    public @interface UnbindReason {}
+
+    public static String getUnbindReason(@UnbindReason final int reason) {
+        switch (reason) {
+            case UNBIND_REASON_UNSPECIFIED:
+                return "UNSPECIFIED";
+            case UNBIND_REASON_SWITCH_CLIENT:
+                return "SWITCH_CLIENT";
+            case UNBIND_REASON_SWITCH_IME:
+                return "SWITCH_IME";
+            case UNBIND_REASON_DISCONNECT_IME:
+                return "DISCONNECT_IME";
+            case UNBIND_REASON_NO_IME:
+                return "NO_IME";
+            case UNBIND_REASON_SWITCH_IME_FAILED:
+                return "SWITCH_IME_FAILED";
+            case UNBIND_REASON_RESET_IME:
+                return "RESET_IME";
+            default:
+                return "Unknown=" + reason;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
index de6e228..33b8e05 100644
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -19,26 +19,19 @@
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 
 import android.content.Context;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.util.AttributeSet;
-import android.view.Choreographer;
-import android.view.DisplayListCanvas;
 import android.view.MotionEvent;
-import android.view.RenderNode;
-import android.view.ThreadedRenderer;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
 import android.view.Window;
-import android.view.WindowCallbacks;
 import android.util.Log;
 import android.util.TypedValue;
 
 import com.android.internal.R;
+import com.android.internal.policy.DecorView;
 import com.android.internal.policy.PhoneWindow;
 
 /**
@@ -67,7 +60,7 @@
  * This will be mitigated once b/22527834 will be addressed.
  */
 public class NonClientDecorView extends LinearLayout
-        implements View.OnClickListener, View.OnTouchListener, WindowCallbacks {
+        implements View.OnClickListener, View.OnTouchListener {
     private final static String TAG = "NonClientDecorView";
     // The height of a window which has focus in DIP.
     private final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20;
@@ -76,8 +69,6 @@
     private PhoneWindow mOwner = null;
     private boolean mWindowHasShadow = false;
     private boolean mShowDecor = false;
-    // True when this object is listening for window size changes.
-    private boolean mAttachedCallbacksToRootViewImpl = false;
 
     // True if the window is being dragged.
     private boolean mDragging = false;
@@ -96,12 +87,6 @@
     // to max until the first layout command has been executed.
     private boolean mAllowUpdateElevation = false;
 
-    // The resize frame renderer.
-    private ResizeFrameThread mFrameRendererThread = null;
-
-    private Drawable mResizingBackgroundDrawable;
-    private Drawable mCaptionBackgroundDrawable;
-
     public NonClientDecorView(Context context) {
         super(context);
     }
@@ -114,37 +99,10 @@
         super(context, attrs, defStyle);
     }
 
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        if (!mAttachedCallbacksToRootViewImpl) {
-            // If there is no window callback installed there was no window set before. Set it now.
-            // Note that our ViewRootImpl object will not change.
-            getViewRootImpl().addWindowCallbacks(this);
-            mAttachedCallbacksToRootViewImpl = true;
-        } else if (mFrameRendererThread != null) {
-            // We are resizing and this call happened due to a configuration change. Tell the
-            // renderer about it.
-            mFrameRendererThread.onConfigurationChange();
-        }
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        if (mAttachedCallbacksToRootViewImpl) {
-            getViewRootImpl().removeWindowCallbacks(this);
-            mAttachedCallbacksToRootViewImpl = false;
-        }
-    }
-
-    public void setPhoneWindow(PhoneWindow owner, boolean showDecor, boolean windowHasShadow,
-            Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawableDrawable) {
+    public void setPhoneWindow(PhoneWindow owner, boolean showDecor, boolean windowHasShadow) {
         mOwner = owner;
         mWindowHasShadow = windowHasShadow;
         mShowDecor = showDecor;
-        mResizingBackgroundDrawable = resizingBackgroundDrawable;
-        mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable;
         updateCaptionVisibility();
         if (mWindowHasShadow) {
             initializeElevation();
@@ -208,7 +166,7 @@
      * @param showDecor True if the decor should be shown.
      * @param windowHasShadow True when the window should show a shadow.
      **/
-    public void phoneWindowUpdated(boolean showDecor, boolean windowHasShadow) {
+    public void onConfigurationChanged(boolean showDecor, boolean windowHasShadow) {
         mShowDecor = showDecor;
         updateCaptionVisibility();
         if (windowHasShadow != mWindowHasShadow) {
@@ -294,11 +252,12 @@
      * Note: Windows which have (temporarily) changed their attributes to cover the SystemUI
      *       will get no shadow as they are expected to be "full screen".
      **/
-    private void updateElevation() {
+    public void updateElevation() {
         float elevation = 0;
         // Do not use a shadow when we are in resizing mode (mRenderer not null) since the shadow
         // is bound to the content size and not the target size.
-        if (mWindowHasShadow && mFrameRendererThread == null) {
+        if (mWindowHasShadow
+                && ((DecorView) mOwner.getDecorView()).mBackdropFrameRenderer == null) {
             boolean fill = isFillingScreen();
             elevation = fill ? 0 :
                     (mWindowHasFocus ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP :
@@ -340,329 +299,12 @@
         }
     }
 
-    @Override
-    public void onWindowDragResizeStart(Rect initialBounds) {
-        if (mOwner.isDestroyed()) {
-            // If the owner's window is gone, we should not be able to come here anymore.
-            releaseResources();
-            return;
-        }
-        if (mFrameRendererThread != null) {
-            return;
-        }
-        final ThreadedRenderer renderer =
-                (ThreadedRenderer) mOwner.getDecorView().getHardwareRenderer();
-        if (renderer != null) {
-            mFrameRendererThread = new ResizeFrameThread(renderer, initialBounds);
-            // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
-            // If we want to get the shadow shown while resizing, we would need to elevate a new
-            // element which owns the caption and has the elevation.
-            updateElevation();
-        }
+    public boolean isShowingDecor() {
+        return mShowDecor;
     }
 
-    @Override
-    public boolean onContentDrawn(int xOffset, int yOffset, int xSize, int ySize) {
-        if (mFrameRendererThread == null) {
-            return false;
-        }
-        return mFrameRendererThread.onContentDrawn(xOffset, yOffset, xSize, ySize);
-    }
-
-    @Override
-    public void onRequestDraw(boolean reportNextDraw) {
-        if (mFrameRendererThread != null) {
-            mFrameRendererThread.onRequestDraw(reportNextDraw);
-        } else if (reportNextDraw) {
-            // If render thread is gone, just report immediately.
-            if (isAttachedToWindow()) {
-                getViewRootImpl().reportDrawFinish();
-            }
-        }
-    }
-
-    @Override
-    public void onWindowDragResizeEnd() {
-        releaseThreadedRenderer();
-    }
-
-    @Override
-    public void onWindowSizeIsChanging(Rect newBounds) {
-        if (mFrameRendererThread != null) {
-            mFrameRendererThread.setTargetRect(newBounds);
-        }
-    }
-
-    /**
-     * Release the renderer thread which is usually done when the user stops resizing.
-     */
-    private void releaseThreadedRenderer() {
-        if (mFrameRendererThread != null) {
-            mFrameRendererThread.releaseRenderer();
-            mFrameRendererThread = null;
-            // Bring the shadow back.
-            updateElevation();
-        }
-    }
-
-    /**
-     * Called when the parent window is destroyed to release all resources. Note that this will also
-     * destroy the renderer thread.
-     */
-    private void releaseResources() {
-        releaseThreadedRenderer();
-    }
-
-    /**
-     * The thread which draws the chrome while we are resizing.
-     * It starts with the creation and it ends once someone calls destroy().
-     * Any size changes can be passed by a call to setTargetRect will passed to the thread and
-     * executed via the Choreographer.
-     * TODO(b/24810450): Separate functionality from non-client-decor so that it can be used
-     * independently.
-     */
-    private class ResizeFrameThread extends Thread implements Choreographer.FrameCallback {
-        // This is containing the last requested size by a resize command. Note that this size might
-        // or might not have been applied to the output already.
-        private final Rect mTargetRect = new Rect();
-
-        // The render nodes for the multi threaded renderer.
-        private ThreadedRenderer mRenderer;
-        private RenderNode mFrameAndBackdropNode;
-
-        private final Rect mOldTargetRect = new Rect();
-        private final Rect mNewTargetRect = new Rect();
-        private Choreographer mChoreographer;
-
-        // Cached size values from the last render for the case that the view hierarchy is gone
-        // during a configuration change.
-        private int mLastContentWidth;
-        private int mLastContentHeight;
-        private int mLastCaptionHeight;
-        private int mLastXOffset;
-        private int mLastYOffset;
-
-        // Whether to report when next frame is drawn or not.
-        private boolean mReportNextDraw;
-
-        ResizeFrameThread(ThreadedRenderer renderer, Rect initialBounds) {
-            setName("ResizeFrame");
-            mRenderer = renderer;
-
-            // Create a render node for the content and frame backdrop
-            // which can be resized independently from the content.
-            mFrameAndBackdropNode = RenderNode.create("FrameAndBackdropNode", null);
-
-            mRenderer.addRenderNode(mFrameAndBackdropNode, true);
-
-            // Set the initial bounds and draw once so that we do not get a broken frame.
-            mTargetRect.set(initialBounds);
-            synchronized (this) {
-                changeWindowSizeLocked(initialBounds);
-            }
-
-            // Kick off our draw thread.
-            start();
-        }
-
-        /**
-         * Call this function asynchronously when the window size has been changed. The change will
-         * be picked up once per frame and the frame will be re-rendered accordingly.
-         * @param newTargetBounds The new target bounds.
-         */
-        public void setTargetRect(Rect newTargetBounds) {
-            synchronized (this) {
-                mTargetRect.set(newTargetBounds);
-                // Notify of a bounds change.
-                pingRenderLocked();
-            }
-        }
-
-        /**
-         * The window got replaced due to a configuration change.
-         */
-        public void onConfigurationChange() {
-            synchronized (this) {
-                if (mRenderer != null) {
-                    // Enforce a window redraw.
-                    mOldTargetRect.set(0, 0, 0, 0);
-                    pingRenderLocked();
-                }
-            }
-        }
-
-        /**
-         * All resources of the renderer will be released. This function can be called from the
-         * the UI thread as well as the renderer thread.
-         */
-        public void releaseRenderer() {
-            synchronized (this) {
-                if (mRenderer != null) {
-                    // Invalidate the current content bounds.
-                    mRenderer.setContentDrawBounds(0, 0, 0, 0);
-
-                    // Remove the render node again
-                    // (see comment above - better to do that only once).
-                    mRenderer.removeRenderNode(mFrameAndBackdropNode);
-
-                    mRenderer = null;
-
-                    // Exit the renderer loop.
-                    pingRenderLocked();
-                }
-            }
-        }
-
-        @Override
-        public void run() {
-            try {
-                Looper.prepare();
-                synchronized (this) {
-                    mChoreographer = Choreographer.getInstance();
-
-                    // Draw at least once.
-                    mChoreographer.postFrameCallback(this);
-                }
-                Looper.loop();
-            } finally {
-                releaseRenderer();
-            }
-            synchronized (this) {
-                // Make sure no more messages are being sent.
-                mChoreographer = null;
-            }
-        }
-
-        /**
-         * The implementation of the FrameCallback.
-         * @param frameTimeNanos The time in nanoseconds when the frame started being rendered,
-         * in the {@link System#nanoTime()} timebase.  Divide this value by {@code 1000000}
-         */
-        @Override
-        public void doFrame(long frameTimeNanos) {
-            synchronized (this) {
-                if (mRenderer == null) {
-                    reportDrawIfNeeded();
-                    // Tell the looper to stop. We are done.
-                    Looper.myLooper().quit();
-                    return;
-                }
-                mNewTargetRect.set(mTargetRect);
-                if (!mNewTargetRect.equals(mOldTargetRect) || mReportNextDraw) {
-                    mOldTargetRect.set(mNewTargetRect);
-                    changeWindowSizeLocked(mNewTargetRect);
-                }
-            }
-        }
-
-        /**
-         * The content is about to be drawn and we got the location of where it will be shown.
-         * If a "changeWindowSizeLocked" call has already been processed, we will re-issue the call
-         * if the previous call was ignored since the size was unknown.
-         * @param xOffset The x offset where the content is drawn to.
-         * @param yOffset The y offset where the content is drawn to.
-         * @param xSize The width size of the content. This should not be 0.
-         * @param ySize The height of the content.
-         * @return true if a frame should be requested after the content is drawn; false otherwise.
-         */
-        public boolean onContentDrawn(int xOffset, int yOffset, int xSize, int ySize) {
-            synchronized (this) {
-                final boolean firstCall = mLastContentWidth == 0;
-                // The current content buffer is drawn here.
-                mLastContentWidth = xSize;
-                mLastContentHeight = ySize - mLastCaptionHeight;
-                mLastXOffset = xOffset;
-                mLastYOffset = yOffset;
-
-                mRenderer.setContentDrawBounds(
-                        mLastXOffset,
-                        mLastYOffset,
-                        mLastXOffset + mLastContentWidth,
-                        mLastYOffset + mLastCaptionHeight + mLastContentHeight);
-                // If this was the first call and changeWindowSizeLocked got already called prior
-                // to us, we should re-issue a changeWindowSizeLocked now.
-                return firstCall && (mLastCaptionHeight != 0 || !mShowDecor);
-            }
-        }
-
-        public void onRequestDraw(boolean reportNextDraw) {
-            synchronized (this) {
-                mReportNextDraw = reportNextDraw;
-                mOldTargetRect.set(0, 0, 0, 0);
-                pingRenderLocked();
-            }
-        }
-
-        /**
-         * Resizing the frame to fit the new window size.
-         * @param newBounds The window bounds which needs to be drawn.
-         */
-        private void changeWindowSizeLocked(Rect newBounds) {
-            // While a configuration change is taking place the view hierarchy might become
-            // inaccessible. For that case we remember the previous metrics to avoid flashes.
-            // Note that even when there is no visible caption, the caption child will exist.
-            View caption = getChildAt(0);
-            if (caption != null) {
-                final int captionHeight = caption.getHeight();
-                // The caption height will probably never dynamically change while we are resizing.
-                // Once set to something other then 0 it should be kept that way.
-                if (captionHeight != 0) {
-                    // Remember the height of the caption.
-                    mLastCaptionHeight = captionHeight;
-                }
-            }
-            // Make sure that the other thread has already prepared the render draw calls for the
-            // content. If any size is 0, we have to wait for it to be drawn first.
-            if ((mLastCaptionHeight == 0 && mShowDecor) ||
-                    mLastContentWidth == 0 || mLastContentHeight == 0) {
-                return;
-            }
-            // Since the surface is spanning the entire screen, we have to add the start offset of
-            // the bounds to get to the surface location.
-            final int left = mLastXOffset + newBounds.left;
-            final int top = mLastYOffset + newBounds.top;
-            final int width = newBounds.width();
-            final int height = newBounds.height();
-
-            mFrameAndBackdropNode.setLeftTopRightBottom(left, top, left + width, top + height);
-
-            // Draw the caption and content backdrops in to our render node.
-            DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
-            mCaptionBackgroundDrawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
-            mCaptionBackgroundDrawable.draw(canvas);
-
-            // The backdrop: clear everything with the background. Clipping is done elsewhere.
-            mResizingBackgroundDrawable.setBounds(0, mLastCaptionHeight, left + width, top + height);
-            mResizingBackgroundDrawable.draw(canvas);
-            mFrameAndBackdropNode.end(canvas);
-
-            // We need to render the node explicitly
-            mRenderer.drawRenderNode(mFrameAndBackdropNode);
-
-            reportDrawIfNeeded();
-        }
-
-        /**
-         * Notify view root that a frame has been drawn by us, if it has requested so.
-         */
-        private void reportDrawIfNeeded() {
-            if (mReportNextDraw) {
-                if (isAttachedToWindow()) {
-                    getViewRootImpl().reportDrawFinish();
-                }
-                mReportNextDraw = false;
-            }
-        }
-
-        /**
-         * Sends a message to the renderer to wake up and perform the next action which can be
-         * either the next rendering or the self destruction if mRenderer is null.
-         * Note: This call must be synchronized.
-         */
-        private void pingRenderLocked() {
-            if (mChoreographer != null) {
-                mChoreographer.postFrameCallback(this);
-            }
-        }
+    public int getDecorCaptionHeight() {
+        final View caption = getChildAt(0);
+        return (caption != null) ? caption.getHeight() : 0;
     }
 }
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 815d330..65e8058 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -608,15 +608,6 @@
       kEMIntFast,
       kEMJitCompiler,
     } executionMode = kEMDefault;
-    char profilePeriod[sizeof("-Xprofile-period:")-1 + PROPERTY_VALUE_MAX];
-    char profileDuration[sizeof("-Xprofile-duration:")-1 + PROPERTY_VALUE_MAX];
-    char profileInterval[sizeof("-Xprofile-interval:")-1 + PROPERTY_VALUE_MAX];
-    char profileBackoff[sizeof("-Xprofile-backoff:")-1 + PROPERTY_VALUE_MAX];
-    char profileTopKThreshold[sizeof("-Xprofile-top-k-threshold:")-1 + PROPERTY_VALUE_MAX];
-    char profileTopKChangeThreshold[sizeof("-Xprofile-top-k-change-threshold:")-1 +
-                                    PROPERTY_VALUE_MAX];
-    char profileType[sizeof("-Xprofile-type:")-1 + PROPERTY_VALUE_MAX];
-    char profileMaxStackDepth[sizeof("-Xprofile-max-stack-depth:")-1 + PROPERTY_VALUE_MAX];
     char localeOption[sizeof("-Duser.locale=") + PROPERTY_VALUE_MAX];
     char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
     char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];
@@ -835,60 +826,6 @@
         addOption(localeOption);
     }
 
-    /*
-     * Set profiler options
-     */
-    // Whether or not the profiler should be enabled.
-    property_get("dalvik.vm.profiler", propBuf, "0");
-    if (propBuf[0] == '1') {
-        addOption("-Xenable-profiler");
-    }
-
-    // Whether the profile should start upon app startup or be delayed by some random offset
-    // (in seconds) that is bound between 0 and a fixed value.
-    property_get("dalvik.vm.profile.start-immed", propBuf, "0");
-    if (propBuf[0] == '1') {
-        addOption("-Xprofile-start-immediately");
-    }
-
-    // Number of seconds during profile runs.
-    parseRuntimeOption("dalvik.vm.profile.period-secs", profilePeriod, "-Xprofile-period:");
-
-    // Length of each profile run (seconds).
-    parseRuntimeOption("dalvik.vm.profile.duration-secs",
-                       profileDuration,
-                       "-Xprofile-duration:");
-
-    // Polling interval during profile run (microseconds).
-    parseRuntimeOption("dalvik.vm.profile.interval-us", profileInterval, "-Xprofile-interval:");
-
-    // Coefficient for period backoff.  The the period is multiplied
-    // by this value after each profile run.
-    parseRuntimeOption("dalvik.vm.profile.backoff-coeff", profileBackoff, "-Xprofile-backoff:");
-
-    // Top K% of samples that are considered relevant when
-    // deciding if the app should be recompiled.
-    parseRuntimeOption("dalvik.vm.profile.top-k-thr",
-                       profileTopKThreshold,
-                       "-Xprofile-top-k-threshold:");
-
-    // The threshold after which a change in the structure of the
-    // top K% profiled samples becomes significant and triggers
-    // recompilation. A change in profile is considered
-    // significant if X% (top-k-change-threshold) of the top K%
-    // (top-k-threshold property) samples has changed.
-    parseRuntimeOption("dalvik.vm.profile.top-k-ch-thr",
-                       profileTopKChangeThreshold,
-                       "-Xprofile-top-k-change-threshold:");
-
-    // Type of profile data.
-    parseRuntimeOption("dalvik.vm.profiler.type", profileType, "-Xprofile-type:");
-
-    // Depth of bounded stack data
-    parseRuntimeOption("dalvik.vm.profile.stack-depth",
-                       profileMaxStackDepth,
-                       "-Xprofile-max-stack-depth:");
-
     // Trace files are stored in /data/misc/trace which is writable only in debug mode.
     property_get("ro.debuggable", propBuf, "0");
     if (strcmp(propBuf, "1") == 0) {
diff --git a/core/jni/android_view_PointerIcon.cpp b/core/jni/android_view_PointerIcon.cpp
index d04adbf..d7e2c02 100644
--- a/core/jni/android_view_PointerIcon.cpp
+++ b/core/jni/android_view_PointerIcon.cpp
@@ -24,6 +24,7 @@
 #include <android_runtime/Log.h>
 #include <utils/Log.h>
 #include <android/graphics/GraphicsJNI.h>
+#include "ScopedLocalRef.h"
 
 #include "core_jni_helpers.h"
 
@@ -35,6 +36,8 @@
     jfieldID mBitmap;
     jfieldID mHotSpotX;
     jfieldID mHotSpotY;
+    jfieldID mBitmapFrames;
+    jfieldID mDurationPerFrame;
     jmethodID getSystemIcon;
     jmethodID load;
 } gPointerIconClassInfo;
@@ -84,6 +87,19 @@
         env->DeleteLocalRef(bitmapObj);
     }
 
+    ScopedLocalRef<jobjectArray> bitmapFramesObj(env, reinterpret_cast<jobjectArray>(
+            env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmapFrames)));
+    if (bitmapFramesObj.get()) {
+        outPointerIcon->durationPerFrame = env->GetIntField(
+                loadedPointerIconObj, gPointerIconClassInfo.mDurationPerFrame);
+        jsize size = env->GetArrayLength(bitmapFramesObj.get());
+        outPointerIcon->bitmapFrames.resize(size);
+        for (jsize i = 0; i < size; ++i) {
+            ScopedLocalRef<jobject> bitmapObj(env, env->GetObjectArrayElement(bitmapFramesObj.get(), i));
+            GraphicsJNI::getSkBitmap(env, bitmapObj.get(), &(outPointerIcon->bitmapFrames[i]));
+        }
+    }
+
     env->DeleteLocalRef(loadedPointerIconObj);
     return OK;
 }
@@ -121,6 +137,12 @@
     gPointerIconClassInfo.mHotSpotY = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz,
             "mHotSpotY", "F");
 
+    gPointerIconClassInfo.mBitmapFrames = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz,
+            "mBitmapFrames", "[Landroid/graphics/Bitmap;");
+
+    gPointerIconClassInfo.mDurationPerFrame = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz,
+            "mDurationPerFrame", "I");
+
     gPointerIconClassInfo.getSystemIcon = GetStaticMethodIDOrDie(env, gPointerIconClassInfo.clazz,
             "getSystemIcon", "(Landroid/content/Context;I)Landroid/view/PointerIcon;");
 
diff --git a/core/jni/android_view_PointerIcon.h b/core/jni/android_view_PointerIcon.h
index 86f288d..ca08085 100644
--- a/core/jni/android_view_PointerIcon.h
+++ b/core/jni/android_view_PointerIcon.h
@@ -19,6 +19,8 @@
 
 #include "jni.h"
 
+#include <vector>
+
 #include <utils/Errors.h>
 #include <SkBitmap.h>
 
@@ -69,6 +71,8 @@
     SkBitmap bitmap;
     float hotSpotX;
     float hotSpotY;
+    std::vector<SkBitmap> bitmapFrames;
+    int32_t durationPerFrame;
 
     inline bool isNullIcon() {
         return style == POINTER_ICON_STYLE_NULL;
@@ -79,6 +83,8 @@
         bitmap.reset();
         hotSpotX = 0;
         hotSpotY = 0;
+        bitmapFrames.clear();
+        durationPerFrame = 0;
     }
 };
 
diff --git a/core/res/res/drawable-mdpi/pointer_wait_0.png b/core/res/res/drawable-mdpi/pointer_wait_0.png
new file mode 100644
index 0000000..adb7806
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_1.png b/core/res/res/drawable-mdpi/pointer_wait_1.png
new file mode 100644
index 0000000..fc6b42f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_10.png b/core/res/res/drawable-mdpi/pointer_wait_10.png
new file mode 100644
index 0000000..02968b5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_10.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_11.png b/core/res/res/drawable-mdpi/pointer_wait_11.png
new file mode 100644
index 0000000..24f866b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_11.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_12.png b/core/res/res/drawable-mdpi/pointer_wait_12.png
new file mode 100644
index 0000000..d1a31bc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_12.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_13.png b/core/res/res/drawable-mdpi/pointer_wait_13.png
new file mode 100644
index 0000000..b0c6798
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_13.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_14.png b/core/res/res/drawable-mdpi/pointer_wait_14.png
new file mode 100644
index 0000000..721e86d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_14.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_15.png b/core/res/res/drawable-mdpi/pointer_wait_15.png
new file mode 100644
index 0000000..adb0199
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_15.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_16.png b/core/res/res/drawable-mdpi/pointer_wait_16.png
new file mode 100644
index 0000000..3695c18
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_16.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_17.png b/core/res/res/drawable-mdpi/pointer_wait_17.png
new file mode 100644
index 0000000..861605e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_17.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_18.png b/core/res/res/drawable-mdpi/pointer_wait_18.png
new file mode 100644
index 0000000..f5dfdcf
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_18.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_19.png b/core/res/res/drawable-mdpi/pointer_wait_19.png
new file mode 100644
index 0000000..9d51f79
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_19.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_2.png b/core/res/res/drawable-mdpi/pointer_wait_2.png
new file mode 100644
index 0000000..d73a154
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_20.png b/core/res/res/drawable-mdpi/pointer_wait_20.png
new file mode 100644
index 0000000..81d1d51
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_20.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_21.png b/core/res/res/drawable-mdpi/pointer_wait_21.png
new file mode 100644
index 0000000..331820b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_21.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_22.png b/core/res/res/drawable-mdpi/pointer_wait_22.png
new file mode 100644
index 0000000..2678d32
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_22.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_23.png b/core/res/res/drawable-mdpi/pointer_wait_23.png
new file mode 100644
index 0000000..d54d9eb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_23.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_24.png b/core/res/res/drawable-mdpi/pointer_wait_24.png
new file mode 100644
index 0000000..442ace7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_24.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_25.png b/core/res/res/drawable-mdpi/pointer_wait_25.png
new file mode 100644
index 0000000..27ce60d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_25.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_26.png b/core/res/res/drawable-mdpi/pointer_wait_26.png
new file mode 100644
index 0000000..8143634
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_26.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_27.png b/core/res/res/drawable-mdpi/pointer_wait_27.png
new file mode 100644
index 0000000..496ab9a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_27.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_28.png b/core/res/res/drawable-mdpi/pointer_wait_28.png
new file mode 100644
index 0000000..a2aab2b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_28.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_29.png b/core/res/res/drawable-mdpi/pointer_wait_29.png
new file mode 100644
index 0000000..646d153
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_29.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_3.png b/core/res/res/drawable-mdpi/pointer_wait_3.png
new file mode 100644
index 0000000..9f45afe
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_30.png b/core/res/res/drawable-mdpi/pointer_wait_30.png
new file mode 100644
index 0000000..27b3fc4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_30.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_31.png b/core/res/res/drawable-mdpi/pointer_wait_31.png
new file mode 100644
index 0000000..6dbe184
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_31.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_32.png b/core/res/res/drawable-mdpi/pointer_wait_32.png
new file mode 100644
index 0000000..9f072ef
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_32.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_33.png b/core/res/res/drawable-mdpi/pointer_wait_33.png
new file mode 100644
index 0000000..881ec5f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_33.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_34.png b/core/res/res/drawable-mdpi/pointer_wait_34.png
new file mode 100644
index 0000000..94961e3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_34.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_35.png b/core/res/res/drawable-mdpi/pointer_wait_35.png
new file mode 100644
index 0000000..dfa65d7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_35.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_4.png b/core/res/res/drawable-mdpi/pointer_wait_4.png
new file mode 100644
index 0000000..5d3d652
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_5.png b/core/res/res/drawable-mdpi/pointer_wait_5.png
new file mode 100644
index 0000000..d440a82
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_6.png b/core/res/res/drawable-mdpi/pointer_wait_6.png
new file mode 100644
index 0000000..ae65590
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_6.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_7.png b/core/res/res/drawable-mdpi/pointer_wait_7.png
new file mode 100644
index 0000000..cd84aa5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_7.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_8.png b/core/res/res/drawable-mdpi/pointer_wait_8.png
new file mode 100644
index 0000000..0b81a9a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_8.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_9.png b/core/res/res/drawable-mdpi/pointer_wait_9.png
new file mode 100644
index 0000000..c13a90c1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_wait_9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_0.png b/core/res/res/drawable-xhdpi/pointer_wait_0.png
new file mode 100644
index 0000000..5396784
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_0.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_1.png b/core/res/res/drawable-xhdpi/pointer_wait_1.png
new file mode 100644
index 0000000..25edbf5
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_10.png b/core/res/res/drawable-xhdpi/pointer_wait_10.png
new file mode 100644
index 0000000..96d93a9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_10.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_11.png b/core/res/res/drawable-xhdpi/pointer_wait_11.png
new file mode 100644
index 0000000..cd78675
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_11.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_12.png b/core/res/res/drawable-xhdpi/pointer_wait_12.png
new file mode 100644
index 0000000..1b2c7b2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_12.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_13.png b/core/res/res/drawable-xhdpi/pointer_wait_13.png
new file mode 100644
index 0000000..3b00f10
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_13.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_14.png b/core/res/res/drawable-xhdpi/pointer_wait_14.png
new file mode 100644
index 0000000..eca5c3f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_14.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_15.png b/core/res/res/drawable-xhdpi/pointer_wait_15.png
new file mode 100644
index 0000000..0fc2085
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_15.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_16.png b/core/res/res/drawable-xhdpi/pointer_wait_16.png
new file mode 100644
index 0000000..db13cf6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_16.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_17.png b/core/res/res/drawable-xhdpi/pointer_wait_17.png
new file mode 100644
index 0000000..9b6fac5
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_17.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_18.png b/core/res/res/drawable-xhdpi/pointer_wait_18.png
new file mode 100644
index 0000000..c56ff6c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_18.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_19.png b/core/res/res/drawable-xhdpi/pointer_wait_19.png
new file mode 100644
index 0000000..22b7c90
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_19.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_2.png b/core/res/res/drawable-xhdpi/pointer_wait_2.png
new file mode 100644
index 0000000..4bdbe3f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_20.png b/core/res/res/drawable-xhdpi/pointer_wait_20.png
new file mode 100644
index 0000000..6d042fb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_20.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_21.png b/core/res/res/drawable-xhdpi/pointer_wait_21.png
new file mode 100644
index 0000000..e3ab63f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_21.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_22.png b/core/res/res/drawable-xhdpi/pointer_wait_22.png
new file mode 100644
index 0000000..b25f6b7d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_22.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_23.png b/core/res/res/drawable-xhdpi/pointer_wait_23.png
new file mode 100644
index 0000000..49faba9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_23.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_24.png b/core/res/res/drawable-xhdpi/pointer_wait_24.png
new file mode 100644
index 0000000..e91c340
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_24.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_25.png b/core/res/res/drawable-xhdpi/pointer_wait_25.png
new file mode 100644
index 0000000..f4785c6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_25.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_26.png b/core/res/res/drawable-xhdpi/pointer_wait_26.png
new file mode 100644
index 0000000..ea902f8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_26.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_27.png b/core/res/res/drawable-xhdpi/pointer_wait_27.png
new file mode 100644
index 0000000..7d628c3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_27.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_28.png b/core/res/res/drawable-xhdpi/pointer_wait_28.png
new file mode 100644
index 0000000..92d6dc1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_28.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_29.png b/core/res/res/drawable-xhdpi/pointer_wait_29.png
new file mode 100644
index 0000000..5a8d18915
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_29.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_3.png b/core/res/res/drawable-xhdpi/pointer_wait_3.png
new file mode 100644
index 0000000..de4d79c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_30.png b/core/res/res/drawable-xhdpi/pointer_wait_30.png
new file mode 100644
index 0000000..ba04b5e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_30.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_31.png b/core/res/res/drawable-xhdpi/pointer_wait_31.png
new file mode 100644
index 0000000..3ef8e98
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_31.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_32.png b/core/res/res/drawable-xhdpi/pointer_wait_32.png
new file mode 100644
index 0000000..3297a7d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_32.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_33.png b/core/res/res/drawable-xhdpi/pointer_wait_33.png
new file mode 100644
index 0000000..b0ac3b9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_33.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_34.png b/core/res/res/drawable-xhdpi/pointer_wait_34.png
new file mode 100644
index 0000000..0eaa386
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_34.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_35.png b/core/res/res/drawable-xhdpi/pointer_wait_35.png
new file mode 100644
index 0000000..73894d8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_35.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_4.png b/core/res/res/drawable-xhdpi/pointer_wait_4.png
new file mode 100644
index 0000000..ea44e85
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_4.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_5.png b/core/res/res/drawable-xhdpi/pointer_wait_5.png
new file mode 100644
index 0000000..46c399d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_5.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_6.png b/core/res/res/drawable-xhdpi/pointer_wait_6.png
new file mode 100644
index 0000000..3b9aff6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_6.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_7.png b/core/res/res/drawable-xhdpi/pointer_wait_7.png
new file mode 100644
index 0000000..a54edc0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_7.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_8.png b/core/res/res/drawable-xhdpi/pointer_wait_8.png
new file mode 100644
index 0000000..2f30732
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_8.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_9.png b/core/res/res/drawable-xhdpi/pointer_wait_9.png
new file mode 100644
index 0000000..f39c7a7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_wait_9.png
Binary files differ
diff --git a/core/res/res/drawable/pointer_wait.xml b/core/res/res/drawable/pointer_wait.xml
new file mode 100644
index 0000000..8955ce8
--- /dev/null
+++ b/core/res/res/drawable/pointer_wait.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
+  <item android:drawable="@drawable/pointer_wait_1" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_2" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_3" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_4" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_5" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_6" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_7" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_8" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_9" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_10" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_11" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_12" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_13" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_14" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_15" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_16" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_17" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_18" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_19" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_20" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_21" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_22" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_23" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_24" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_25" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_26" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_27" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_28" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_29" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_30" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_31" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_32" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_33" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_34" android:duration="25"/>
+  <item android:drawable="@drawable/pointer_wait_35" android:duration="25"/>
+</animation-list>
diff --git a/core/res/res/drawable/pointer_wait_icon.xml b/core/res/res/drawable/pointer_wait_icon.xml
new file mode 100644
index 0000000..d9b03b0
--- /dev/null
+++ b/core/res/res/drawable/pointer_wait_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_wait"
+    android:hotSpotX="7dp"
+    android:hotSpotY="7dp" />
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 94e9c4e..9c45c12 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -22,10 +22,6 @@
     <dimen name="thumbnail_width">360dp</dimen>
     <!-- The height that is used when creating thumbnails of applications. -->
     <dimen name="thumbnail_height">360dp</dimen>
-    <!-- The maximum number of action buttons that should be permitted within
-         an action bar/action mode. This will be used to determine how many
-         showAsAction="ifRoom" items can fit. "always" items can override this. -->
-    <integer name="max_action_buttons">5</integer>
     <!-- Default height of an action bar. -->
     <dimen name="action_bar_default_height">56dip</dimen>
     <!-- Vertical padding around action bar icons. -->
@@ -88,7 +84,7 @@
     <!-- Size of the generic status lines keyguard's status view  -->
     <dimen name="kg_status_line_font_size">16sp</dimen>
 
-    <!-- Top margin for the clock view --> 
+    <!-- Top margin for the clock view -->
     <dimen name="kg_clock_top_margin">0dp</dimen>
 
     <!-- Size of margin on the right of keyguard's status view -->
diff --git a/core/res/res/values-w360dp/dimens.xml b/core/res/res/values-w360dp/dimens.xml
deleted file mode 100644
index 0f5d656..0000000
--- a/core/res/res/values-w360dp/dimens.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<resources>
-    <!-- The maximum number of action buttons that should be permitted within
-         an action bar/action mode. This will be used to determine how many
-         showAsAction="ifRoom" items can fit. "always" items can override this. -->
-    <integer name="max_action_buttons">3</integer>
-</resources>
diff --git a/core/res/res/values-w500dp/dimens.xml b/core/res/res/values-w500dp/dimens.xml
deleted file mode 100644
index 68841ca..0000000
--- a/core/res/res/values-w500dp/dimens.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<resources>
-    <!-- The maximum number of action buttons that should be permitted within
-         an action bar/action mode. This will be used to determine how many
-         showAsAction="ifRoom" items can fit. "always" items can override this. -->
-    <integer name="max_action_buttons">4</integer>
-</resources>
diff --git a/core/res/res/values-w600dp/dimens.xml b/core/res/res/values-w600dp/dimens.xml
deleted file mode 100644
index 83c45b5..0000000
--- a/core/res/res/values-w600dp/dimens.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<resources>
-    <!-- The maximum number of action buttons that should be permitted within
-         an action bar/action mode. This will be used to determine how many
-         showAsAction="ifRoom" items can fit. "always" items can override this. -->
-    <integer name="max_action_buttons">5</integer>
-</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 90fc22b..04f4fc2 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4248,7 +4248,8 @@
         <attr name="autoLink" />
         <!-- If set to false, keeps the movement method from being set
              to the link movement method even if autoLink causes links
-             to be found. -->
+             to be found or the input text contains a
+             {@link android.text.style.ClickableSpan ClickableSpan}. -->
         <attr name="linksClickable" format="boolean" />
         <!-- If set, specifies that this TextView has a numeric input method.
              The default is false.
@@ -7631,6 +7632,8 @@
         <attr name="pointerIconHand" format="reference"/>
         <!-- Reference to a pointer drawable with STYLE_HELP -->
         <attr name="pointerIconHelp" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_WAIT -->
+        <attr name="pointerIconWait" format="reference"/>
         <!-- Reference to a pointer drawable with STYLE_CELL -->
         <attr name="pointerIconCell" format="reference"/>
         <!-- Reference to a pointer drawable with STYLE_CROSSHAIR -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 28756f5..01daf26 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -25,10 +25,7 @@
     <!-- The standard size (both width and height) of an application icon that
          will be displayed in the app launcher and elsewhere. -->
     <dimen name="app_icon_size">48dip</dimen>
-    <!-- The maximum number of action buttons that should be permitted within
-         an action bar/action mode. This will be used to determine how many
-         showAsAction="ifRoom" items can fit. "always" items can override this. -->
-    <integer name="max_action_buttons">2</integer>
+
     <dimen name="toast_y_offset">64dip</dimen>
     <!-- Height of the status bar -->
     <dimen name="status_bar_height">24dp</dimen>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index b831df8..eb99077 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1339,6 +1339,7 @@
         <item name="pointerIconHand">@drawable/pointer_hand_icon</item>
         <item name="pointerIconContextMenu">@drawable/pointer_context_menu_icon</item>
         <item name="pointerIconHelp">@drawable/pointer_help_icon</item>
+        <item name="pointerIconWait">@drawable/pointer_wait_icon</item>
         <item name="pointerIconCell">@drawable/pointer_cell_icon</item>
         <item name="pointerIconCrosshair">@drawable/pointer_crosshair_icon</item>
         <item name="pointerIconText">@drawable/pointer_text_icon</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e8f6b46..556467a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -401,7 +401,6 @@
   <java-symbol type="integer" name="db_connection_pool_size" />
   <java-symbol type="integer" name="db_journal_size_limit" />
   <java-symbol type="integer" name="db_wal_autocheckpoint" />
-  <java-symbol type="integer" name="max_action_buttons" />
   <java-symbol type="integer" name="config_soundEffectVolumeDb" />
   <java-symbol type="integer" name="config_lockSoundVolumeDb" />
   <java-symbol type="integer" name="config_multiuserMaximumUsers" />
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index c31a8b7..8c20ddc 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -101,20 +101,21 @@
      */
     public static void install() {
         Provider[] providers = Security.getProviders();
-        int bcProviderPosition = -1;
-        for (int position = 0; position < providers.length; position++) {
-            Provider provider = providers[position];
+        int bcProviderIndex = -1;
+        for (int i = 0; i < providers.length; i++) {
+            Provider provider = providers[i];
             if ("BC".equals(provider.getName())) {
-                bcProviderPosition = position;
+                bcProviderIndex = i;
                 break;
             }
         }
 
         Security.addProvider(new AndroidKeyStoreProvider());
         Provider workaroundProvider = new AndroidKeyStoreBCWorkaroundProvider();
-        if (bcProviderPosition != -1) {
+        if (bcProviderIndex != -1) {
             // Bouncy Castle provider found -- install the workaround provider above it.
-            Security.insertProviderAt(workaroundProvider, bcProviderPosition);
+            // insertProviderAt uses 1-based positions.
+            Security.insertProviderAt(workaroundProvider, bcProviderIndex + 1);
         } else {
             // Bouncy Castle provider not found -- install the workaround provider at lowest
             // priority.
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index 39b7ecb..4cfbb2a 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -18,6 +18,7 @@
 #include "Extensions.h"
 
 #include <GLES2/gl2.h>
+#include <log/log.h>
 
 #include <thread>
 #include <mutex>
@@ -29,6 +30,7 @@
 static std::once_flag sInitializedFlag;
 
 const DeviceInfo* DeviceInfo::get() {
+    LOG_ALWAYS_FATAL_IF(!sDeviceInfo, "DeviceInfo not yet initialized.");
     return sDeviceInfo;
 }
 
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp
index b04f16f..96cac7e 100644
--- a/libs/hwui/OpReorderer.cpp
+++ b/libs/hwui/OpReorderer.cpp
@@ -21,10 +21,10 @@
 #include "renderstate/OffscreenBufferPool.h"
 #include "utils/FatVector.h"
 #include "utils/PaintUtils.h"
+#include "utils/TraceUtils.h"
 
 #include <SkCanvas.h>
 #include <SkPathOps.h>
-#include <utils/Trace.h>
 #include <utils/TypeHelpers.h>
 
 namespace android {
@@ -331,13 +331,15 @@
         RenderNode* layerNode = layers.entries()[i].renderNode;
         const Rect& layerDamage = layers.entries()[i].damage;
 
-        saveForLayer(layerNode->getWidth(), layerNode->getHeight(),
-                layerDamage, nullptr, layerNode);
-        mCanvasState.writableSnapshot()->setClip(
-                layerDamage.left, layerDamage.top, layerDamage.right, layerDamage.bottom);
+        // map current light center into RenderNode's coordinate space
+        Vector3 lightCenter = mCanvasState.currentSnapshot()->getRelativeLightCenter();
+        layerNode->getLayer()->inverseTransformInWindow.mapPoint3d(lightCenter);
+
+        saveForLayer(layerNode->getWidth(), layerNode->getHeight(), 0, 0,
+                layerDamage, lightCenter, nullptr, layerNode);
 
         if (layerNode->getDisplayList()) {
-            deferImpl(*(layerNode->getDisplayList()));
+            deferDisplayList(*(layerNode->getDisplayList()));
         }
         restoreForLayer();
     }
@@ -363,7 +365,7 @@
     mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
             0, 0, viewportWidth, viewportHeight, lightCenter);
 
-    deferImpl(displayList);
+    deferDisplayList(displayList);
 }
 
 void OpReorderer::onViewportInitialized() {}
@@ -371,18 +373,99 @@
 void OpReorderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
 
 void OpReorderer::deferNodePropsAndOps(RenderNode& node) {
-    if (node.applyViewProperties(mCanvasState, mAllocator)) {
-        // not rejected so render
+    const RenderProperties& properties = node.properties();
+    const Outline& outline = properties.getOutline();
+    if (properties.getAlpha() <= 0
+            || (outline.getShouldClip() && outline.isEmpty())
+            || properties.getScaleX() == 0
+            || properties.getScaleY() == 0) {
+        return; // rejected
+    }
+
+    if (properties.getLeft() != 0 || properties.getTop() != 0) {
+        mCanvasState.translate(properties.getLeft(), properties.getTop());
+    }
+    if (properties.getStaticMatrix()) {
+        mCanvasState.concatMatrix(*properties.getStaticMatrix());
+    } else if (properties.getAnimationMatrix()) {
+        mCanvasState.concatMatrix(*properties.getAnimationMatrix());
+    }
+    if (properties.hasTransformMatrix()) {
+        if (properties.isTransformTranslateOnly()) {
+            mCanvasState.translate(properties.getTranslationX(), properties.getTranslationY());
+        } else {
+            mCanvasState.concatMatrix(*properties.getTransformMatrix());
+        }
+    }
+
+    const int width = properties.getWidth();
+    const int height = properties.getHeight();
+
+    Rect saveLayerBounds; // will be set to non-empty if saveLayer needed
+    const bool isLayer = properties.effectiveLayerType() != LayerType::None;
+    int clipFlags = properties.getClippingFlags();
+    if (properties.getAlpha() < 1) {
+        if (isLayer) {
+            clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
+        }
+        if (CC_LIKELY(isLayer || !properties.getHasOverlappingRendering())) {
+            // simply scale rendering content's alpha
+            mCanvasState.scaleAlpha(properties.getAlpha());
+        } else {
+            // schedule saveLayer by initializing saveLayerBounds
+            saveLayerBounds.set(0, 0, width, height);
+            if (clipFlags) {
+                properties.getClippingRectForFlags(clipFlags, &saveLayerBounds);
+                clipFlags = 0; // all clipping done by savelayer
+            }
+        }
+
+        if (CC_UNLIKELY(ATRACE_ENABLED() && properties.promotedToLayer())) {
+            // pretend alpha always causes savelayer to warn about
+            // performance problem affecting old versions
+            ATRACE_FORMAT("%s alpha caused saveLayer %dx%d", node.getName(), width, height);
+        }
+    }
+    if (clipFlags) {
+        Rect clipRect;
+        properties.getClippingRectForFlags(clipFlags, &clipRect);
+        mCanvasState.clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
+                SkRegion::kIntersect_Op);
+    }
+
+    if (properties.getRevealClip().willClip()) {
+        Rect bounds;
+        properties.getRevealClip().getBounds(&bounds);
+        mCanvasState.setClippingRoundRect(mAllocator,
+                bounds, properties.getRevealClip().getRadius());
+    } else if (properties.getOutline().willClip()) {
+        mCanvasState.setClippingOutline(mAllocator, &(properties.getOutline()));
+    }
+
+    if (!mCanvasState.quickRejectConservative(0, 0, width, height)) {
+        // not rejected, so defer render as either Layer, or direct (possibly wrapped in saveLayer)
         if (node.getLayer()) {
             // HW layer
             LayerOp* drawLayerOp = new (mAllocator) LayerOp(node);
             BakedOpState* bakedOpState = tryBakeOpState(*drawLayerOp);
             if (bakedOpState) {
-                // Layer will be drawn into parent layer (which is now current, since we popped mLayerStack)
+                // Node's layer already deferred, schedule it to render into parent layer
                 currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Bitmap);
             }
+        } else if (CC_UNLIKELY(!saveLayerBounds.isEmpty())) {
+            // draw DisplayList contents within temporary, since persisted layer could not be used.
+            // (temp layers are clipped to viewport, since they don't persist offscreen content)
+            SkPaint saveLayerPaint;
+            saveLayerPaint.setAlpha(properties.getAlpha());
+            onBeginLayerOp(*new (mAllocator) BeginLayerOp(
+                    saveLayerBounds,
+                    Matrix4::identity(),
+                    saveLayerBounds,
+                    &saveLayerPaint));
+            deferDisplayList(*(node.getDisplayList()));
+            onEndLayerOp(*new (mAllocator) EndLayerOp());
         } else {
-            deferImpl(*(node.getDisplayList()));
+            deferDisplayList(*(node.getDisplayList()));
         }
     }
 }
@@ -535,7 +618,7 @@
  */
 #define OP_RECEIVER(Type) \
         [](OpReorderer& reorderer, const RecordedOp& op) { reorderer.on##Type(static_cast<const Type&>(op)); },
-void OpReorderer::deferImpl(const DisplayList& displayList) {
+void OpReorderer::deferDisplayList(const DisplayList& displayList) {
     static std::function<void(OpReorderer& reorderer, const RecordedOp&)> receivers[] = {
         MAP_OPS(OP_RECEIVER)
     };
@@ -600,34 +683,21 @@
     currentLayer().deferUnmergeableOp(mAllocator, bakedStateOp, OpBatchType::Vertices);
 }
 
-void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight, const Rect& repaintRect,
+void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
+        float contentTranslateX, float contentTranslateY,
+        const Rect& repaintRect,
+        const Vector3& lightCenter,
         const BeginLayerOp* beginLayerOp, RenderNode* renderNode) {
-
-    auto previous = mCanvasState.currentSnapshot();
     mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
-    mCanvasState.writableSnapshot()->transform->loadIdentity();
     mCanvasState.writableSnapshot()->initializeViewport(layerWidth, layerHeight);
     mCanvasState.writableSnapshot()->roundRectClipState = nullptr;
-
-    Vector3 lightCenter = previous->getRelativeLightCenter();
-    if (renderNode) {
-        Matrix4& inverse = renderNode->getLayer()->inverseTransformInWindow;
-        inverse.mapPoint3d(lightCenter);
-    } else {
-        // Combine all transforms used to present saveLayer content:
-        // parent content transform * canvas transform * bounds offset
-        Matrix4 contentTransform(*previous->transform);
-        contentTransform.multiply(beginLayerOp->localMatrix);
-        contentTransform.translate(beginLayerOp->unmappedBounds.left, beginLayerOp->unmappedBounds.top);
-
-        // inverse the total transform, to map light center into layer-relative space
-        Matrix4 inverse;
-        inverse.loadInverse(contentTransform);
-        inverse.mapPoint3d(lightCenter);
-    }
     mCanvasState.writableSnapshot()->setRelativeLightCenter(lightCenter);
+    mCanvasState.writableSnapshot()->transform->loadTranslate(
+            contentTranslateX, contentTranslateY, 0);
+    mCanvasState.writableSnapshot()->setClip(
+            repaintRect.left, repaintRect.top, repaintRect.right, repaintRect.bottom);
 
-    // create a new layer, and push its index on the stack
+    // create a new layer repaint, and push its index on the stack
     mLayerStack.push_back(mLayerReorderers.size());
     mLayerReorderers.emplace_back(layerWidth, layerHeight, repaintRect, beginLayerOp, renderNode);
 }
@@ -640,9 +710,48 @@
 
 // TODO: test rejection at defer time, where the bounds become empty
 void OpReorderer::onBeginLayerOp(const BeginLayerOp& op) {
-    const uint32_t layerWidth = (uint32_t) op.unmappedBounds.getWidth();
-    const uint32_t layerHeight = (uint32_t) op.unmappedBounds.getHeight();
-    saveForLayer(layerWidth, layerHeight, Rect(layerWidth, layerHeight), &op, nullptr);
+    uint32_t layerWidth = (uint32_t) op.unmappedBounds.getWidth();
+    uint32_t layerHeight = (uint32_t) op.unmappedBounds.getHeight();
+
+    auto previous = mCanvasState.currentSnapshot();
+    Vector3 lightCenter = previous->getRelativeLightCenter();
+
+    // Combine all transforms used to present saveLayer content:
+    // parent content transform * canvas transform * bounds offset
+    Matrix4 contentTransform(*previous->transform);
+    contentTransform.multiply(op.localMatrix);
+    contentTransform.translate(op.unmappedBounds.left, op.unmappedBounds.top);
+
+    Matrix4 inverseContentTransform;
+    inverseContentTransform.loadInverse(contentTransform);
+
+    // map the light center into layer-relative space
+    inverseContentTransform.mapPoint3d(lightCenter);
+
+    // Clip bounds of temporary layer to parent's clip rect, so:
+    Rect saveLayerBounds(layerWidth, layerHeight);
+    //     1) transform Rect(width, height) into parent's space
+    //        note: left/top offsets put in contentTransform above
+    contentTransform.mapRect(saveLayerBounds);
+    //     2) intersect with parent's clip
+    saveLayerBounds.doIntersect(previous->getRenderTargetClip());
+    //     3) and transform back
+    inverseContentTransform.mapRect(saveLayerBounds);
+    saveLayerBounds.doIntersect(Rect(layerWidth, layerHeight));
+    saveLayerBounds.roundOut();
+
+    // if bounds are reduced, will clip the layer's area by reducing required bounds...
+    layerWidth = saveLayerBounds.getWidth();
+    layerHeight = saveLayerBounds.getHeight();
+    // ...and shifting drawing content to account for left/top side clipping
+    float contentTranslateX = -saveLayerBounds.left;
+    float contentTranslateY = -saveLayerBounds.top;
+
+    saveForLayer(layerWidth, layerHeight,
+            contentTranslateX, contentTranslateY,
+            Rect(layerWidth, layerHeight),
+            lightCenter,
+            &op, nullptr);
 }
 
 void OpReorderer::onEndLayerOp(const EndLayerOp& /* ignored */) {
diff --git a/libs/hwui/OpReorderer.h b/libs/hwui/OpReorderer.h
index 09d5cbc..976f413 100644
--- a/libs/hwui/OpReorderer.h
+++ b/libs/hwui/OpReorderer.h
@@ -190,7 +190,10 @@
         Positive
     };
     void saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
-            const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
+            float contentTranslateX, float contentTranslateY,
+            const Rect& repaintRect,
+            const Vector3& lightCenter,
+            const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
     void restoreForLayer();
 
     LayerReorderer& currentLayer() { return mLayerReorderers[mLayerStack.back()]; }
@@ -204,7 +207,7 @@
 
     void deferShadow(const RenderNodeOp& casterOp);
 
-    void deferImpl(const DisplayList& displayList);
+    void deferDisplayList(const DisplayList& displayList);
 
     template <typename V>
     void defer3dChildren(ChildrenSelectMode mode, const V& zTranslatedNodes);
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 50199db..0736a10 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -276,7 +276,7 @@
     }
 
     void dump(const char* label = nullptr) const {
-        ALOGD("%s[l=%f t=%f r=%f b=%f]", label ? label : "Rect", left, top, right, bottom);
+        ALOGD("%s[l=%.2f t=%.2f r=%.2f b=%.2f]", label ? label : "Rect", left, top, right, bottom);
     }
 }; // class Rect
 
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 2713f46..716d536 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -524,76 +524,6 @@
     }
 }
 
-bool RenderNode::applyViewProperties(CanvasState& canvasState, LinearAllocator& allocator) const {
-    const Outline& outline = properties().getOutline();
-    if (properties().getAlpha() <= 0
-            || (outline.getShouldClip() && outline.isEmpty())
-            || properties().getScaleX() == 0
-            || properties().getScaleY() == 0) {
-        return false; // rejected
-    }
-
-    if (properties().getLeft() != 0 || properties().getTop() != 0) {
-        canvasState.translate(properties().getLeft(), properties().getTop());
-    }
-    if (properties().getStaticMatrix()) {
-        canvasState.concatMatrix(*properties().getStaticMatrix());
-    } else if (properties().getAnimationMatrix()) {
-        canvasState.concatMatrix(*properties().getAnimationMatrix());
-    }
-    if (properties().hasTransformMatrix()) {
-        if (properties().isTransformTranslateOnly()) {
-            canvasState.translate(properties().getTranslationX(), properties().getTranslationY());
-        } else {
-            canvasState.concatMatrix(*properties().getTransformMatrix());
-        }
-    }
-
-    const bool isLayer = properties().effectiveLayerType() != LayerType::None;
-    int clipFlags = properties().getClippingFlags();
-    if (properties().getAlpha() < 1) {
-        if (isLayer) {
-            clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
-        }
-        if (CC_LIKELY(isLayer || !properties().getHasOverlappingRendering())) {
-            // simply scale rendering content's alpha
-            canvasState.scaleAlpha(properties().getAlpha());
-        } else {
-            // savelayer needed to create an offscreen buffer
-            Rect layerBounds(0, 0, getWidth(), getHeight());
-            if (clipFlags) {
-                properties().getClippingRectForFlags(clipFlags, &layerBounds);
-                clipFlags = 0; // all clipping done by savelayer
-            }
-            LOG_ALWAYS_FATAL("TODO: savelayer");
-        }
-
-        if (CC_UNLIKELY(ATRACE_ENABLED() && properties().promotedToLayer())) {
-            // pretend alpha always causes savelayer to warn about
-            // performance problem affecting old versions
-            ATRACE_FORMAT("%s alpha caused saveLayer %dx%d", getName(), getWidth(), getHeight());
-        }
-    }
-    if (clipFlags) {
-        Rect clipRect;
-        properties().getClippingRectForFlags(clipFlags, &clipRect);
-        canvasState.clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
-                SkRegion::kIntersect_Op);
-    }
-
-    // TODO: support nesting round rect clips
-    if (mProperties.getRevealClip().willClip()) {
-        Rect bounds;
-        mProperties.getRevealClip().getBounds(&bounds);
-        canvasState.setClippingRoundRect(allocator,
-                bounds, mProperties.getRevealClip().getRadius());
-    } else if (mProperties.getOutline().willClip()) {
-        canvasState.setClippingOutline(allocator, &(mProperties.getOutline()));
-    }
-    return !canvasState.quickRejectConservative(
-            0, 0, properties().getWidth(), properties().getHeight());
-}
-
 /*
  * For property operations, we pass a savecount of 0, since the operations aren't part of the
  * displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index bae5ebe..83d1b58 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -187,9 +187,6 @@
 
     AnimatorManager& animators() { return mAnimatorManager; }
 
-    // Returns false if the properties dictate the subtree contained in this RenderNode won't render
-    bool applyViewProperties(CanvasState& canvasState, LinearAllocator& allocator) const;
-
     void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false) const;
 
     bool nothingToDraw() const {
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 0bd5b65..3952798 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -610,7 +610,6 @@
 
     bool fitsOnLayer() const {
         const DeviceInfo* deviceInfo = DeviceInfo::get();
-        LOG_ALWAYS_FATAL_IF(!deviceInfo, "DeviceInfo uninitialized");
         return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize()
                         && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize();
     }
diff --git a/libs/hwui/unit_tests/OpReordererTests.cpp b/libs/hwui/unit_tests/OpReordererTests.cpp
index a8c9bba..07a1855 100644
--- a/libs/hwui/unit_tests/OpReordererTests.cpp
+++ b/libs/hwui/unit_tests/OpReordererTests.cpp
@@ -17,10 +17,10 @@
 #include <gtest/gtest.h>
 
 #include <BakedOpState.h>
+#include <LayerUpdateQueue.h>
 #include <OpReorderer.h>
 #include <RecordedOp.h>
 #include <RecordingCanvas.h>
-#include <renderthread/CanvasContext.h> // todo: remove
 #include <unit_tests/TestUtils.h>
 
 #include <unordered_map>
@@ -28,8 +28,8 @@
 namespace android {
 namespace uirenderer {
 
-LayerUpdateQueue sEmptyLayerUpdateQueue;
-Vector3 sLightCenter = {100, 100, 100};
+const LayerUpdateQueue sEmptyLayerUpdateQueue;
+const Vector3 sLightCenter = {100, 100, 100};
 
 static std::vector<sp<RenderNode>> createSyncedNodeList(sp<RenderNode>& node) {
     TestUtils::syncHierarchyPropertiesAndDisplayList(node);
@@ -79,7 +79,7 @@
 
 /**
  * Dispatches all static methods to similar formed methods on renderer, which fail by default but
- * are overriden by subclasses per test.
+ * are overridden by subclasses per test.
  */
 class TestDispatcher {
 public:
@@ -117,7 +117,6 @@
         canvas.drawBitmap(bitmap, 10, 10, nullptr);
     });
     OpReorderer reorderer(100, 200, *dl, sLightCenter);
-
     SimpleTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end
@@ -163,7 +162,6 @@
     });
 
     OpReorderer reorderer(200, 200, *dl, sLightCenter);
-
     SimpleBatchingTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(2 * SIMPLE_BATCHING_LOOPS, renderer.getIndex()); // 2 x loops ops, because no merging (TODO: force no merging)
@@ -208,7 +206,6 @@
 
     OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
             createSyncedNodeList(parent), sLightCenter);
-
     RenderNodeTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
 }
@@ -232,7 +229,6 @@
     OpReorderer reorderer(sEmptyLayerUpdateQueue,
             SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver
             200, 200, createSyncedNodeList(node), sLightCenter);
-
     ClippedTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
 }
@@ -274,7 +270,6 @@
     });
 
     OpReorderer reorderer(200, 200, *dl, sLightCenter);
-
     SaveLayerSimpleTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(4, renderer.getIndex());
@@ -345,7 +340,6 @@
     });
 
     OpReorderer reorderer(800, 800, *dl, sLightCenter);
-
     SaveLayerNestedTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(10, renderer.getIndex());
@@ -520,7 +514,6 @@
 
     OpReorderer reorderer(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
             syncedList, sLightCenter);
-
     HwLayerComplexTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(13, renderer.getIndex());
@@ -570,7 +563,6 @@
     });
     OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
             createSyncedNodeList(parent), sLightCenter);
-
     ZReorderTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(10, renderer.getIndex());
@@ -616,7 +608,6 @@
 
     OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
             createSyncedNodeList(parent), sLightCenter);
-
     ShadowTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(2, renderer.getIndex());
@@ -658,7 +649,6 @@
 
     OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
             createSyncedNodeList(parent), (Vector3) { 100, 100, 100 });
-
     ShadowSaveLayerTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(5, renderer.getIndex());
@@ -708,7 +698,6 @@
     layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100));
     OpReorderer reorderer(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
             syncedList, (Vector3) { 100, 100, 100 });
-
     ShadowHwLayerTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(5, renderer.getIndex());
@@ -738,13 +727,11 @@
 
     OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
             createSyncedNodeList(parent), sLightCenter);
-
     ShadowLayeringTestRenderer renderer;
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(4, renderer.getIndex());
 }
 
-
 static void testProperty(TestUtils::PropSetupCallback propSetupCallback,
         std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) {
     class PropertyTestRenderer : public TestRendererBase {
@@ -766,7 +753,6 @@
 
     OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200,
             createSyncedNodeList(node), sLightCenter);
-
     PropertyTestRenderer renderer(opValidateCallback);
     reorderer.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op";
@@ -854,5 +840,128 @@
     });
 }
 
+struct SaveLayerAlphaData {
+    uint32_t layerWidth = 0;
+    uint32_t layerHeight = 0;
+    Rect rectClippedBounds;
+    Matrix4 rectMatrix;
+};
+/**
+ * Constructs a view to hit the temporary layer alpha property implementation:
+ *     a) 0 < alpha < 1
+ *     b) too big for layer (larger than maxTextureSize)
+ *     c) overlapping rendering content
+ * returning observed data about layer size and content clip/transform.
+ *
+ * Used to validate clipping behavior of temporary layer, where requested layer size is reduced
+ * (for efficiency, and to fit in layer size constraints) based on parent clip.
+ */
+void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
+        TestUtils::PropSetupCallback propSetupCallback) {
+    class SaveLayerAlphaClipTestRenderer : public TestRendererBase {
+    public:
+        SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData)
+                : mOutData(outData) {}
+
+        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
+            EXPECT_EQ(0, mIndex++);
+            mOutData->layerWidth = width;
+            mOutData->layerHeight = height;
+            return nullptr;
+        }
+        void onRectOp(const RectOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(1, mIndex++);
+
+            mOutData->rectClippedBounds = state.computedState.clippedBounds;
+            mOutData->rectMatrix = state.computedState.transform;
+        }
+        void endLayer() override {
+            EXPECT_EQ(2, mIndex++);
+        }
+        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(3, mIndex++);
+        }
+    private:
+        SaveLayerAlphaData* mOutData;
+    };
+
+    ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize())
+            << "Node must be bigger than max texture size to exercise saveLayer codepath";
+    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 10000, 10000, [](RecordingCanvas& canvas) {
+        SkPaint paint;
+        paint.setColor(SK_ColorWHITE);
+        canvas.drawRect(0, 0, 10000, 10000, paint);
+    }, [&propSetupCallback](RenderProperties& properties) {
+        properties.setHasOverlappingRendering(true);
+        properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer
+
+        // apply other properties
+        int flags = propSetupCallback(properties);
+        return RenderNode::GENERIC | RenderNode::ALPHA | flags;
+    });
+    auto nodes = createSyncedNodeList(node); // sync before querying height
+
+    OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, nodes, sLightCenter);
+    SaveLayerAlphaClipTestRenderer renderer(outObservedData);
+    reorderer.replayBakedOps<TestDispatcher>(renderer);
+
+    // assert, since output won't be valid if we haven't seen a save layer triggered
+    ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
+}
+
+TEST(OpReorderer, renderPropSaveLayerAlphaClipBig) {
+    SaveLayerAlphaData observedData;
+    testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
+        properties.setTranslationX(10); // offset rendering content
+        properties.setTranslationY(-2000); // offset rendering content
+        return RenderNode::TRANSLATION_X | RenderNode::TRANSLATION_Y;
+    });
+    EXPECT_EQ(190u, observedData.layerWidth);
+    EXPECT_EQ(200u, observedData.layerHeight);
+    EXPECT_EQ(Rect(0, 0, 190, 200), observedData.rectClippedBounds)
+            << "expect content to be clipped to screen area";
+    Matrix4 expected;
+    expected.loadTranslate(0, -2000, 0);
+    EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix)
+            << "expect content to be translated as part of being clipped";
+}
+
+TEST(OpReorderer, renderPropSaveLayerAlphaRotate) {
+    SaveLayerAlphaData observedData;
+    testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
+        // Translate and rotate the view so that the only visible part is the top left corner of
+        // the view. It will form an isoceles right triangle with a long side length of 200 at the
+        // bottom of the viewport.
+        properties.setTranslationX(100);
+        properties.setTranslationY(100);
+        properties.setPivotX(0);
+        properties.setPivotY(0);
+        properties.setRotation(45);
+        return RenderNode::GENERIC
+                | RenderNode::TRANSLATION_X | RenderNode::TRANSLATION_Y
+                | RenderNode::ROTATION;
+    });
+    // ceil(sqrt(2) / 2 * 200) = 142
+    EXPECT_EQ(142u, observedData.layerWidth);
+    EXPECT_EQ(142u, observedData.layerHeight);
+    EXPECT_EQ(Rect(0, 0, 142, 142), observedData.rectClippedBounds);
+    EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix);
+}
+
+TEST(OpReorderer, renderPropSaveLayerAlphaScale) {
+    SaveLayerAlphaData observedData;
+    testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
+        properties.setPivotX(0);
+        properties.setPivotY(0);
+        properties.setScaleX(2);
+        properties.setScaleY(0.5f);
+        return RenderNode::GENERIC | RenderNode::SCALE_X | RenderNode::SCALE_Y;
+    });
+    EXPECT_EQ(100u, observedData.layerWidth);
+    EXPECT_EQ(400u, observedData.layerHeight);
+    EXPECT_EQ(Rect(0, 0, 100, 400), observedData.rectClippedBounds);
+    EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix);
+}
+
 } // namespace uirenderer
 } // namespace android
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index c9586e4..bd6af78 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -86,6 +86,9 @@
     mLocked.pointerIconChanged = false;
     mLocked.requestedPointerShape = mPolicy->getDefaultPointerIconId();
 
+    mLocked.animationFrameIndex = 0;
+    mLocked.lastFrameUpdatedTime = 0;
+
     mLocked.buttonState = 0;
 
     loadResources();
@@ -239,7 +242,8 @@
     AutoMutex _l(mLock);
 
     if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
-        mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources);
+        mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
+                                              &mLocked.animationResources);
     }
 
     if (mLocked.presentation != presentation) {
@@ -402,7 +406,7 @@
     updatePointerLocked();
 }
 
-void PointerController::updatePointerShape(int iconId) {
+void PointerController::updatePointerShape(int32_t iconId) {
     AutoMutex _l(mLock);
     if (mLocked.requestedPointerShape != iconId) {
         mLocked.requestedPointerShape = iconId;
@@ -462,8 +466,17 @@
 void PointerController::doAnimate(nsecs_t timestamp) {
     AutoMutex _l(mLock);
 
-    bool keepAnimating = false;
     mLocked.animationPending = false;
+
+    bool keepFading = doFadingAnimationLocked(timestamp);
+    bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp);
+    if (keepFading || keepBitmapFlipping) {
+        startAnimationLocked();
+    }
+}
+
+bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
+    bool keepAnimating = false;
     nsecs_t frameDelay = timestamp - mLocked.animationTime;
 
     // Animate pointer fade.
@@ -501,10 +514,32 @@
             }
         }
     }
+    return keepAnimating;
+}
 
-    if (keepAnimating) {
-        startAnimationLocked();
+bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) {
+    std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find(
+            mLocked.requestedPointerShape);
+    if (iter == mLocked.animationResources.end()) {
+        return false;
     }
+
+    if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
+        mSpriteController->openTransaction();
+
+        int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
+        mLocked.animationFrameIndex += incr;
+        mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
+        while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
+            mLocked.animationFrameIndex -= iter->second.animationFrames.size();
+        }
+        mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
+
+        mSpriteController->closeTransaction();
+    }
+
+    // Keep animating.
+    return true;
 }
 
 void PointerController::doInactivityTimeout() {
@@ -549,9 +584,16 @@
             if (mLocked.requestedPointerShape == mPolicy->getDefaultPointerIconId()) {
                 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
             } else {
-                std::map<int, SpriteIcon>::const_iterator iter =
+                std::map<int32_t, SpriteIcon>::const_iterator iter =
                     mLocked.additionalMouseResources.find(mLocked.requestedPointerShape);
                 if (iter != mLocked.additionalMouseResources.end()) {
+                    std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
+                            mLocked.animationResources.find(mLocked.requestedPointerShape);
+                    if (anim_iter != mLocked.animationResources.end()) {
+                        mLocked.animationFrameIndex = 0;
+                        mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
+                        startAnimationLocked();
+                    }
                     mLocked.pointerSprite->setIcon(iter->second);
                 } else {
                     ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerShape);
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 6d840db..b6c01d2 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -20,6 +20,7 @@
 #include "SpriteController.h"
 
 #include <map>
+#include <vector>
 
 #include <ui/DisplayInfo.h>
 #include <input/Input.h>
@@ -30,8 +31,6 @@
 #include <utils/String8.h>
 #include <gui/DisplayEventReceiver.h>
 
-#include <SkBitmap.h>
-
 namespace android {
 
 /*
@@ -43,6 +42,11 @@
     SpriteIcon spotAnchor;
 };
 
+struct PointerAnimation {
+    std::vector<SpriteIcon> animationFrames;
+    nsecs_t durationPerFrame;
+};
+
 /*
  * Pointer controller policy interface.
  *
@@ -59,7 +63,8 @@
 
 public:
     virtual void loadPointerResources(PointerResources* outResources) = 0;
-    virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources) = 0;
+    virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
+            std::map<int32_t, PointerAnimation>* outAnimationResources) = 0;
     virtual int32_t getDefaultPointerIconId() = 0;
 };
 
@@ -98,7 +103,7 @@
             const uint32_t* spotIdToIndex, BitSet32 spotIdBits);
     virtual void clearSpots();
 
-    void updatePointerShape(int iconId);
+    void updatePointerShape(int32_t iconId);
     void setDisplayViewport(int32_t width, int32_t height, int32_t orientation);
     void setPointerIcon(const SpriteIcon& icon);
     void setInactivityTimeout(InactivityTimeout inactivityTimeout);
@@ -145,6 +150,9 @@
         bool animationPending;
         nsecs_t animationTime;
 
+        size_t animationFrameIndex;
+        nsecs_t lastFrameUpdatedTime;
+
         int32_t displayWidth;
         int32_t displayHeight;
         int32_t displayOrientation;
@@ -162,7 +170,8 @@
         SpriteIcon pointerIcon;
         bool pointerIconChanged;
 
-        std::map<int, SpriteIcon> additionalMouseResources;
+        std::map<int32_t, SpriteIcon> additionalMouseResources;
+        std::map<int32_t, PointerAnimation> animationResources;
 
         int32_t requestedPointerShape;
 
@@ -178,6 +187,8 @@
     void handleMessage(const Message& message);
     int handleEvent(int fd, int events, void* data);
     void doAnimate(nsecs_t timestamp);
+    bool doFadingAnimationLocked(nsecs_t timestamp);
+    bool doBitmapAnimationLocked(nsecs_t timestamp);
     void doInactivityTimeout();
 
     void startAnimationLocked();
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 6bf5721..445ee6f 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -17,6 +17,8 @@
 package android.media;
 
 import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.text.ParsePosition;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -128,6 +130,9 @@
     // use sLock to serialize the accesses.
     private static final Object sLock = new Object();
 
+    // Pattern to check non zero timestamp
+    private static final Pattern sNonZeroTimePattern = Pattern.compile(".*[1-9].*");
+
     /**
      * Reads Exif tags from the specified JPEG file.
      */
@@ -367,7 +372,8 @@
      */
     public long getDateTime() {
         String dateTimeString = mAttributes.get(TAG_DATETIME);
-        if (dateTimeString == null) return -1;
+        if (dateTimeString == null
+                || !sNonZeroTimePattern.matcher(dateTimeString).matches()) return -1;
 
         ParsePosition pos = new ParsePosition(0);
         try {
@@ -402,7 +408,9 @@
     public long getGpsDateTime() {
         String date = mAttributes.get(TAG_GPS_DATESTAMP);
         String time = mAttributes.get(TAG_GPS_TIMESTAMP);
-        if (date == null || time == null) return -1;
+        if (date == null || time == null
+                || (!sNonZeroTimePattern.matcher(date).matches()
+                && !sNonZeroTimePattern.matcher(time).matches())) return -1;
 
         String dateTimeString = date + ' ' + time;
 
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index cf13374..f263af7 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Tweesydig"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Oriëntasie"</string>
     <string name="label_pages" msgid="7768589729282182230">"Bladsye"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Kies \'n drukker"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Al <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Omvang van <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"bv. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml
index 18c90f5..a93e0a9 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"ባለ ሁለት-ጎን"</string>
     <string name="label_orientation" msgid="2853142581990496477">"አቀማመጠ ገፅ"</string>
     <string name="label_pages" msgid="7768589729282182230">"ገፆች"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"አንድ አታሚ ይምረጡ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ሁሉም <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"የ<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ክልል"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ለምሳሌ፦ 1–5,8,11–13"</string>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index 2d87498c..c9a6a395 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"الجانبان"</string>
     <string name="label_orientation" msgid="2853142581990496477">"الاتجاه"</string>
     <string name="label_pages" msgid="7768589729282182230">"الصفحات"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"اختر طابعة"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"جميع الصفحات وعددها <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"النطاق <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"على سبيل المثال، 1—5،8،11—13"</string>
diff --git a/packages/PrintSpooler/res/values-az-rAZ/strings.xml b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
index c8ca06c..5aeb7bb 100644
--- a/packages/PrintSpooler/res/values-az-rAZ/strings.xml
+++ b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"İkitərəfli"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Oriyentasiya"</string>
     <string name="label_pages" msgid="7768589729282182230">"Səhifələr"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Printer seçin"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Bütün <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> diapazonu"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"məsələn, 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index 7129cc1..93feea5 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Двустранно"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Ориентация"</string>
     <string name="label_pages" msgid="7768589729282182230">"Страници"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Избиране на принтер"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Всички <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Обхват от <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"напр. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-bn-rBD/strings.xml b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
index ae0b01c..0eed9aa 100644
--- a/packages/PrintSpooler/res/values-bn-rBD/strings.xml
+++ b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"দ্বিভুজ"</string>
     <string name="label_orientation" msgid="2853142581990496477">"সজ্জা"</string>
     <string name="label_pages" msgid="7768589729282182230">"পৃষ্ঠাগুলি"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"একটি মুদ্রক নির্বাচন করুন"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"সমস্ত <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> এর পরিসর"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"যেমন, ১—৫,৮,১১—১৩"</string>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index d221c6c..03d3060 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"De dues cares"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientació"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pàgines"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Tria una impressora"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Totes (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="template_page_range" msgid="428638530038286328">"Interval de: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"p. ex. 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index 5396b3e..414abf9 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Oboustranně"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientace"</string>
     <string name="label_pages" msgid="7768589729282182230">"Stránky"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Vyberte tiskárnu"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Vše: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Rozsah: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"např. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index 484d66f..893c991 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Tosidet"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Retning"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sider"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Vælg en printer"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Alle <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Interval på <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"f.eks. 1-5,8,11-13"</string>
diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml
index c6323ef..f6f53ea 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Zweiseitig"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Ausrichtung"</string>
     <string name="label_pages" msgid="7768589729282182230">"Seiten"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Drucker auswählen"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Alle <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Auswahl von <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"z. B. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml
index 85923b7..10ddf62 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Δύο όψεων"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Προσανατολισμός"</string>
     <string name="label_pages" msgid="7768589729282182230">"Σελίδες"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Επιλέξτε εκτυπωτή"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Και οι <xliff:g id="PAGE_COUNT">%1$s</xliff:g> σελίδες"</string>
     <string name="template_page_range" msgid="428638530038286328">"Εύρος σελίδων από <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"π.χ. 1-5,8,11-13"</string>
diff --git a/packages/PrintSpooler/res/values-en-rAU/strings.xml b/packages/PrintSpooler/res/values-en-rAU/strings.xml
index 5ac14a3..a540ac5 100644
--- a/packages/PrintSpooler/res/values-en-rAU/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rAU/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Two-sided"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pages"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Select a printer"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"All <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Range of <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"e.g. 1–5,8,11–13"</string>
diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml
index 5ac14a3..a540ac5 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Two-sided"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pages"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Select a printer"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"All <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Range of <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"e.g. 1–5,8,11–13"</string>
diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml
index 5ac14a3..a540ac5 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Two-sided"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pages"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Select a printer"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"All <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Range of <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"e.g. 1–5,8,11–13"</string>
diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml
index 1876ae1..8929aa8 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Ambos lados"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientación"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páginas"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Seleccionar una impresora"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Todas (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="template_page_range" msgid="428638530038286328">"Rango de <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"Ej.: 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index 14ed0d8..7cfd92a 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dos caras"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientación"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páginas"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Elige una impresora"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Todas (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="template_page_range" msgid="428638530038286328">"Intervalo de <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"p. ej.: 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml
index c2843321..ee93bcf 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Kahepoolne"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Suund"</string>
     <string name="label_pages" msgid="7768589729282182230">"Lehed"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Printeri valimine"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Kõik <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Vahemik <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"nt 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-eu-rES/strings.xml b/packages/PrintSpooler/res/values-eu-rES/strings.xml
index eab7587..882e888 100644
--- a/packages/PrintSpooler/res/values-eu-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-eu-rES/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Bi aldekoa"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientazioa"</string>
     <string name="label_pages" msgid="7768589729282182230">"Orriak"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Hautatu inprimagailua"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> orriak"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> orriko tartea"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"adib., 1-5, 8,11-13"</string>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index 156eb47..10743e7 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"دوطرفه"</string>
     <string name="label_orientation" msgid="2853142581990496477">"جهت"</string>
     <string name="label_pages" msgid="7768589729282182230">"صفحه‌ها"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"چاپگری انتخاب کنید"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"همه <xliff:g id="PAGE_COUNT">%1$s</xliff:g> صفحه"</string>
     <string name="template_page_range" msgid="428638530038286328">"محدوده <xliff:g id="PAGE_COUNT">%1$s</xliff:g> صفحه"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"‏‏‎مثلاً ۱—۵،‏۹،۷—۱۰"</string>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index 887d428..ee35c41 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Kaksipuolinen"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Suunta"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sivut"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Valitse tulostin"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Kaikki <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Sivumäärä: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"esim. 1–5,8,11–13"</string>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index a97b20a..eb99441 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Recto verso"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pages"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Sélectionnez une imprimante"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Toutes (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="template_page_range" msgid="428638530038286328">"Plage de <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"p. ex. 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index 726915b..c0eecfb 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Recto verso"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pages"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Sélect. imprimante"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Toutes (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="template_page_range" msgid="428638530038286328">"Plage de <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ex. : 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-gl-rES/strings.xml b/packages/PrintSpooler/res/values-gl-rES/strings.xml
index 6a2d031..b4a1ec6 100644
--- a/packages/PrintSpooler/res/values-gl-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-gl-rES/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dual"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientación"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páxinas"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Escoller impresora"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"As <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Intervalo de <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ex.: 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-gu-rIN/strings.xml b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
index 3b3d2ed..8f77953 100644
--- a/packages/PrintSpooler/res/values-gu-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"દ્વિભુજ"</string>
     <string name="label_orientation" msgid="2853142581990496477">"ઓરિએન્ટેશન"</string>
     <string name="label_pages" msgid="7768589729282182230">"પૃષ્ઠો"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"પ્રિન્ટર પસંદ કરો"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"તમામ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ની શ્રેણી"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"દા.ત. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 162f65b..4c11323 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"दो-तरफ़ा"</string>
     <string name="label_orientation" msgid="2853142581990496477">"अभिविन्‍यास"</string>
     <string name="label_pages" msgid="7768589729282182230">"पृष्ठ"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"कोई प्रिंटर चुनें"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"सभी <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"पृष्ठ संख्या <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"उदा. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index 9276300..4cec3ba 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Obostrano"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orijentacija"</string>
     <string name="label_pages" msgid="7768589729282182230">"Stranice"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Odaberite pisač"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Sve stranice (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="template_page_range" msgid="428638530038286328">"Raspon od <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"npr. 1 – 5,8,11 – 13"</string>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index ca48f9a..ac1ba6e 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Kétoldalas"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Tájolás"</string>
     <string name="label_pages" msgid="7768589729282182230">"Oldalak"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Válasszon ki egy nyomtatót"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Összes (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> oldalas tartomány"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"pl. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
index a198277..dda6745 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Երկկողմանի"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Դիրքավորում"</string>
     <string name="label_pages" msgid="7768589729282182230">"Էջեր"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Ընտրել տպիչ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Բոլորը՝ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Միջակայքը՝ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"օր.՝ 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index 5050700..b203e2b 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Bersisi ganda"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientasi"</string>
     <string name="label_pages" msgid="7768589729282182230">"Halaman"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Pilih printer"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Semua dari <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Rentang dari <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"misalnya 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-is-rIS/strings.xml b/packages/PrintSpooler/res/values-is-rIS/strings.xml
index 33f10f5..6dfdabc 100644
--- a/packages/PrintSpooler/res/values-is-rIS/strings.xml
+++ b/packages/PrintSpooler/res/values-is-rIS/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Tvíhliða"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Stefna"</string>
     <string name="label_pages" msgid="7768589729282182230">"Síður"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Veldu prentara"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Allar <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"t.d. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index f7c6eff..fd5473a 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Con doppia funzione"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientamento"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pagine"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Seleziona stampante"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Tutte e <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Intervallo di <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"Es.: 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 545ba88..dd062a3 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"דו-צדדי"</string>
     <string name="label_orientation" msgid="2853142581990496477">"כיוון"</string>
     <string name="label_pages" msgid="7768589729282182230">"עמודים"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"בחר מדפסת"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"הכל <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"טווח של <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"למשל 1–5‏,8,‏11–13"</string>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index e292013..23e4809 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"両面"</string>
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
     <string name="label_pages" msgid="7768589729282182230">"ページ"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"プリンタを選択"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>ページすべて"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>ページ分"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"例: 1-5,8,11-13"</string>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index db71506..9f86f05 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"ორმხრივი"</string>
     <string name="label_orientation" msgid="2853142581990496477">"ორიენტაცია"</string>
     <string name="label_pages" msgid="7768589729282182230">"გვერდები"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"პრინტერის არჩევა"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ყველა <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>-ის არეალი"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"მაგ. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
index de2115a..05c300e 100644
--- a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
+++ b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Екі жақты"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Бағыты"</string>
     <string name="label_pages" msgid="7768589729282182230">"Беттер"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Принтерді таңдау"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Барлық <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ауқымы"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"мысалы, 1—5,8,11—13"</string>
@@ -60,8 +61,7 @@
     </plurals>
     <string name="choose_print_service" msgid="3740309762324459694">"Принтер қызметін таңдау"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Принтерлерді іздеу"</string>
-    <!-- no translation found for print_no_print_services (8561247706423327966) -->
-    <skip />
+    <string name="print_no_print_services" msgid="8561247706423327966">"Басып шығару қызметтері қосылмаған"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Ешқандай принтер табылмады"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> басып шығарылуда"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> жұмысын тоқтатуда"</string>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index c91e6ae..0861e59 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"សងខាង"</string>
     <string name="label_orientation" msgid="2853142581990496477">"ទិស"</string>
     <string name="label_pages" msgid="7768589729282182230">"ទំព័រ"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"ជ្រើសម៉ាស៊ីនបោះពុម្ព"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ទាំងអស់"</string>
     <string name="template_page_range" msgid="428638530038286328">"ជួរ​នៃ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ឧ. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-kn-rIN/strings.xml b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
index 86dc11f..71b098d 100644
--- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"ಎರಡು ಬದಿ"</string>
     <string name="label_orientation" msgid="2853142581990496477">"ಓರಿಯಂಟೇಶನ್"</string>
     <string name="label_pages" msgid="7768589729282182230">"ಪುಟಗಳು"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"ಪ್ರಿಂಟರ್ ಆಯ್ಕೆ ಮಾಡಿ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ಎಲ್ಲಾ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ನ ಶ್ರೇಣಿ"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ಉದಾ. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index 4450bca..451ab58 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"양면"</string>
     <string name="label_orientation" msgid="2853142581990496477">"방향"</string>
     <string name="label_pages" msgid="7768589729282182230">"페이지"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"프린터 선택"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>페이지 모두"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>페이지 범위"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"예: 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-ky-rKG/strings.xml b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
index b4bdc57..98da08c 100644
--- a/packages/PrintSpooler/res/values-ky-rKG/strings.xml
+++ b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Эки тараптуу"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Багыттоо"</string>
     <string name="label_pages" msgid="7768589729282182230">"Баракчалар"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Принтер тандаңыз"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Бардыгы <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> аралыгы"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"мис. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
index 500f01c..2029fdf 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"ສອງ​ດ້ານ"</string>
     <string name="label_orientation" msgid="2853142581990496477">"ລວງ"</string>
     <string name="label_pages" msgid="7768589729282182230">"ໜ້າ"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"ເລືອກເຄື່ອງພິມ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ທັງ​ໝົດ <xliff:g id="PAGE_COUNT">%1$s</xliff:g> ໜ້າ"</string>
     <string name="template_page_range" msgid="428638530038286328">"ໄລ​ຍະ <xliff:g id="PAGE_COUNT">%1$s</xliff:g> ໜ້າ"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ຕົວຢ່າງ: 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index ad59182..972abb5 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dvipusis"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientacija"</string>
     <string name="label_pages" msgid="7768589729282182230">"Puslapiai"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Spausdint. pasirink."</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Visi <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Diapazonas: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"pvz., 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index 3b30d04..f565b23 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Divpusējs"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Virziens"</string>
     <string name="label_pages" msgid="7768589729282182230">"Lapas"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Atlasīt printeri"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Visas <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Diapazons: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"piem., 1–5,8,11–13"</string>
diff --git a/packages/PrintSpooler/res/values-mk-rMK/strings.xml b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
index 42548fc..f5c06d1 100644
--- a/packages/PrintSpooler/res/values-mk-rMK/strings.xml
+++ b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Двостран"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Ориентација"</string>
     <string name="label_pages" msgid="7768589729282182230">"Страници"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Избери печатач"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Сите <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Опсег од <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"на пр.: 1-5,8,11-13"</string>
diff --git a/packages/PrintSpooler/res/values-ml-rIN/strings.xml b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
index 4e5a99c..2d45ce5 100644
--- a/packages/PrintSpooler/res/values-ml-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"രണ്ട് വശങ്ങളുള്ളത്"</string>
     <string name="label_orientation" msgid="2853142581990496477">"ഓറിയന്‍റേഷന്‍‌"</string>
     <string name="label_pages" msgid="7768589729282182230">"പേജുകൾ"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"ഒരു പ്രിന്റർ തിരഞ്ഞെടുക്കുക"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"എല്ലാ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> എന്നതിന്റെ പരിധി"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ഉദാ. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
index 0f49671..f2c7b73 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Хоёр талт"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Чиглэл"</string>
     <string name="label_pages" msgid="7768589729282182230">"Хуудас"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Хэвлэгчийг сонгоно уу"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Нийт <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Хүрээ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ж.нь. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-mr-rIN/strings.xml b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
index 53225ee..1c079dc 100644
--- a/packages/PrintSpooler/res/values-mr-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"दोन्ही बाजूंनी"</string>
     <string name="label_orientation" msgid="2853142581990496477">"अभिमुखता"</string>
     <string name="label_pages" msgid="7768589729282182230">"पृष्ठे"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"प्रिंटर निवडा"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"सर्व <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ची श्रेणी"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"उदा. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index a15587b..d6b5ea7 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dua sisi"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientasi"</string>
     <string name="label_pages" msgid="7768589729282182230">"Halaman"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Pilih pencetak"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Semua <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Julat <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"cth. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-my-rMM/strings.xml b/packages/PrintSpooler/res/values-my-rMM/strings.xml
index 10dc93a..c3dc490 100644
--- a/packages/PrintSpooler/res/values-my-rMM/strings.xml
+++ b/packages/PrintSpooler/res/values-my-rMM/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"နှစ်ဖက်လှ"</string>
     <string name="label_orientation" msgid="2853142581990496477">"အနေအထား"</string>
     <string name="label_pages" msgid="7768589729282182230">"စာမျက်နှာများ"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"ပုံနှိပ်စက်ကို ရွေးပါ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"အားလုံး <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>ဘောင် ထဲမှာ"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ဥပမာ ၁-၅၊ ၈၊ ၁၁-၁၃"</string>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index 8cbcee7..945bbea 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Tosidig"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Retning"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sider"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Velg en skriver"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Alle <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Område på <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"f.eks. 1–5, 8,11–13"</string>
diff --git a/packages/PrintSpooler/res/values-ne-rNP/strings.xml b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
index ad9b4e3..34c1dd4f 100644
--- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml
+++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
@@ -27,6 +27,8 @@
     <string name="label_duplex" msgid="5370037254347072243">"दुई-पक्षीय"</string>
     <string name="label_orientation" msgid="2853142581990496477">"अभिमुखिकरण"</string>
     <string name="label_pages" msgid="7768589729282182230">"पृष्ठहरू"</string>
+    <!-- no translation found for destination_default_text (5422708056807065710) -->
+    <skip />
     <string name="template_all_pages" msgid="3322235982020148762">"सबै <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> को सीमा"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"उदाहरण १-५,८,११-१३"</string>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index bb8391e..76c8656 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dubbelzijdig"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Stand"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pagina\'s"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Printer selecteren"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Alle <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Bereik van <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"bijv. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-pa-rIN/strings.xml b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
index aede004..45fa460 100644
--- a/packages/PrintSpooler/res/values-pa-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"ਦੋ-ਪਾਸੇ ਦਾ"</string>
     <string name="label_orientation" msgid="2853142581990496477">"ਅਨੁਕੂਲਨ"</string>
     <string name="label_pages" msgid="7768589729282182230">"ਸਫ਼ੇ"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"ਇੱਕ ਪ੍ਰਿੰਟਰ ਚੁਣੋ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ਸਾਰੇ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ਦੀ ਰੇਂਜ"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ਉਦਾਹਰਨ ਲਈ 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index 4e20eed..df3ee924 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dwustronny"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientacja"</string>
     <string name="label_pages" msgid="7768589729282182230">"Strony"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Wybierz drukarkę"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Wszystkie <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Zakres <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"np. 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rBR/strings.xml b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
index 7ab0f0a..90da72b 100644
--- a/packages/PrintSpooler/res/values-pt-rBR/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dois lados"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientação"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páginas"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Selec. impressora"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Todas as <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Intervalo de <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"Ex.: 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 583052a..99bbd81 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dois lados"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientação"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páginas"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Selec. impressora"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Todas as <xliff:g id="PAGE_COUNT">%1$s</xliff:g> páginas"</string>
     <string name="template_page_range" msgid="428638530038286328">"Intervalo de <xliff:g id="PAGE_COUNT">%1$s</xliff:g> pág."</string>
     <string name="pages_range_example" msgid="8558694453556945172">"p. ex. 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml
index 7ab0f0a..90da72b 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dois lados"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientação"</string>
     <string name="label_pages" msgid="7768589729282182230">"Páginas"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Selec. impressora"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Todas as <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Intervalo de <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"Ex.: 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml
index 2769aae..4cfb8ab 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Față-verso"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientare"</string>
     <string name="label_pages" msgid="7768589729282182230">"Pagini"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Selectați imprimanta"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Toate cele <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Intervalul de <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"de ex. 1-5, 8, 11-13"</string>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index c3cfac0..fb49330 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Двусторонний"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Ориентация"</string>
     <string name="label_pages" msgid="7768589729282182230">"Страницы"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Выберите принтер"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Все <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Диапазон <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"напр., 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-si-rLK/strings.xml b/packages/PrintSpooler/res/values-si-rLK/strings.xml
index 0e20705..fb6f145 100644
--- a/packages/PrintSpooler/res/values-si-rLK/strings.xml
+++ b/packages/PrintSpooler/res/values-si-rLK/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"පැති-දෙකක"</string>
     <string name="label_orientation" msgid="2853142581990496477">"දිශානතිය"</string>
     <string name="label_pages" msgid="7768589729282182230">"පිටු"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"මුද්‍රණ යන්ත්‍රයක් තෝරන්න"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"සියලුම <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> පරාසය"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"උ.දා. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index b8d2167..605237b 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Obojstranné"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientácia"</string>
     <string name="label_pages" msgid="7768589729282182230">"Strany"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Výber tlačiarne"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Všetky: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Rozsah: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"napr. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index a320e79b..48d2e1d 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dvostransko"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Postavitev"</string>
     <string name="label_pages" msgid="7768589729282182230">"Strani"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Izberite tiskalnik"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Vse (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="template_page_range" msgid="428638530038286328">"Obseg strani: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"npr. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-sq-rAL/strings.xml b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
index 177b282..5ba72ff 100644
--- a/packages/PrintSpooler/res/values-sq-rAL/strings.xml
+++ b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Në dy anë"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientimi"</string>
     <string name="label_pages" msgid="7768589729282182230">"Faqe"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Zgjidh një printer"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Të <xliff:g id="PAGE_COUNT">%1$s</xliff:g> faqet"</string>
     <string name="template_page_range" msgid="428638530038286328">"Gama e faqeve: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"p.sh. 1 - 5,8,11 - 13"</string>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index f686e6d..7a04b8d 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Двострано"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Положај"</string>
     <string name="label_pages" msgid="7768589729282182230">"Странице"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Изаберите штампач"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Све странице (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="template_page_range" msgid="428638530038286328">"Опсег од <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"нпр. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index 6e176f03..ec4ad30 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Dubbelsidig"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Orientering"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sidor"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Välj skrivare"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Alla <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Intervall på <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"t.ex. 1–5,8,11–13"</string>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 8ce9190..eed3356 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Yenye pande mbili"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Mkao"</string>
     <string name="label_pages" msgid="7768589729282182230">"Kurasa"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Chagua printa"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Kurasa zote <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Mfululizo wa <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"k.m. 1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-ta-rIN/strings.xml b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
index 486ddca..a9879c3 100644
--- a/packages/PrintSpooler/res/values-ta-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"இரு பக்க முறை"</string>
     <string name="label_orientation" msgid="2853142581990496477">"திசையமைப்பு"</string>
     <string name="label_pages" msgid="7768589729282182230">"பக்கங்கள்"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"பிரிண்டரை தேர்ந்தெடு"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"எல்லாம்: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"வரம்பில்: <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"எ.கா. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-te-rIN/strings.xml b/packages/PrintSpooler/res/values-te-rIN/strings.xml
index f0f7e07..909cb90 100644
--- a/packages/PrintSpooler/res/values-te-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-te-rIN/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"రెండు వైపుల"</string>
     <string name="label_orientation" msgid="2853142581990496477">"దృగ్విన్యాసం"</string>
     <string name="label_pages" msgid="7768589729282182230">"పేజీలు"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"ప్రింటర్ ఎంచుకోండి"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"మొత్తం <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> పరిధి"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ఉదా. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index d3ef7c6..c33a759 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"2 ด้าน"</string>
     <string name="label_orientation" msgid="2853142581990496477">"การวางแนว"</string>
     <string name="label_pages" msgid="7768589729282182230">"หน้า"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"เลือกเครื่องพิมพ์"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ทั้ง <xliff:g id="PAGE_COUNT">%1$s</xliff:g> หน้า"</string>
     <string name="template_page_range" msgid="428638530038286328">"ช่วง <xliff:g id="PAGE_COUNT">%1$s</xliff:g> หน้า"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"เช่น 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index 061eeb9..545bda4 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Two-sided"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Oryentasyon"</string>
     <string name="label_pages" msgid="7768589729282182230">"Mga Page"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Pumili ng printer"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Lahat ng <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Hanay ng <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"hal. 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index db203ae..a13f2df 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Çift taraflı"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Sayfa yönü"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sayfa"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Yazıcı seçin"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> sayfanın tamamı"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> sayfalık aralık"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"ör. 1-5,8,11-13"</string>
diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml
index 09c0555..def21ab 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Двосторонній друк"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Орієнтація"</string>
     <string name="label_pages" msgid="7768589729282182230">"Сторінки"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Виберіть принтер"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Усі <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Діапазон <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"напр.,1–5, 8, 11–13"</string>
diff --git a/packages/PrintSpooler/res/values-ur-rPK/strings.xml b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
index 44ca82b..c031aba 100644
--- a/packages/PrintSpooler/res/values-ur-rPK/strings.xml
+++ b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"دو طرف"</string>
     <string name="label_orientation" msgid="2853142581990496477">"سمت بندی"</string>
     <string name="label_pages" msgid="7768589729282182230">"صفحات"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"ایک پرنٹر منتخب کریں"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"سبھی <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> کی رینج"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"‏مثلاً ‎1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
index 477e424..9d615fb 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Ikki tomonlama"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Joylashuv"</string>
     <string name="label_pages" msgid="7768589729282182230">"Sahifalar"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Printer tanlash"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Barchasi (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="template_page_range" msgid="428638530038286328">"O‘zgarish chegarasi (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"masalan: 1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml
index 3428ec7..0167823 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Hai mặt"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Hướng"</string>
     <string name="label_pages" msgid="7768589729282182230">"Trang"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Chọn máy in"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Tất cả <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Phạm vi <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"Ví dụ: 1—5, 8, 11—13"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index d1be250..f2b304a 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -27,6 +27,8 @@
     <string name="label_duplex" msgid="5370037254347072243">"双面"</string>
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
     <string name="label_pages" msgid="7768589729282182230">"页数"</string>
+    <!-- no translation found for destination_default_text (5422708056807065710) -->
+    <skip />
     <string name="template_all_pages" msgid="3322235982020148762">"全部<xliff:g id="PAGE_COUNT">%1$s</xliff:g>页"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g>页"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"例如:1-5、8、11-13"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index bca0612..35643f3 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"雙面"</string>
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
     <string name="label_pages" msgid="7768589729282182230">"頁數"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"選擇打印機"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"全部 <xliff:g id="PAGE_COUNT">%1$s</xliff:g> 頁"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> 頁"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"例如:1-5,8,11-13"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index c345252..40c44ff 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"雙面"</string>
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
     <string name="label_pages" msgid="7768589729282182230">"頁面"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"選取印表機"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"全部 <xliff:g id="PAGE_COUNT">%1$s</xliff:g> 頁"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> 頁"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"例如:1—5,8,11—13"</string>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index 7ba8950..e0f6f34 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -27,6 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"Inezinhlangothi ezimbili"</string>
     <string name="label_orientation" msgid="2853142581990496477">"Umumo"</string>
     <string name="label_pages" msgid="7768589729282182230">"Amakhasi"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"Khetha iphrinta"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"Konke <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"Ibanga le-<xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"isb. 1—5, 8, 11—13"</string>
@@ -60,7 +61,7 @@
     </plurals>
     <string name="choose_print_service" msgid="3740309762324459694">"Khetha isevisi yephrinta"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Isesha amaphrinta"</string>
-    <string name="print_no_print_services" msgid="8561247706423327966">"Awekho amasevisi okuphrinta enikwe amandla"</string>
+    <string name="print_no_print_services" msgid="8561247706423327966">"Amasevisi ephrinta akavuliwe."</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Awekho amaphrinta atholiwe"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Iphrinta i-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Ikhansela i-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java b/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java
new file mode 100644
index 0000000..ef511bb
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java
@@ -0,0 +1,269 @@
+/*
+ * 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.settingslib.accounts;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AuthenticatorDescription;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SyncAdapterType;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.UserHandle;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Helper class for monitoring accounts on the device for a given user.
+ *
+ * Classes using this helper should implement {@link OnAccountsUpdateListener}.
+ * {@link OnAccountsUpdateListener#onAccountsUpdate(UserHandle)} will then be
+ * called once accounts get updated. For setting up listening for account
+ * updates, {@link #listenToAccountUpdates()} and
+ * {@link #stopListeningToAccountUpdates()} should be used.
+ */
+final public class AuthenticatorHelper extends BroadcastReceiver {
+    private static final String TAG = "AuthenticatorHelper";
+
+    private final Map<String, AuthenticatorDescription> mTypeToAuthDescription = new HashMap<>();
+    private final ArrayList<String> mEnabledAccountTypes = new ArrayList<>();
+    private final Map<String, Drawable> mAccTypeIconCache = new HashMap<>();
+    private final HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = new HashMap<>();
+
+    private final UserHandle mUserHandle;
+    private final Context mContext;
+    private final OnAccountsUpdateListener mListener;
+    private boolean mListeningToAccountUpdates;
+
+    public interface OnAccountsUpdateListener {
+        void onAccountsUpdate(UserHandle userHandle);
+    }
+
+    public AuthenticatorHelper(Context context, UserHandle userHandle,
+            OnAccountsUpdateListener listener) {
+        mContext = context;
+        mUserHandle = userHandle;
+        mListener = listener;
+        // This guarantees that the helper is ready to use once constructed: the account types and
+        // authorities are initialized
+        onAccountsUpdated(null);
+    }
+
+    public String[] getEnabledAccountTypes() {
+        return mEnabledAccountTypes.toArray(new String[mEnabledAccountTypes.size()]);
+    }
+
+    public void preloadDrawableForType(final Context context, final String accountType) {
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                getDrawableForType(context, accountType);
+                return null;
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+    }
+
+    /**
+     * Gets an icon associated with a particular account type. If none found, return null.
+     * @param accountType the type of account
+     * @return a drawable for the icon or a default icon returned by
+     * {@link PackageManager#getDefaultActivityIcon} if one cannot be found.
+     */
+    public Drawable getDrawableForType(Context context, final String accountType) {
+        Drawable icon = null;
+        synchronized (mAccTypeIconCache) {
+            if (mAccTypeIconCache.containsKey(accountType)) {
+                return mAccTypeIconCache.get(accountType);
+            }
+        }
+        if (mTypeToAuthDescription.containsKey(accountType)) {
+            try {
+                AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+                Context authContext = context.createPackageContextAsUser(desc.packageName, 0,
+                        mUserHandle);
+                icon = mContext.getPackageManager().getUserBadgedIcon(
+                        authContext.getDrawable(desc.iconId), mUserHandle);
+                synchronized (mAccTypeIconCache) {
+                    mAccTypeIconCache.put(accountType, icon);
+                }
+            } catch (PackageManager.NameNotFoundException|Resources.NotFoundException e) {
+                // Ignore
+            }
+        }
+        if (icon == null) {
+            icon = context.getPackageManager().getDefaultActivityIcon();
+        }
+        return icon;
+    }
+
+    /**
+     * Gets the label associated with a particular account type. If none found, return null.
+     * @param accountType the type of account
+     * @return a CharSequence for the label or null if one cannot be found.
+     */
+    public CharSequence getLabelForType(Context context, final String accountType) {
+        CharSequence label = null;
+        if (mTypeToAuthDescription.containsKey(accountType)) {
+            try {
+                AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+                Context authContext = context.createPackageContextAsUser(desc.packageName, 0,
+                        mUserHandle);
+                label = authContext.getResources().getText(desc.labelId);
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.w(TAG, "No label name for account type " + accountType);
+            } catch (Resources.NotFoundException e) {
+                Log.w(TAG, "No label icon for account type " + accountType);
+            }
+        }
+        return label;
+    }
+
+    /**
+     * Gets the package associated with a particular account type. If none found, return null.
+     * @param accountType the type of account
+     * @return the package name or null if one cannot be found.
+     */
+    public String getPackageForType(final String accountType) {
+        if (mTypeToAuthDescription.containsKey(accountType)) {
+            AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+            return desc.packageName;
+        }
+        return null;
+    }
+
+    /**
+     * Gets the resource id of the label associated with a particular account type. If none found,
+     * return -1.
+     * @param accountType the type of account
+     * @return a resource id for the label or -1 if none found;
+     */
+    public int getLabelIdForType(final String accountType) {
+        if (mTypeToAuthDescription.containsKey(accountType)) {
+            AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+            return desc.labelId;
+        }
+        return -1;
+    }
+
+    /**
+     * Updates provider icons. Subclasses should call this in onCreate()
+     * and update any UI that depends on AuthenticatorDescriptions in onAuthDescriptionsUpdated().
+     */
+    public void updateAuthDescriptions(Context context) {
+        AuthenticatorDescription[] authDescs = AccountManager.get(context)
+                .getAuthenticatorTypesAsUser(mUserHandle.getIdentifier());
+        for (int i = 0; i < authDescs.length; i++) {
+            mTypeToAuthDescription.put(authDescs[i].type, authDescs[i]);
+        }
+    }
+
+    public boolean containsAccountType(String accountType) {
+        return mTypeToAuthDescription.containsKey(accountType);
+    }
+
+    public AuthenticatorDescription getAccountTypeDescription(String accountType) {
+        return mTypeToAuthDescription.get(accountType);
+    }
+
+    public boolean hasAccountPreferences(final String accountType) {
+        if (containsAccountType(accountType)) {
+            AuthenticatorDescription desc = getAccountTypeDescription(accountType);
+            if (desc != null && desc.accountPreferencesId != 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void onAccountsUpdated(Account[] accounts) {
+        updateAuthDescriptions(mContext);
+        if (accounts == null) {
+            accounts = AccountManager.get(mContext).getAccountsAsUser(mUserHandle.getIdentifier());
+        }
+        mEnabledAccountTypes.clear();
+        mAccTypeIconCache.clear();
+        for (int i = 0; i < accounts.length; i++) {
+            final Account account = accounts[i];
+            if (!mEnabledAccountTypes.contains(account.type)) {
+                mEnabledAccountTypes.add(account.type);
+            }
+        }
+        buildAccountTypeToAuthoritiesMap();
+        if (mListeningToAccountUpdates) {
+            mListener.onAccountsUpdate(mUserHandle);
+        }
+    }
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        // TODO: watch for package upgrades to invalidate cache; see http://b/7206643
+        final Account[] accounts = AccountManager.get(mContext)
+                .getAccountsAsUser(mUserHandle.getIdentifier());
+        onAccountsUpdated(accounts);
+    }
+
+    public void listenToAccountUpdates() {
+        if (!mListeningToAccountUpdates) {
+            IntentFilter intentFilter = new IntentFilter();
+            intentFilter.addAction(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
+            // At disk full, certain actions are blocked (such as writing the accounts to storage).
+            // It is useful to also listen for recovery from disk full to avoid bugs.
+            intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
+            mContext.registerReceiverAsUser(this, mUserHandle, intentFilter, null, null);
+            mListeningToAccountUpdates = true;
+        }
+    }
+
+    public void stopListeningToAccountUpdates() {
+        if (mListeningToAccountUpdates) {
+            mContext.unregisterReceiver(this);
+            mListeningToAccountUpdates = false;
+        }
+    }
+
+    public ArrayList<String> getAuthoritiesForAccountType(String type) {
+        return mAccountTypeToAuthorities.get(type);
+    }
+
+    private void buildAccountTypeToAuthoritiesMap() {
+        mAccountTypeToAuthorities.clear();
+        SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(
+                mUserHandle.getIdentifier());
+        for (int i = 0, n = syncAdapters.length; i < n; i++) {
+            final SyncAdapterType sa = syncAdapters[i];
+            ArrayList<String> authorities = mAccountTypeToAuthorities.get(sa.accountType);
+            if (authorities == null) {
+                authorities = new ArrayList<String>();
+                mAccountTypeToAuthorities.put(sa.accountType, authorities);
+            }
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, "Added authority " + sa.authority + " to accountType "
+                        + sa.accountType);
+            }
+            authorities.add(sa.authority);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java b/packages/SettingsLib/src/com/android/settingslib/net/MobileDataController.java
similarity index 92%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java
rename to packages/SettingsLib/src/com/android/settingslib/net/MobileDataController.java
index a7fdadc..642b60e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/MobileDataController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,14 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
-
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
-import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
-import static android.telephony.TelephonyManager.SIM_STATE_READY;
-import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
-import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
+package com.android.settingslib.net;
 
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -42,7 +35,14 @@
 import java.util.Date;
 import java.util.Locale;
 
-public class MobileDataControllerImpl implements NetworkController.MobileDataController {
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
+import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
+import static android.telephony.TelephonyManager.SIM_STATE_READY;
+import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
+import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
+
+public class MobileDataController {
     private static final String TAG = "MobileDataController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -60,9 +60,9 @@
 
     private INetworkStatsSession mSession;
     private Callback mCallback;
-    private NetworkControllerImpl mNetworkController;
+    private NetworkNameProvider mNetworkController;
 
-    public MobileDataControllerImpl(Context context) {
+    public MobileDataController(Context context) {
         mContext = context;
         mTelephonyManager = TelephonyManager.from(context);
         mConnectivityManager = ConnectivityManager.from(context);
@@ -71,7 +71,7 @@
         mPolicyManager = NetworkPolicyManager.from(mContext);
     }
 
-    public void setNetworkController(NetworkControllerImpl networkController) {
+    public void setNetworkController(NetworkNameProvider networkController) {
         mNetworkController = networkController;
     }
 
@@ -161,7 +161,7 @@
             } else {
                 usage.warningLevel = DEFAULT_WARNING_LEVEL;
             }
-            if (usage != null) {
+            if (usage != null && mNetworkController != null) {
                 usage.carrier = mNetworkController.getMobileDataNetworkName();
             }
             return usage;
@@ -231,6 +231,18 @@
         }
     }
 
+    public interface NetworkNameProvider {
+        String getMobileDataNetworkName();
+    }
+
+    public static class DataUsageInfo {
+        public String carrier;
+        public String period;
+        public long limitLevel;
+        public long warningLevel;
+        public long usageLevel;
+    }
+
     public interface Callback {
         void onMobileDataEnabled(boolean enabled);
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/AnimatedImageView.java b/packages/SettingsLib/src/com/android/settingslib/widget/AnimatedImageView.java
new file mode 100644
index 0000000..f5e39be
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/AnimatedImageView.java
@@ -0,0 +1,100 @@
+/*
+ * 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.settingslib.widget;
+
+import android.content.Context;
+import android.graphics.drawable.AnimatedRotateDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+
+public class AnimatedImageView extends ImageView {
+    private AnimatedRotateDrawable mDrawable;
+    private boolean mAnimating;
+
+    public AnimatedImageView(Context context) {
+        super(context);
+    }
+
+    public AnimatedImageView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    private void updateDrawable() {
+        if (isShown() && mDrawable != null) {
+            mDrawable.stop();
+        }
+        final Drawable drawable = getDrawable();
+        if (drawable instanceof AnimatedRotateDrawable) {
+            mDrawable = (AnimatedRotateDrawable) drawable;
+            // TODO: define in drawable xml once we have public attrs.
+            mDrawable.setFramesCount(56);
+            mDrawable.setFramesDuration(32);
+            if (isShown() && mAnimating) {
+                mDrawable.start();
+            }
+        } else {
+            mDrawable = null;
+        }
+    }
+
+    private void updateAnimating() {
+        if (mDrawable != null) {
+            if (isShown() && mAnimating) {
+                mDrawable.start();
+            } else {
+                mDrawable.stop();
+            }
+        }
+    }
+
+    @Override
+    public void setImageDrawable(Drawable drawable) {
+        super.setImageDrawable(drawable);
+        updateDrawable();
+    }
+
+    @Override
+    public void setImageResource(int resid) {
+        super.setImageResource(resid);
+        updateDrawable();
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        updateAnimating();
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        updateAnimating();
+    }
+
+    public void setAnimating(boolean animating) {
+        mAnimating = animating;
+        updateAnimating();
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int vis) {
+        super.onVisibilityChanged(changedView, vis);
+        updateAnimating();
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
new file mode 100644
index 0000000..fabae57
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -0,0 +1,79 @@
+/*
+ * 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.settingslib.wifi;
+
+import android.content.Intent;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+
+import java.util.List;
+
+public class WifiStatusTracker {
+
+    private final WifiManager mWifiManager;
+    public boolean enabled;
+    public boolean connected;
+    public String ssid;
+    public int rssi;
+    public int level;
+
+    public WifiStatusTracker(WifiManager wifiManager) {
+        mWifiManager = wifiManager;
+    }
+
+    public void handleBroadcast(Intent intent) {
+        String action = intent.getAction();
+        if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+            enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                    WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
+        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+            final NetworkInfo networkInfo = (NetworkInfo)
+                    intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+            connected = networkInfo != null && networkInfo.isConnected();
+            // If Connected grab the signal strength and ssid.
+            if (connected) {
+                // try getting it out of the intent first
+                WifiInfo info = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) != null
+                        ? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO)
+                        : mWifiManager.getConnectionInfo();
+                if (info != null) {
+                    ssid = getSsid(info);
+                } else {
+                    ssid = null;
+                }
+            } else if (!connected) {
+                ssid = null;
+            }
+        } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
+            // Default to -200 as its below WifiManager.MIN_RSSI.
+            rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
+            level = WifiManager.calculateSignalLevel(rssi, 5);
+        }
+    }
+
+    private String getSsid(WifiInfo info) {
+        String ssid = info.getSSID();
+        if (ssid != null) {
+            return ssid;
+        }
+        // OK, it's not in the connectionInfo; we have to go hunting for it
+        List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
+        int length = networks.size();
+        for (int i = 0; i < length; i++) {
+            if (networks.get(i).networkId == info.getNetworkId()) {
+                return networks.get(i).SSID;
+            }
+        }
+        return null;
+    }
+}
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d5f9557e..00b10a1 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1067,6 +1067,9 @@
     <!-- Name of status bar -->
     <string name="status_bar">Status bar</string>
 
+    <!-- Name of overview -->
+    <string name="overview">Overview</string>
+
     <!-- Name of demo mode (mode with preset icons for screenshots) -->
     <string name="demo_mode">Demo mode</string>
 
@@ -1156,6 +1159,11 @@
     <!-- Option to use new paging layout in quick settings [CHAR LIMIT=60] -->
     <string name="qs_paging" translatable="false">Use the new Quick Settings</string>
 
+    <!-- Toggles fast-toggling recents via the recents button -->
+    <string name="overview_fast_toggle_via_button">Enable fast toggle</string>
+    <!-- Description for the toggle for fast-toggling recents via the recents button -->
+    <string name="overview_fast_toggle_via_button_desc">Enable paging via the Overview button</string>
+
     <!-- Category in the System UI Tuner settings, where new/experimental
          settings are -->
     <string name="experimental">Experimental</string>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 5980108..c36cab8 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -87,6 +87,17 @@
 
     </PreferenceScreen>
 
+
+    <PreferenceScreen
+        android:title="@string/overview" >
+
+        <com.android.systemui.tuner.TunerSwitch
+            android:key="overview_fast_toggle"
+            android:title="@string/overview_fast_toggle_via_button"
+            android:summary="@string/overview_fast_toggle_via_button_desc" />
+
+    </PreferenceScreen>
+
     <SwitchPreference
         android:key="battery_pct"
         android:title="@string/show_battery_percentage"
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 3657cf2..9d98772 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -30,7 +30,8 @@
 
     @Retention(RetentionPolicy.SOURCE)
     @StringDef({
-        Key.SEARCH_APP_WIDGET_ID,
+        Key.OVERVIEW_SEARCH_APP_WIDGET_ID,
+        Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE,
         Key.DEBUG_MODE_ENABLED,
         Key.HOTSPOT_TILE_LAST_USED,
         Key.COLOR_INVERSION_TILE_LAST_USED,
@@ -43,8 +44,8 @@
         Key.DND_FAVORITE_ZEN,
     })
     public @interface Key {
-        String SEARCH_APP_WIDGET_ID = "searchAppWidgetId";
-        String SEARCH_APP_WIDGET_PACKAGE = "searchAppWidgetPackage";
+        String OVERVIEW_SEARCH_APP_WIDGET_ID = "searchAppWidgetId";
+        String OVERVIEW_SEARCH_APP_WIDGET_PACKAGE = "searchAppWidgetPackage";
         String DEBUG_MODE_ENABLED = "debugModeEnabled";
         String HOTSPOT_TILE_LAST_USED = "HotspotTileLastUsed";
         String COLOR_INVERSION_TILE_LAST_USED = "ColorInversionTileLastUsed";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index e2d2ffb..a0bbbe3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -23,16 +23,14 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-
 import com.android.internal.logging.MetricsLogger;
+import com.android.settingslib.net.MobileDataController;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.QSTileBaseView;
 import com.android.systemui.qs.SignalTileView;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
-import com.android.systemui.statusbar.policy.NetworkController.MobileDataController;
-import com.android.systemui.statusbar.policy.NetworkController.MobileDataController.DataUsageInfo;
 import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
 
 /** Quick settings tile: Cellular **/
@@ -247,7 +245,7 @@
             final DataUsageDetailView v = (DataUsageDetailView) (convertView != null
                     ? convertView
                     : LayoutInflater.from(mContext).inflate(R.layout.data_usage, parent, false));
-            final DataUsageInfo info = mDataController.getDataUsageInfo();
+            final MobileDataController.DataUsageInfo info = mDataController.getDataUsageInfo();
             if (info == null) return v;
             v.bind(info);
             return v;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index d0ae383..d814b1c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -23,11 +23,10 @@
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.TextView;
-
+import com.android.settingslib.net.MobileDataController;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.qs.DataUsageGraph;
-import com.android.systemui.statusbar.policy.NetworkController;
 
 import java.text.DecimalFormat;
 
@@ -60,7 +59,7 @@
                 R.dimen.qs_data_usage_text_size);
     }
 
-    public void bind(NetworkController.MobileDataController.DataUsageInfo info) {
+    public void bind(MobileDataController.DataUsageInfo info) {
         final Resources res = mContext.getResources();
         final int titleId;
         final long bytes;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index a429447..c08fb05 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -29,34 +29,4 @@
         public static final int DismissSourceHeaderButton = 2;
     }
 
-    // TODO: Move into RecentsDebugFlags
-    public static class DebugFlags {
-
-        public static class App {
-            // Enables debug drawing for the transition thumbnail
-            public static final boolean EnableTransitionThumbnailDebugMode = false;
-            // Enables the filtering of tasks according to their grouping
-            public static final boolean EnableTaskFiltering = false;
-            // Enables dismiss-all
-            public static final boolean EnableDismissAll = false;
-            // Enables fast-toggling by just tapping on the recents button
-            public static final boolean EnableFastToggleRecents = false;
-            // Enables the thumbnail alpha on the front-most task
-            public static final boolean EnableThumbnailAlphaOnFrontmost = false;
-            // This disables the search bar integration
-            public static final boolean DisableSearchBar = true;
-            // This disables the bitmap and icon caches
-            public static final boolean DisableBackgroundCache = false;
-            // Enables the simulated task affiliations
-            public static final boolean EnableSimulatedTaskGroups = false;
-            // Defines the number of mock task affiliations per group
-            public static final int TaskAffiliationsGroupCount = 12;
-            // Enables us to create mock recents tasks
-            public static final boolean EnableSystemServicesProxy = false;
-            // Defines the number of mock recents packages to create
-            public static final int SystemServicesProxyMockPackageCount = 3;
-            // Defines the number of mock recents tasks to create
-            public static final int SystemServicesProxyMockTaskCount = 100;
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 95f1eb2..3806b46 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -62,6 +62,7 @@
     private final static String ACTION_TOGGLE_RECENTS = "com.android.systemui.recents.ACTION_TOGGLE";
 
     private static SystemServicesProxy sSystemServicesProxy;
+    private static RecentsDebugFlags sDebugFlags;
     private static RecentsTaskLoader sTaskLoader;
     private static RecentsConfiguration sConfiguration;
 
@@ -148,8 +149,13 @@
         return sConfiguration;
     }
 
+    public static RecentsDebugFlags getDebugFlags() {
+        return sDebugFlags;
+    }
+
     @Override
     public void start() {
+        sDebugFlags = new RecentsDebugFlags(mContext);
         sSystemServicesProxy = new SystemServicesProxy(mContext);
         sTaskLoader = new RecentsTaskLoader(mContext);
         sConfiguration = new RecentsConfiguration(mContext);
@@ -166,6 +172,7 @@
 
         // Register with the event bus
         EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
+        EventBus.getDefault().register(sSystemServicesProxy, EVENT_BUS_PRIORITY);
         EventBus.getDefault().register(sTaskLoader, EVENT_BUS_PRIORITY);
 
         // Due to the fact that RecentsActivity is per-user, we need to establish and interface for
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 1e46e6f..4e24d54 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -45,6 +45,7 @@
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
+import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
 import com.android.systemui.recents.events.activity.IterateRecentsEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
@@ -217,14 +218,14 @@
                 mEmptyView = mEmptyViewStub.inflate();
             }
             mEmptyView.setVisibility(View.VISIBLE);
-            if (!Constants.DebugFlags.App.DisableSearchBar) {
+            if (!RecentsDebugFlags.Static.DisableSearchBar) {
                 mRecentsView.setSearchBarVisibility(View.GONE);
             }
         } else {
             if (mEmptyView != null) {
                 mEmptyView.setVisibility(View.GONE);
             }
-            if (!Constants.DebugFlags.App.DisableSearchBar) {
+            if (!RecentsDebugFlags.Static.DisableSearchBar) {
                 if (mRecentsView.hasValidSearchBar()) {
                     mRecentsView.setSearchBarVisibility(View.VISIBLE);
                 } else {
@@ -338,7 +339,7 @@
         EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
 
         // Initialize the widget host (the host id is static and does not change)
-        if (!Constants.DebugFlags.App.DisableSearchBar) {
+        if (!RecentsDebugFlags.Static.DisableSearchBar) {
             mAppWidgetHost = new RecentsAppWidgetHost(this, RecentsAppWidgetHost.HOST_ID);
         }
         mPackageMonitor = new RecentsPackageMonitor();
@@ -364,14 +365,14 @@
         mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent);
 
         // Bind the search app widget when we first start up
-        if (!Constants.DebugFlags.App.DisableSearchBar) {
+        if (!RecentsDebugFlags.Static.DisableSearchBar) {
             mSearchWidgetInfo = ssp.getOrBindSearchAppWidget(this, mAppWidgetHost);
         }
 
         // Register the broadcast receiver to handle messages when the screen is turned off
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SCREEN_OFF);
-        if (!Constants.DebugFlags.App.DisableSearchBar) {
+        if (!RecentsDebugFlags.Static.DisableSearchBar) {
             filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
         }
         registerReceiver(mSystemBroadcastReceiver, filter);
@@ -420,6 +421,8 @@
         if (state.startHidden) {
             state.startHidden = false;
             mRecentsView.setStackViewVisibility(View.INVISIBLE);
+        } else {
+            mRecentsView.setStackViewVisibility(View.VISIBLE);
         }
     }
 
@@ -433,12 +436,8 @@
     protected void onPause() {
         super.onPause();
 
-        if (Constants.DebugFlags.App.EnableFastToggleRecents) {
-            // Stop the fast-toggle dozer
-            mIterateTrigger.stopDozing();
-        }
-
-        if (Constants.DebugFlags.App.EnableFastToggleRecents) {
+        RecentsDebugFlags flags = Recents.getDebugFlags();
+        if (flags.isFastToggleRecentsEnabled()) {
             // Stop the fast-toggle dozer
             mIterateTrigger.stopDozing();
         }
@@ -483,7 +482,7 @@
         mPackageMonitor.unregister();
 
         // Stop listening for widget package changes if there was one bound
-        if (!Constants.DebugFlags.App.DisableSearchBar) {
+        if (!RecentsDebugFlags.Static.DisableSearchBar) {
             mAppWidgetHost.stopListening();
         }
 
@@ -617,7 +616,7 @@
         ViewAnimation.TaskViewEnterContext ctx = new ViewAnimation.TaskViewEnterContext(t);
         ctx.postAnimationTrigger.increment();
         if (mSearchWidgetInfo != null) {
-            if (!Constants.DebugFlags.App.DisableSearchBar) {
+            if (!RecentsDebugFlags.Static.DisableSearchBar) {
                 ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
                     @Override
                     public void run() {
@@ -636,8 +635,8 @@
                 // the dozer now
                 RecentsConfiguration config = Recents.getConfiguration();
                 RecentsActivityLaunchState launchState = config.getLaunchState();
-                if (Constants.DebugFlags.App.EnableFastToggleRecents &&
-                        !launchState.launchedWithAltTab) {
+                RecentsDebugFlags flags = Recents.getDebugFlags();
+                if (flags.isFastToggleRecentsEnabled() && !launchState.launchedWithAltTab) {
                     mIterateTrigger.startDozing();
                 }
             }
@@ -725,6 +724,11 @@
         MetricsLogger.count(this, "overview_screen_pinned", 1);
     }
 
+    public final void onBusEvent(DebugFlagsChangedEvent event) {
+        // Just finish recents so that we can reload the flags anew on the next instantiation
+        finish();
+    }
+
     private void refreshSearchWidgetView() {
         if (mSearchWidgetInfo != null) {
             SystemServicesProxy ssp = Recents.getSystemServices();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index 01ffd2a..7f7dbce 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -74,7 +74,8 @@
      * Returns the task to focus given the current launch state.
      */
     public int getInitialFocusTaskIndex(int numTasks) {
-        if (Constants.DebugFlags.App.EnableFastToggleRecents && !launchedWithAltTab) {
+        RecentsDebugFlags flags = Recents.getDebugFlags();
+        if (flags.isFastToggleRecentsEnabled() && !launchedWithAltTab) {
             // If we are fast toggling, then focus the next task depending on when you are on home
             // or coming in from another app
             if (launchedFromHome) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index a73f323..8f952be 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -154,7 +154,7 @@
             int swInset = getInsetToSmallestWidth(windowBounds.right - windowBounds.left);
             int top = searchBarBounds.isEmpty() ? topInset : 0;
             taskStackBounds.set(windowBounds.left + swInset, searchBarBounds.bottom + top,
-                    windowBounds.right - swInset, windowBounds.bottom);
+                    windowBounds.right - swInset - rightInset, windowBounds.bottom);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
new file mode 100644
index 0000000..6c74a4e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 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.recents;
+
+import android.content.Context;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
+import com.android.systemui.tuner.TunerService;
+
+/**
+ * Tunable debug flags
+ */
+public class RecentsDebugFlags implements TunerService.Tunable {
+
+    private static final String KEY_FAST_TOGGLE = "overview_fast_toggle";
+
+    public static class Static {
+        // Enables debug drawing for the transition thumbnail
+        public static final boolean EnableTransitionThumbnailDebugMode = false;
+        // This disables the search bar integration
+        public static final boolean DisableSearchBar = true;
+        // This disables the bitmap and icon caches
+        public static final boolean DisableBackgroundCache = false;
+        // Enables the simulated task affiliations
+        public static final boolean EnableSimulatedTaskGroups = false;
+        // Defines the number of mock task affiliations per group
+        public static final int TaskAffiliationsGroupCount = 12;
+        // Enables us to create mock recents tasks
+        public static final boolean EnableSystemServicesProxy = false;
+        // Defines the number of mock recents packages to create
+        public static final int SystemServicesProxyMockPackageCount = 3;
+        // Defines the number of mock recents tasks to create
+        public static final int SystemServicesProxyMockTaskCount = 100;
+    }
+
+    private boolean mForceEnableFreeformWorkspace;
+    private boolean mEnableFastToggleRecents;
+
+    /**
+     * We read the prefs once when we start the activity, then update them as the tuner changes
+     * the flags.
+     */
+    public RecentsDebugFlags(Context context) {
+        // Register all our flags, this will also call onTuningChanged() for each key, which will
+        // initialize the current state of each flag
+        TunerService.get(context).addTunable(this, KEY_FAST_TOGGLE);
+    }
+
+    /**
+     * @return whether we are enabling fast toggling.
+     */
+    public boolean isFastToggleRecentsEnabled() {
+        return mEnableFastToggleRecents;
+    }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        switch (key) {
+            case KEY_FAST_TOGGLE:
+                mEnableFastToggleRecents = (newValue != null) &&
+                        (Integer.parseInt(newValue) != 0);
+                break;
+        }
+        EventBus.getDefault().send(new DebugFlagsChangedEvent());
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index b491f94..85a2eda 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -324,8 +324,8 @@
             if (topTask != null && ssp.isRecentsTopMost(topTask, isTopTaskHome)) {
                 RecentsConfiguration config = Recents.getConfiguration();
                 RecentsActivityLaunchState launchState = config.getLaunchState();
-                if (Constants.DebugFlags.App.EnableFastToggleRecents &&
-                        !launchState.launchedWithAltTab) {
+                RecentsDebugFlags flags = Recents.getDebugFlags();
+                if (flags.isFastToggleRecentsEnabled() && !launchState.launchedWithAltTab) {
                     // Notify recents to move onto the next task
                     EventBus.getDefault().post(new IterateRecentsEvent());
                 } else {
@@ -555,7 +555,7 @@
         // Update the configuration for the current state
         config.update(mContext, ssp, ssp.getWindowRect());
 
-        if (!Constants.DebugFlags.App.DisableSearchBar && tryAndBindSearchWidget) {
+        if (!RecentsDebugFlags.Static.DisableSearchBar && tryAndBindSearchWidget) {
             // Try and pre-emptively bind the search widget on startup to ensure that we
             // have the right thumbnail bounds to animate to.
             // Note: We have to reload the widget id before we get the task stack bounds below
@@ -758,7 +758,7 @@
                 int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale);
                 thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight,
                         Bitmap.Config.ARGB_8888);
-                if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+                if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
                     thumbnail.eraseColor(0xFFff0000);
                 } else {
                     Canvas c = new Canvas(thumbnail);
@@ -816,11 +816,11 @@
         if (!useThumbnailTransition) {
             // If there is no thumbnail transition, but is launching from home into recents, then
             // use a quick home transition and do the animation from home
-            if (!Constants.DebugFlags.App.DisableSearchBar && hasRecentTasks) {
+            if (!RecentsDebugFlags.Static.DisableSearchBar && hasRecentTasks) {
                 SystemServicesProxy ssp = Recents.getSystemServices();
                 String homeActivityPackage = ssp.getHomeActivityPackageName();
                 String searchWidgetPackage = Prefs.getString(mContext,
-                        Prefs.Key.SEARCH_APP_WIDGET_PACKAGE, null);
+                        Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null);
 
                 // Determine whether we are coming from a search owned home activity
                 boolean fromSearchHome = (homeActivityPackage != null) &&
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DebugFlagsChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DebugFlagsChangedEvent.java
new file mode 100644
index 0000000..fe3bf26
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DebugFlagsChangedEvent.java
@@ -0,0 +1,26 @@
+/*
+ * 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.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when the SystemUI tuner changes a flag.
+ */
+public class DebugFlagsChangedEvent extends EventBus.Event {
+    // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 0432ac9..16d6929 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -63,7 +63,8 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.RecentsImpl;
 
 import java.io.IOException;
@@ -113,6 +114,7 @@
 
     /** Private constructor */
     public SystemServicesProxy(Context context) {
+        RecentsDebugFlags flags = Recents.getDebugFlags();
         mAccm = AccessibilityManager.getInstance(context);
         mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         mIam = ActivityManagerNative.getDefault();
@@ -124,8 +126,8 @@
         mUm = UserManager.get(context);
         mDisplay = mWm.getDefaultDisplay();
         mRecentsPackage = context.getPackageName();
-        mHasFreeformWorkspaceSupport = false && mPm.hasSystemFeature(
-                PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT);
+        mHasFreeformWorkspaceSupport = false &&
+                mPm.hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT);
 
         // Get the dummy thumbnail width/heights
         Resources res = context.getResources();
@@ -143,7 +145,7 @@
         // Resolve the assist intent
         mAssistComponent = mAssistUtils.getAssistComponentForUser(UserHandle.myUserId());
 
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) {
             // Create a dummy icon
             mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
             mDummyIcon.eraseColor(0xFF999999);
@@ -156,13 +158,13 @@
         if (mAm == null) return null;
 
         // If we are mocking, then create some recent tasks
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) {
             ArrayList<ActivityManager.RecentTaskInfo> tasks =
                     new ArrayList<ActivityManager.RecentTaskInfo>();
-            int count = Math.min(numLatestTasks, Constants.DebugFlags.App.SystemServicesProxyMockTaskCount);
+            int count = Math.min(numLatestTasks, RecentsDebugFlags.Static.SystemServicesProxyMockTaskCount);
             for (int i = 0; i < count; i++) {
                 // Create a dummy component name
-                int packageIndex = i % Constants.DebugFlags.App.SystemServicesProxyMockPackageCount;
+                int packageIndex = i % RecentsDebugFlags.Static.SystemServicesProxyMockPackageCount;
                 ComponentName cn = new ComponentName("com.android.test" + packageIndex,
                         "com.android.test" + i + ".Activity");
                 String description = "" + i + " - " +
@@ -381,7 +383,7 @@
         if (mAm == null) return null;
 
         // If we are mocking, then just return a dummy thumbnail
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) {
             Bitmap thumbnail = Bitmap.createBitmap(mDummyThumbnailWidth, mDummyThumbnailHeight,
                     Bitmap.Config.ARGB_8888);
             thumbnail.eraseColor(0xff333333);
@@ -443,7 +445,7 @@
     /** Moves a task to the front with the specified activity options. */
     public void moveTaskToFront(int taskId, ActivityOptions opts) {
         if (mAm == null) return;
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) return;
 
         if (opts != null) {
             mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME,
@@ -456,7 +458,7 @@
     /** Removes the task */
     public void removeTask(final int taskId) {
         if (mAm == null) return;
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) return;
 
         // Remove the task.
         BackgroundThread.getHandler().post(new Runnable() {
@@ -475,7 +477,7 @@
      */
     public ActivityInfo getActivityInfo(ComponentName cn, int userId) {
         if (mIpm == null) return null;
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return new ActivityInfo();
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) return new ActivityInfo();
 
         try {
             return mIpm.getActivityInfo(cn, PackageManager.GET_META_DATA, userId);
@@ -492,7 +494,7 @@
      */
     public ActivityInfo getActivityInfo(ComponentName cn) {
         if (mPm == null) return null;
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return new ActivityInfo();
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) return new ActivityInfo();
 
         try {
             return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
@@ -507,7 +509,7 @@
         if (mPm == null) return null;
 
         // If we are mocking, then return a mock label
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) {
             return "Recent Task";
         }
 
@@ -519,7 +521,7 @@
         if (mPm == null) return null;
 
         // If we are mocking, then return a mock label
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) {
             return "Recent Task";
         }
 
@@ -549,7 +551,7 @@
         if (mPm == null) return null;
 
         // If we are mocking, then return a mock label
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) {
             return new ColorDrawable(0xFF666666);
         }
 
@@ -580,7 +582,7 @@
     /** Returns the package name of the home activity. */
     public String getHomeActivityPackageName() {
         if (mPm == null) return null;
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return null;
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) return null;
 
         ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
         ComponentName defaultHomeActivity = mPm.getHomeActivities(homeActivities);
@@ -623,22 +625,22 @@
      * Returns the current search widget id.
      */
     public int getSearchAppWidgetId(Context context) {
-        return Prefs.getInt(context, Prefs.Key.SEARCH_APP_WIDGET_ID, -1);
+        return Prefs.getInt(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_ID, -1);
     }
 
     /**
      * Returns the current search widget info, binding a new one if necessary.
      */
     public AppWidgetProviderInfo getOrBindSearchAppWidget(Context context, AppWidgetHost host) {
-        int searchWidgetId = Prefs.getInt(context, Prefs.Key.SEARCH_APP_WIDGET_ID, -1);
+        int searchWidgetId = Prefs.getInt(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_ID, -1);
         AppWidgetProviderInfo searchWidgetInfo = mAwm.getAppWidgetInfo(searchWidgetId);
         AppWidgetProviderInfo resolvedSearchWidgetInfo = resolveSearchAppWidget();
 
         // Return the search widget info if it hasn't changed
         if (searchWidgetInfo != null && resolvedSearchWidgetInfo != null &&
                 searchWidgetInfo.provider.equals(resolvedSearchWidgetInfo.provider)) {
-            if (Prefs.getString(context, Prefs.Key.SEARCH_APP_WIDGET_PACKAGE, null) == null) {
-                Prefs.putString(context, Prefs.Key.SEARCH_APP_WIDGET_PACKAGE,
+            if (Prefs.getString(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null) == null) {
+                Prefs.putString(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE,
                         searchWidgetInfo.provider.getPackageName());
             }
             return searchWidgetInfo;
@@ -654,16 +656,16 @@
             Pair<Integer, AppWidgetProviderInfo> widgetInfo = bindSearchAppWidget(host,
                     resolvedSearchWidgetInfo);
             if (widgetInfo != null) {
-                Prefs.putInt(context, Prefs.Key.SEARCH_APP_WIDGET_ID, widgetInfo.first);
-                Prefs.putString(context, Prefs.Key.SEARCH_APP_WIDGET_PACKAGE,
+                Prefs.putInt(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_ID, widgetInfo.first);
+                Prefs.putString(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE,
                         widgetInfo.second.provider.getPackageName());
                 return widgetInfo.second;
             }
         }
 
         // If we fall through here, then there is no resolved search widget, so clear the state
-        Prefs.remove(context, Prefs.Key.SEARCH_APP_WIDGET_ID);
-        Prefs.remove(context, Prefs.Key.SEARCH_APP_WIDGET_PACKAGE);
+        Prefs.remove(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_ID);
+        Prefs.remove(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE);
         return null;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index bba453a..fe67fd9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -30,9 +30,9 @@
 import android.util.Log;
 import android.util.LruCache;
 import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.events.activity.PackagesChangedEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 
@@ -283,9 +283,9 @@
                 res.getColor(R.color.recents_task_bar_default_background_color);
         mMaxThumbnailCacheSize = res.getInteger(R.integer.config_recents_max_thumbnail_count);
         mMaxIconCacheSize = res.getInteger(R.integer.config_recents_max_icon_count);
-        int iconCacheSize = Constants.DebugFlags.App.DisableBackgroundCache ? 1 :
+        int iconCacheSize = RecentsDebugFlags.Static.DisableBackgroundCache ? 1 :
                 mMaxIconCacheSize;
-        int thumbnailCacheSize = Constants.DebugFlags.App.DisableBackgroundCache ? 1 :
+        int thumbnailCacheSize = RecentsDebugFlags.Static.DisableBackgroundCache ? 1 :
                 mMaxThumbnailCacheSize;
 
         // Create the default assets
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 6734012..f26dcde 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -24,8 +24,8 @@
 import android.graphics.RectF;
 import android.graphics.drawable.ColorDrawable;
 import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.misc.NamedCounter;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
@@ -543,7 +543,7 @@
      * Temporary: This method will simulate affiliation groups by
      */
     public void createAffiliatedGroupings(Context context) {
-        if (Constants.DebugFlags.App.EnableSimulatedTaskGroups) {
+        if (RecentsDebugFlags.Static.EnableSimulatedTaskGroups) {
             HashMap<Task.TaskKey, Task> taskMap = new HashMap<Task.TaskKey, Task>();
             // Sort all tasks by increasing firstActiveTime of the task
             ArrayList<Task> tasks = mTaskList.getTasks();
@@ -559,7 +559,7 @@
             String prevPackage = "";
             int prevAffiliation = -1;
             Random r = new Random();
-            int groupCountDown = Constants.DebugFlags.App.TaskAffiliationsGroupCount;
+            int groupCountDown = RecentsDebugFlags.Static.TaskAffiliationsGroupCount;
             for (int i = 0; i < taskCount; i++) {
                 Task t = tasks.get(i);
                 String packageName = t.key.getComponent().getPackageName();
@@ -574,7 +574,7 @@
                     addGroup(group);
                     prevAffiliation = affiliation;
                     prevPackage = packageName;
-                    groupCountDown = Constants.DebugFlags.App.TaskAffiliationsGroupCount;
+                    groupCountDown = RecentsDebugFlags.Static.TaskAffiliationsGroupCount;
                 }
                 group.addTask(t);
                 taskMap.put(t.key, t);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index b2f716d..4ecb80a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -34,6 +34,7 @@
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.ExitRecentsWindowFirstAnimationFrameEvent;
 import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
@@ -319,7 +320,7 @@
             b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
                     Bitmap.Config.ARGB_8888);
 
-            if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+            if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
                 b.eraseColor(0xFFff0000);
             } else {
                 Canvas c = new Canvas(b);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 51091c3..b3bd6ed 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -201,7 +201,7 @@
                 taskStackBounds.right - widthPadding,
                 taskStackBounds.bottom);
         // Anchor the task rect to the top-center of the non-freeform stack rect
-        int size = Math.min(mStackRect.width(), mStackRect.height() - mStackBottomOffset);
+        int size = mStackRect.width();
         mTaskRect.set(mStackRect.left, mStackRect.top,
                 mStackRect.left + size, mStackRect.top + size);
         mCurrentStackRect = ssp.hasFreeformWorkspaceSupport() ? mFreeformStackRect : mStackRect;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index a57ac9d..7250d6a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -114,6 +114,7 @@
     HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<>();
     ArrayList<TaskView> mTaskViews = new ArrayList<>();
     List<TaskView> mImmutableTaskViews = new ArrayList<>();
+    List<TaskView> mTmpTaskViews = new ArrayList<>();
     LayoutInflater mInflater;
     boolean mLayersDisabled;
     boolean mTouchExplorationEnabled;
@@ -279,14 +280,9 @@
         }
 
         // Mark each task view for relayout
-        if (mViewPool != null) {
-            Iterator<TaskView> iter = mViewPool.poolViewIterator();
-            if (iter != null) {
-                while (iter.hasNext()) {
-                    TaskView tv = iter.next();
-                    tv.reset();
-                }
-            }
+        List<TaskView> poolViews = mViewPool.getViews();
+        for (TaskView tv : poolViews) {
+            tv.reset();
         }
 
         // Reset the stack state
@@ -862,10 +858,12 @@
         }
 
         // Measure each of the TaskViews
-        List<TaskView> taskViews = getTaskViews();
-        int taskViewCount = taskViews.size();
+        mTmpTaskViews.clear();
+        mTmpTaskViews.addAll(getTaskViews());
+        mTmpTaskViews.addAll(mViewPool.getViews());
+        int taskViewCount = mTmpTaskViews.size();
         for (int i = 0; i < taskViewCount; i++) {
-            TaskView tv = taskViews.get(i);
+            TaskView tv = mTmpTaskViews.get(i);
             if (tv.getBackground() != null) {
                 tv.getBackground().getPadding(mTmpRect);
             } else {
@@ -891,10 +889,12 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         // Layout each of the TaskViews
-        List<TaskView> taskViews = getTaskViews();
-        int taskViewCount = taskViews.size();
+        mTmpTaskViews.clear();
+        mTmpTaskViews.addAll(getTaskViews());
+        mTmpTaskViews.addAll(mViewPool.getViews());
+        int taskViewCount = mTmpTaskViews.size();
         for (int i = 0; i < taskViewCount; i++) {
-            TaskView tv = taskViews.get(i);
+            TaskView tv = mTmpTaskViews.get(i);
             if (tv.getBackground() != null) {
                 tv.getBackground().getPadding(mTmpRect);
             } else {
@@ -911,6 +911,9 @@
         }
 
         if (changed) {
+            if (mStackScroller.isScrollOutOfBounds()) {
+                mStackScroller.boundScroll();
+            }
             requestSynchronizeStackViewsWithModel();
             synchronizeStackViewsWithModel();
             clipTaskViews(true /* forceUpdate */);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index cb7465d..2c8f316 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -45,6 +45,7 @@
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
@@ -324,22 +325,9 @@
 
         if (launchState.launchedFromAppWithThumbnail) {
             if (mTask.isLaunchTarget) {
-                // Animate the dim/overlay
-                if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
-                    // Animate the thumbnail alpha before the dim animation (to prevent updating the
-                    // hardware layer)
-                    mThumbnailView.startEnterRecentsAnimation(new Runnable() {
-                            @Override
-                            public void run() {
-                                animateDimToProgress(taskViewEnterFromAppDuration,
-                                        ctx.postAnimationTrigger.decrementOnAnimationEnd());
-                            }
-                        });
-                } else {
-                    // Immediately start the dim animation
-                    animateDimToProgress(taskViewEnterFromAppDuration,
-                            ctx.postAnimationTrigger.decrementOnAnimationEnd());
-                }
+                // Immediately start the dim animation
+                animateDimToProgress(taskViewEnterFromAppDuration,
+                        ctx.postAnimationTrigger.decrementOnAnimationEnd());
                 ctx.postAnimationTrigger.increment();
 
                 // Animate the action button in
@@ -635,7 +623,9 @@
     @Override
     protected void dispatchDraw(Canvas canvas) {
         super.dispatchDraw(canvas);
-        if (Constants.DebugFlags.App.EnableFastToggleRecents && mIsFocused) {
+
+        RecentsDebugFlags flags = Recents.getDebugFlags();
+        if (flags.isFastToggleRecentsEnabled() && mIsFocused) {
             Paint tmpPaint = new Paint();
             Rect tmpRect = new Rect();
             tmpRect.set(0, 0, getWidth(), getHeight());
@@ -676,7 +666,8 @@
                 clearAccessibilityFocus();
             }
         }
-        if (Constants.DebugFlags.App.EnableFastToggleRecents) {
+        RecentsDebugFlags flags = Recents.getDebugFlags();
+        if (flags.isFastToggleRecentsEnabled()) {
             invalidate();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
index 12b91af..31fbd3e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
@@ -20,6 +20,7 @@
 
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 
 
 /* A view pool to manage more views than we can visibly handle */
@@ -76,11 +77,10 @@
         return v;
     }
 
-    /** Returns an iterator to the list of the views in the pool. */
-    Iterator<V> poolViewIterator() {
-        if (mPool != null) {
-            return mPool.iterator();
-        }
-        return null;
+    /**
+     * Returns the list of views in the pool.
+     */
+    List<V> getViews() {
+        return mPool;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 9e3cf37..e6a291c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -594,7 +594,9 @@
 
         // Setup the animation with the screenshot just taken
         if (mScreenshotAnimation != null) {
-            mScreenshotAnimation.end();
+            if (mScreenshotAnimation.isStarted()) {
+                mScreenshotAnimation.end();
+            }
             mScreenshotAnimation.removeAllListeners();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 069279f..d3d9bef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -470,7 +470,6 @@
                         processForRemoteInput(sbn.getNotification());
                         String key = sbn.getKey();
                         boolean isUpdate = mNotificationData.get(key) != null;
-
                         // In case we don't allow child notifications, we ignore children of
                         // notifications that have a summary, since we're not going to show them
                         // anyway. This is true also when the summary is canceled,
@@ -2023,6 +2022,7 @@
         }
 
         Notification n = notification.getNotification();
+        mNotificationData.updateRanking(ranking);
 
         boolean applyInPlace = !entry.cacheContentViews(mContext, notification.getNotification());
         boolean shouldInterrupt = shouldInterrupt(entry, notification);
@@ -2077,7 +2077,6 @@
             inflateViews(entry, mStackScroller);
         }
         updateHeadsUp(key, entry, shouldInterrupt, alertAgain);
-        mNotificationData.updateRanking(ranking);
         updateNotifications();
 
         // Update the veto button accordingly (and as a result, whether this row is
@@ -2167,7 +2166,6 @@
         boolean accessibilityForcesLaunch = isFullscreen
                 && mAccessibilityManager.isTouchExplorationEnabled();
         boolean justLaunchedFullScreenIntent = entry.hasJustLaunchedFullScreenIntent();
-
         boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
                 && isAllowed
                 && !accessibilityForcesLaunch
@@ -2175,7 +2173,8 @@
                 && mPowerManager.isScreenOn()
                 && (!mStatusBarKeyguardViewManager.isShowing()
                         || mStatusBarKeyguardViewManager.isOccluded())
-                && !mStatusBarKeyguardViewManager.isInputRestricted();
+                && !mStatusBarKeyguardViewManager.isInputRestricted()
+                && !mNotificationData.shouldSuppressPeek(sbn.getKey());
         try {
             interrupt = interrupt && !mDreamManager.isDreaming();
         } catch (RemoteException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 6a90d8e..83dbde5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -105,36 +105,29 @@
         }
 
         public boolean cacheContentViews(Context ctx, Notification updatedNotification) {
-            boolean cached = false;
+            boolean applyInPlace = false;
             if (updatedNotification != null) {
                 final Notification.Builder updatedNotificationBuilder
                         = Notification.Builder.recoverBuilder(ctx, updatedNotification);
                 final RemoteViews newContentView = updatedNotificationBuilder.makeContentView();
-                if (!compareRemoteViews(cachedContentView, newContentView)) {
-                    cachedContentView = newContentView;
-                    cached |= true;
-                }
                 final RemoteViews newBigContentView =
                         updatedNotificationBuilder.makeBigContentView();
-                if (!compareRemoteViews(cachedBigContentView, newBigContentView)) {
-                    cachedBigContentView = newBigContentView;
-                    cached |= true;
-                }
                 final RemoteViews newHeadsUpContentView =
                         updatedNotificationBuilder.makeHeadsUpContentView();
-                if (!compareRemoteViews(cachedHeadsUpContentView, newBigContentView)) {
-                    cachedHeadsUpContentView = newHeadsUpContentView;
-                    cached |= true;
-                }
                 final Notification updatedPublicNotification = updatedNotification.publicVersion;
                 final RemoteViews newPubContentView = (updatedPublicNotification != null)
                         ? Notification.Builder.recoverBuilder(
                                 ctx, updatedPublicNotification).makeContentView()
                         : null;
-                if (!compareRemoteViews(cachedPublicContentView, newPubContentView)) {
-                    cachedPublicContentView = newPubContentView;
-                    cached |= true;
-                }
+
+                applyInPlace = compareRemoteViews(cachedContentView, newContentView)
+                        && compareRemoteViews(cachedBigContentView, newBigContentView)
+                        && compareRemoteViews(cachedHeadsUpContentView, newHeadsUpContentView)
+                        && compareRemoteViews(cachedPublicContentView, newPubContentView);
+                cachedPublicContentView = newPubContentView;
+                cachedHeadsUpContentView = newHeadsUpContentView;
+                cachedBigContentView = newBigContentView;
+                cachedContentView = newContentView;
             } else {
                 final Notification.Builder builder
                         = Notification.Builder.recoverBuilder(ctx, notification.getNotification());
@@ -150,9 +143,9 @@
                             = Notification.Builder.recoverBuilder(ctx, publicNotification);
                     cachedPublicContentView = publicBuilder.makeContentView();
                 }
-                cached = true;
+                applyInPlace = false;
             }
-            return cached;
+            return applyInPlace;
         }
 
         // Returns true if the RemoteViews are the same.
@@ -292,6 +285,15 @@
         return NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
     }
 
+    public boolean shouldSuppressPeek(String key) {
+        if (mRankingMap != null) {
+            mRankingMap.getRanking(key, mTmpRanking);
+            return (mTmpRanking.getSuppressedVisualEffects()
+                    & NotificationListenerService.SUPPRESSED_EFFECT_PEEK) != 0;
+        }
+        return false;
+    }
+
     private void updateRankingAndSort(RankingMap ranking) {
         if (ranking != null) {
             mRankingMap = ranking;
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 9ab2a2c..0cddf1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1261,6 +1261,7 @@
             Entry oldEntry) {
         if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());
 
+        mNotificationData.updateRanking(ranking);
         Entry shadeEntry = createNotificationViews(notification);
         if (shadeEntry == null) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 38656ee..f8c72b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.telephony.SubscriptionInfo;
-
+import com.android.settingslib.net.MobileDataController;
 import com.android.settingslib.wifi.AccessPoint;
 
 import java.util.List;
@@ -85,22 +85,4 @@
             void onSettingsActivityTriggered(Intent settingsIntent);
         }
     }
-
-    /**
-     * Tracks mobile data support and usage.
-     */
-    public interface MobileDataController {
-        boolean isMobileDataSupported();
-        boolean isMobileDataEnabled();
-        void setMobileDataEnabled(boolean enabled);
-        DataUsageInfo getDataUsageInfo();
-
-        public static class DataUsageInfo {
-            public String carrier;
-            public String period;
-            public long limitLevel;
-            public long warningLevel;
-            public long usageLevel;
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 2996808..909f497 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -39,10 +37,10 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.MathUtils;
-
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.settingslib.net.MobileDataController;
 import com.android.systemui.DemoMode;
 import com.android.systemui.R;
 
@@ -57,9 +55,11 @@
 import java.util.Locale;
 import java.util.Map;
 
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+
 /** Platform implementation of the network controller. **/
 public class NetworkControllerImpl extends BroadcastReceiver
-        implements NetworkController, DemoMode {
+        implements NetworkController, DemoMode, MobileDataController.NetworkNameProvider {
     // debug
     static final String TAG = "NetworkController";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -94,7 +94,7 @@
     // SIM for most actions.  This may be null if there aren't any SIMs around.
     private MobileSignalController mDefaultSignalController;
     private final AccessPointControllerImpl mAccessPoints;
-    private final MobileDataControllerImpl mMobileDataController;
+    private final MobileDataController mMobileDataController;
 
     private boolean mInetCondition; // Used for Logging and demo.
 
@@ -139,7 +139,7 @@
                 SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
                 new CallbackHandler(),
                 new AccessPointControllerImpl(context, bgLooper),
-                new MobileDataControllerImpl(context),
+                new MobileDataController(context),
                 new SubscriptionDefaults());
         mReceiverHandler.post(mRegisterListeners);
     }
@@ -150,7 +150,7 @@
             SubscriptionManager subManager, Config config, Looper bgLooper,
             CallbackHandler callbackHandler,
             AccessPointControllerImpl accessPointController,
-            MobileDataControllerImpl mobileDataController,
+            MobileDataController mobileDataController,
             SubscriptionDefaults defaultsHandler) {
         mContext = context;
         mConfig = config;
@@ -174,7 +174,7 @@
         mMobileDataController = mobileDataController;
         mMobileDataController.setNetworkController(this);
         // TODO: Find a way to move this into MobileDataController.
-        mMobileDataController.setCallback(new MobileDataControllerImpl.Callback() {
+        mMobileDataController.setCallback(new MobileDataController.Callback() {
             @Override
             public void onMobileDataEnabled(boolean enabled) {
                 mCallbackHandler.setMobileDataEnabled(enabled);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 9b1e72a..eab6e13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -18,20 +18,16 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Messenger;
 import android.util.Log;
-
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.AsyncChannel;
+import com.android.settingslib.wifi.WifiStatusTracker;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 
-import java.util.List;
 import java.util.Objects;
 
 
@@ -40,12 +36,14 @@
     private final WifiManager mWifiManager;
     private final AsyncChannel mWifiChannel;
     private final boolean mHasMobileData;
+    private final WifiStatusTracker mWifiTracker;
 
     public WifiSignalController(Context context, boolean hasMobileData,
             CallbackHandler callbackHandler, NetworkControllerImpl networkController) {
         super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
                 callbackHandler, networkController);
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mWifiTracker = new WifiStatusTracker(mWifiManager);
         mHasMobileData = hasMobileData;
         Handler handler = new WifiHandler();
         mWifiChannel = new AsyncChannel();
@@ -93,54 +91,15 @@
      * Extract wifi state directly from broadcasts about changes in wifi state.
      */
     public void handleBroadcast(Intent intent) {
-        String action = intent.getAction();
-        if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-            mCurrentState.enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                    WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-            final NetworkInfo networkInfo = (NetworkInfo)
-                    intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-            mCurrentState.connected = networkInfo != null && networkInfo.isConnected();
-            // If Connected grab the signal strength and ssid.
-            if (mCurrentState.connected) {
-                // try getting it out of the intent first
-                WifiInfo info = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) != null
-                        ? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO)
-                        : mWifiManager.getConnectionInfo();
-                if (info != null) {
-                    mCurrentState.ssid = getSsid(info);
-                } else {
-                    mCurrentState.ssid = null;
-                }
-            } else if (!mCurrentState.connected) {
-                mCurrentState.ssid = null;
-            }
-        } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
-            // Default to -200 as its below WifiManager.MIN_RSSI.
-            mCurrentState.rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
-            mCurrentState.level = WifiManager.calculateSignalLevel(
-                    mCurrentState.rssi, WifiIcons.WIFI_LEVEL_COUNT);
-        }
-
+        mWifiTracker.handleBroadcast(intent);
+        mCurrentState.enabled = mWifiTracker.enabled;
+        mCurrentState.connected = mWifiTracker.connected;
+        mCurrentState.ssid = mWifiTracker.ssid;
+        mCurrentState.rssi = mWifiTracker.rssi;
+        mCurrentState.level = mWifiTracker.level;
         notifyListenersIfNecessary();
     }
 
-    private String getSsid(WifiInfo info) {
-        String ssid = info.getSSID();
-        if (ssid != null) {
-            return ssid;
-        }
-        // OK, it's not in the connectionInfo; we have to go hunting for it
-        List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
-        int length = networks.size();
-        for (int i = 0; i < length; i++) {
-            if (networks.get(i).networkId == info.getNetworkId()) {
-                return networks.get(i).SSID;
-            }
-        }
-        return null;
-    }
-
     @VisibleForTesting
     void setActivity(int wifiActivity) {
         mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 30c08cd..13fc47d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -33,6 +33,7 @@
 import android.util.Log;
 
 import com.android.internal.telephony.cdma.EriInfo;
+import com.android.settingslib.net.MobileDataController;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
@@ -95,7 +96,7 @@
         mCallbackHandler = mock(CallbackHandler.class);
         mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
                 mConfig, Looper.getMainLooper(), mCallbackHandler,
-                mock(AccessPointControllerImpl.class), mock(MobileDataControllerImpl.class),
+                mock(AccessPointControllerImpl.class), mock(MobileDataController.class),
                 mMockSubDefaults);
         setupNetworkController();
 
@@ -136,7 +137,7 @@
               = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
                         mConfig, Looper.getMainLooper(), mCallbackHandler,
                         mock(AccessPointControllerImpl.class),
-                        mock(MobileDataControllerImpl.class), mMockSubDefaults);
+                        mock(MobileDataController.class), mMockSubDefaults);
 
       setupNetworkController();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 0ec8802..587e2b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -4,6 +4,7 @@
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.settingslib.net.MobileDataController;
 import org.mockito.Mockito;
 
 @SmallTest
@@ -87,7 +88,7 @@
         mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
                 mConfig, Looper.getMainLooper(), mCallbackHandler,
                 Mockito.mock(AccessPointControllerImpl.class),
-                Mockito.mock(MobileDataControllerImpl.class), mMockSubDefaults);
+                Mockito.mock(MobileDataController.class), mMockSubDefaults);
         setupNetworkController();
 
         setupDefaultSignal();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 660fd9c..760aa9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -29,6 +29,7 @@
 
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.settingslib.net.MobileDataController;
 import com.android.systemui.R;
 
 import org.mockito.ArgumentCaptor;
@@ -46,7 +47,7 @@
         // Create a new NetworkController as this is currently handled in constructor.
         mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
                 mConfig, Looper.getMainLooper(), mCallbackHandler,
-                mock(AccessPointControllerImpl.class), mock(MobileDataControllerImpl.class),
+                mock(AccessPointControllerImpl.class), mock(MobileDataController.class),
                 mMockSubDefaults);
         setupNetworkController();
 
@@ -95,7 +96,7 @@
         // Create a new NetworkController as this is currently handled in constructor.
         mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
                 mConfig, Looper.getMainLooper(), mCallbackHandler,
-                mock(AccessPointControllerImpl.class), mock(MobileDataControllerImpl.class),
+                mock(AccessPointControllerImpl.class), mock(MobileDataController.class),
                 mMockSubDefaults);
         setupNetworkController();
 
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index ab1d775..ae9ddc0 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -30,6 +30,7 @@
 import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.IInputSessionCallback;
 import com.android.internal.view.InputBindResult;
+import com.android.internal.view.InputMethodClient;
 import com.android.server.statusbar.StatusBarManagerService;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -160,8 +161,8 @@
     static final int MSG_START_INPUT = 2000;
     static final int MSG_RESTART_INPUT = 2010;
 
-    static final int MSG_UNBIND_METHOD = 3000;
-    static final int MSG_BIND_METHOD = 3010;
+    static final int MSG_UNBIND_CLIENT = 3000;
+    static final int MSG_BIND_CLIENT = 3010;
     static final int MSG_SET_ACTIVE = 3020;
     static final int MSG_SET_INTERACTIVE = 3030;
     static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 3040;
@@ -935,7 +936,7 @@
                 || (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
             if (!updateOnlyWhenLocaleChanged) {
                 hideCurrentInputLocked(0, null);
-                unbindCurrentMethodLocked(true, false);
+                resetCurrentMethodAndClient(InputMethodClient.UNBIND_REASON_RESET_IME);
             }
             if (DEBUG) {
                 Slog.i(TAG, "Locale has been changed to " + newLocale);
@@ -1208,7 +1209,8 @@
          }
     }
 
-    void unbindCurrentClientLocked() {
+    void unbindCurrentClientLocked(
+            /* @InputMethodClient.UnbindReason */ final int unbindClientReason) {
         if (mCurClient != null) {
             if (DEBUG) Slog.v(TAG, "unbindCurrentInputLocked: client = "
                     + mCurClient.client.asBinder());
@@ -1222,8 +1224,8 @@
 
             executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
                     MSG_SET_ACTIVE, 0, mCurClient));
-            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
-                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
+            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO(
+                    MSG_UNBIND_CLIENT, mCurSeq, unbindClientReason, mCurClient.client));
             mCurClient.sessionRequested = false;
             mCurClient = null;
 
@@ -1324,7 +1326,7 @@
             mCurClientInKeyguard = isKeyguardLocked();
             // If the client is changing, we need to switch over to the new
             // one.
-            unbindCurrentClientLocked();
+            unbindCurrentClientLocked(InputMethodClient.UNBIND_REASON_SWITCH_CLIENT);
             if (DEBUG) Slog.v(TAG, "switching to client: client = "
                     + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
 
@@ -1395,7 +1397,7 @@
             throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
         }
 
-        unbindCurrentMethodLocked(false, true);
+        unbindCurrentMethodLocked(true);
 
         mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
         mCurIntent.setComponent(info.getComponent());
@@ -1453,7 +1455,7 @@
                 mCurMethod = IInputMethod.Stub.asInterface(service);
                 if (mCurToken == null) {
                     Slog.w(TAG, "Service connected without a token!");
-                    unbindCurrentMethodLocked(false, false);
+                    unbindCurrentMethodLocked(false);
                     return;
                 }
                 if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
@@ -1479,7 +1481,7 @@
                     InputBindResult res = attachNewInputLocked(true);
                     if (res.method != null) {
                         executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
-                                MSG_BIND_METHOD, mCurClient.client, res));
+                                MSG_BIND_CLIENT, mCurClient.client, res));
                     }
                     return;
                 }
@@ -1490,11 +1492,7 @@
         channel.dispose();
     }
 
-    void unbindCurrentMethodLocked(boolean resetCurrentMethodAndClient, boolean savePosition) {
-        if (resetCurrentMethodAndClient) {
-            mCurMethodId = null;
-        }
-
+    void unbindCurrentMethodLocked(boolean savePosition) {
         if (mVisibleBound) {
             mContext.unbindService(mVisibleConnection);
             mVisibleBound = false;
@@ -1520,10 +1518,13 @@
 
         mCurId = null;
         clearCurMethodLocked();
+    }
 
-        if (resetCurrentMethodAndClient) {
-            unbindCurrentClientLocked();
-        }
+    void resetCurrentMethodAndClient(
+            /* @InputMethodClient.UnbindReason */ final int unbindClientReason) {
+        mCurMethodId = null;
+        unbindCurrentMethodLocked(false);
+        unbindCurrentClientLocked(unbindClientReason);
     }
 
     void requestClientSessionLocked(ClientState cs) {
@@ -1590,8 +1591,9 @@
                 mShowRequested = mInputShown;
                 mInputShown = false;
                 if (mCurClient != null) {
-                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
-                            MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
+                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO(
+                            MSG_UNBIND_CLIENT, InputMethodClient.UNBIND_REASON_DISCONNECT_IME,
+                            mCurSeq, mCurClient.client));
                 }
             }
         }
@@ -1876,12 +1878,12 @@
                 setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id));
             } catch (IllegalArgumentException e) {
                 Slog.w(TAG, "Unknown input method from prefs: " + id, e);
-                unbindCurrentMethodLocked(true, false);
+                resetCurrentMethodAndClient(InputMethodClient.UNBIND_REASON_SWITCH_IME_FAILED);
             }
             mShortcutInputMethodsAndSubtypes.clear();
         } else {
             // There is no longer an input method set, so stop any current one.
-            unbindCurrentMethodLocked(true, false);
+            resetCurrentMethodAndClient(InputMethodClient.UNBIND_REASON_NO_IME);
         }
         // Here is not the perfect place to reset the switching controller. Ideally
         // mSwitchingController and mSettings should be able to share the same state.
@@ -1967,7 +1969,7 @@
                 intent.putExtra("input_method_id", id);
                 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
             }
-            unbindCurrentClientLocked();
+            unbindCurrentClientLocked(InputMethodClient.UNBIND_REASON_SWITCH_IME);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -2771,14 +2773,14 @@
 
             // ---------------------------------------------------------
 
-            case MSG_UNBIND_METHOD:
+            case MSG_UNBIND_CLIENT:
                 try {
-                    ((IInputMethodClient)msg.obj).onUnbindMethod(msg.arg1);
+                    ((IInputMethodClient)msg.obj).onUnbindMethod(msg.arg1, msg.arg2);
                 } catch (RemoteException e) {
                     // There is nothing interesting about the last client dying.
                 }
                 return true;
-            case MSG_BIND_METHOD: {
+            case MSG_BIND_CLIENT: {
                 args = (SomeArgs)msg.obj;
                 IInputMethodClient client = (IInputMethodClient)args.arg1;
                 InputBindResult res = (InputBindResult)args.arg2;
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index c228422..9eb66dd 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -88,6 +88,7 @@
     private SettingsObserver mSettingObserver;
 
     native static boolean vibratorExists();
+    native static void vibratorInit();
     native static void vibratorOn(long milliseconds);
     native static void vibratorOff();
 
@@ -195,6 +196,7 @@
     }
 
     VibratorService(Context context) {
+        vibratorInit();
         // Reset the hardware to a default state, in case this is a runtime
         // restart instead of a fresh boot.
         vibratorOff();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 025126f..6e6bfb7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17969,7 +17969,7 @@
 
         app.systemNoUi = false;
 
-        final int PROCESS_STATE_TOP = mTopProcessState;
+        final int PROCESS_STATE_CUR_TOP = mTopProcessState;
 
         // Determine the importance of the process, starting with most
         // important to least, and assign an appropriate OOM adjustment.
@@ -17984,7 +17984,7 @@
             schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.adjType = "top-activity";
             foregroundActivities = true;
-            procState = PROCESS_STATE_TOP;
+            procState = PROCESS_STATE_CUR_TOP;
         } else if (app.instrumentationClass != null) {
             // Don't want to kill running instrumentation.
             adj = ProcessList.FOREGROUND_APP_ADJ;
@@ -18038,8 +18038,8 @@
                         adj = ProcessList.VISIBLE_APP_ADJ;
                         app.adjType = "visible";
                     }
-                    if (procState > PROCESS_STATE_TOP) {
-                        procState = PROCESS_STATE_TOP;
+                    if (procState > PROCESS_STATE_CUR_TOP) {
+                        procState = PROCESS_STATE_CUR_TOP;
                     }
                     schedGroup = Process.THREAD_GROUP_DEFAULT;
                     app.cached = false;
@@ -18057,8 +18057,8 @@
                         adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                         app.adjType = "pausing";
                     }
-                    if (procState > PROCESS_STATE_TOP) {
-                        procState = PROCESS_STATE_TOP;
+                    if (procState > PROCESS_STATE_CUR_TOP) {
+                        procState = PROCESS_STATE_CUR_TOP;
                     }
                     schedGroup = Process.THREAD_GROUP_DEFAULT;
                     app.cached = false;
@@ -18096,7 +18096,8 @@
             }
         }
 
-        if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+        if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
+                || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
             if (app.foregroundServices) {
                 // The user is aware of this app, so make it visible.
                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b84811f..fd1e9dd 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -17,6 +17,8 @@
 package com.android.server.notification;
 
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
+import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_LIGHTS;
+import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_PEEK;
 import static android.service.notification.NotificationListenerService.TRIM_FULL;
 import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -78,7 +80,6 @@
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.service.notification.Condition;
-import android.service.notification.IConditionListener;
 import android.service.notification.IConditionProvider;
 import android.service.notification.INotificationListener;
 import android.service.notification.IStatusBarNotificationHolder;
@@ -2511,7 +2512,9 @@
         // light
         // release the light
         boolean wasShowLights = mLights.remove(record.getKey());
-        if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && aboveThreshold) {
+        if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && aboveThreshold
+                && ((record.getSuppressedVisualEffects()
+                & NotificationListenerService.SUPPRESSED_EFFECT_LIGHTS) == 0)) {
             mLights.add(record.getKey());
             updateLightsLocked();
             if (mUseAttentionLight) {
@@ -2701,6 +2704,11 @@
     // let zen mode evaluate this record
     private void applyZenModeLocked(NotificationRecord record) {
         record.setIntercepted(mZenModeHelper.shouldIntercept(record));
+        if (record.isIntercepted()) {
+            int suppressed = (mZenModeHelper.shouldSuppressLight() ? SUPPRESSED_EFFECT_LIGHTS : 0)
+                    | (mZenModeHelper.shouldSuppressPeek() ? SUPPRESSED_EFFECT_PEEK : 0);
+            record.setSuppressedVisualEffects(suppressed);
+        }
     }
 
     // lock on mNotificationList
@@ -3234,6 +3242,7 @@
         ArrayList<String> keys = new ArrayList<String>(N);
         ArrayList<String> interceptedKeys = new ArrayList<String>(N);
         Bundle visibilityOverrides = new Bundle();
+        Bundle suppressedVisualEffects = new Bundle();
         for (int i = 0; i < N; i++) {
             NotificationRecord record = mNotificationList.get(i);
             if (!isVisibleToListener(record.sbn, info)) {
@@ -3242,7 +3251,10 @@
             keys.add(record.sbn.getKey());
             if (record.isIntercepted()) {
                 interceptedKeys.add(record.sbn.getKey());
+
             }
+            suppressedVisualEffects.putInt(
+                    record.sbn.getKey(), record.getSuppressedVisualEffects());
             if (record.getPackageVisibilityOverride()
                     != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
                 visibilityOverrides.putInt(record.sbn.getKey(),
@@ -3264,7 +3276,7 @@
         String[] keysAr = keys.toArray(new String[keys.size()]);
         String[] interceptedKeysAr = interceptedKeys.toArray(new String[interceptedKeys.size()]);
         return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
-                speedBumpIndex);
+                speedBumpIndex, suppressedVisualEffects);
     }
 
     private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index f37702c..2a7568d 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -83,6 +83,8 @@
     private String mGlobalSortKey;
     private int mPackageVisibility;
 
+    private int mSuppressedVisualEffects = 0;
+
     @VisibleForTesting
     public NotificationRecord(StatusBarNotification sbn, int score)
     {
@@ -199,6 +201,7 @@
         pw.println(prefix + "  mCreationTimeMs=" + mCreationTimeMs);
         pw.println(prefix + "  mVisibleSinceMs=" + mVisibleSinceMs);
         pw.println(prefix + "  mUpdateTimeMs=" + mUpdateTimeMs);
+        pw.println(prefix + "  mSuppressedVisualEffects= " + mSuppressedVisualEffects);
     }
 
 
@@ -274,6 +277,14 @@
         return mIntercept;
     }
 
+    public void setSuppressedVisualEffects(int effects) {
+        mSuppressedVisualEffects = effects;
+    }
+
+    public int getSuppressedVisualEffects() {
+        return mSuppressedVisualEffects;
+    }
+
     public boolean isCategory(String category) {
         return Objects.equals(getNotification().category, category);
     }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index a1f8c41..dbdc3f4 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -138,6 +138,18 @@
         }
     }
 
+    public boolean shouldSuppressLight() {
+        synchronized (mConfig) {
+            return !mConfig.allowLights;
+        }
+    }
+
+    public boolean shouldSuppressPeek() {
+        synchronized (mConfig) {
+            return !mConfig.allowPeek;
+        }
+    }
+
     public void addCallback(Callback callback) {
         mCallbacks.add(callback);
     }
@@ -394,11 +406,11 @@
             return;
         }
         pw.printf("allow(calls=%s,callsFrom=%s,repeatCallers=%s,messages=%s,messagesFrom=%s,"
-                + "events=%s,reminders=%s)\n",
+                + "events=%s,reminders=%s,lights=%s,peek=%s)\n",
                 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
                 config.allowRepeatCallers, config.allowMessages,
                 ZenModeConfig.sourceToString(config.allowMessagesFrom),
-                config.allowEvents, config.allowReminders);
+                config.allowEvents, config.allowReminders, config.allowLights, config.allowPeek);
         pw.print(prefix); pw.print("  manualRule="); pw.println(config.manualRule);
         if (config.automaticRules.isEmpty()) return;
         final int N = config.automaticRules.size();
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index e4dbf65..8fac9da 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -871,7 +871,7 @@
             return false;
         }
         PackageSetting sysPkg = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
-        if (sysPkg != null) {
+        if (sysPkg != null && sysPkg.pkg != null) {
             if ((sysPkg.pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
                 return false;
             }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a9bd71f..3ad2610 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3704,6 +3704,10 @@
         // This is used by freeform <-> recents windows transition. We need to synchronize
         // the animation with the appearance of the content of recents, so we will make
         // animation stay on the first or last frame a little longer.
+        if (specs == null) {
+            Slog.wtf(TAG, "prolongAnimationsFromSpecs: AppTransitionAnimationSpec is null!");
+            return;
+        }
         mTmpTaskIds.clear();
         for (int i = specs.length - 1; i >= 0; i--) {
             mTmpTaskIds.put(specs[i].taskId, 0);
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 64278ed..03fbd19 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -22,32 +22,69 @@
 
 #include <utils/misc.h>
 #include <utils/Log.h>
-#include <hardware_legacy/vibrator.h>
+#include <hardware/vibrator.h>
 
 #include <stdio.h>
 
 namespace android
 {
 
+static hw_module_t *gVibraModule = NULL;
+static vibrator_device_t *gVibraDevice = NULL;
+
+static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)
+{
+    if (gVibraModule != NULL) {
+        return;
+    }
+
+    int err = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, (hw_module_t const**)&gVibraModule);
+
+    if (err) {
+        ALOGE("Couldn't load %s module (%s)", VIBRATOR_HARDWARE_MODULE_ID, strerror(-err));
+    } else {
+        if (gVibraModule) {
+            vibrator_open(gVibraModule, &gVibraDevice);
+        }
+    }
+}
+
 static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */)
 {
-    return vibrator_exists() > 0 ? JNI_TRUE : JNI_FALSE;
+    if (gVibraModule && gVibraDevice) {
+        return JNI_TRUE;
+    } else {
+        return JNI_FALSE;
+    }
 }
 
 static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
 {
-    // ALOGI("vibratorOn\n");
-    vibrator_on(timeout_ms);
+    if (gVibraDevice) {
+        int err = gVibraDevice->vibrator_on(gVibraDevice, timeout_ms);
+        if (err != 0) {
+            ALOGE("The hw module failed in vibrator_on: %s", strerror(-err));
+        }
+    } else {
+        ALOGW("Tried to vibrate but there is no vibrator device.");
+    }
 }
 
 static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
 {
-    // ALOGI("vibratorOff\n");
-    vibrator_off();
+    if (gVibraDevice) {
+        int err = gVibraDevice->vibrator_off(gVibraDevice);
+        if (err != 0) {
+            ALOGE("The hw module failed in vibrator_off(): %s", strerror(-err));
+        }
+    } else {
+        ALOGW("Tried to stop vibrating but there is no vibrator device.");
+    }
 }
 
 static const JNINativeMethod method_table[] = {
     { "vibratorExists", "()Z", (void*)vibratorExists },
+    { "vibratorInit", "()V", (void*)vibratorInit },
     { "vibratorOn", "(J)V", (void*)vibratorOn },
     { "vibratorOff", "()V", (void*)vibratorOff }
 };
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index be190cb..b5654ee 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -152,18 +152,23 @@
             getInputWindowHandleObjLocalRef(env);
 }
 
-static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t style,
-        SpriteIcon* outSpriteIcon) {
-    PointerIcon pointerIcon;
+static void loadSystemIconAsSpriteWithPointerIcon(JNIEnv* env, jobject contextObj, int32_t style,
+        PointerIcon* outPointerIcon, SpriteIcon* outSpriteIcon) {
     status_t status = android_view_PointerIcon_loadSystemIcon(env,
-            contextObj, style, &pointerIcon);
+            contextObj, style, outPointerIcon);
     if (!status) {
-        pointerIcon.bitmap.copyTo(&outSpriteIcon->bitmap, kN32_SkColorType);
-        outSpriteIcon->hotSpotX = pointerIcon.hotSpotX;
-        outSpriteIcon->hotSpotY = pointerIcon.hotSpotY;
+        outPointerIcon->bitmap.copyTo(&outSpriteIcon->bitmap, kN32_SkColorType);
+        outSpriteIcon->hotSpotX = outPointerIcon->hotSpotX;
+        outSpriteIcon->hotSpotY = outPointerIcon->hotSpotY;
     }
 }
 
+static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t style,
+                                   SpriteIcon* outSpriteIcon) {
+    PointerIcon pointerIcon;
+    loadSystemIconAsSpriteWithPointerIcon(env, contextObj, style, &pointerIcon, outSpriteIcon);
+}
+
 enum {
     WM_ACTION_PASS_TO_USER = 1,
 };
@@ -238,7 +243,8 @@
     /* --- PointerControllerPolicyInterface implementation --- */
 
     virtual void loadPointerResources(PointerResources* outResources);
-    virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources);
+    virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
+            std::map<int32_t, PointerAnimation>* outAnimationResources);
     virtual int32_t getDefaultPointerIconId();
 
 private:
@@ -1041,14 +1047,31 @@
             &outResources->spotAnchor);
 }
 
-void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources) {
+void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
+        std::map<int32_t, PointerAnimation>* outAnimationResources) {
     JNIEnv* env = jniEnv();
 
     for (int iconId = POINTER_ICON_STYLE_CONTEXT_MENU; iconId <= POINTER_ICON_STYLE_GRABBING;
              ++iconId) {
-        loadSystemIconAsSprite(env, mContextObj, iconId, &((*outResources)[iconId]));
+        PointerIcon pointerIcon;
+        loadSystemIconAsSpriteWithPointerIcon(
+                env, mContextObj, iconId, &pointerIcon, &((*outResources)[iconId]));
+        if (!pointerIcon.bitmapFrames.empty()) {
+            PointerAnimation& animationData = (*outAnimationResources)[iconId];
+            size_t numFrames = pointerIcon.bitmapFrames.size() + 1;
+            animationData.durationPerFrame =
+                    milliseconds_to_nanoseconds(pointerIcon.durationPerFrame);
+            animationData.animationFrames.reserve(numFrames);
+            animationData.animationFrames.push_back(SpriteIcon(
+                    pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY));
+            for (size_t i = 0; i < numFrames - 1; ++i) {
+              animationData.animationFrames.push_back(SpriteIcon(
+                      pointerIcon.bitmapFrames[i], pointerIcon.hotSpotX, pointerIcon.hotSpotY));
+            }
+        }
     }
-    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_NULL, &((*outResources)[POINTER_ICON_STYLE_NULL]));
+    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_NULL,
+            &((*outResources)[POINTER_ICON_STYLE_NULL]));
 }
 
 int32_t NativeInputManager::getDefaultPointerIconId() {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c743f24..31c3670 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2436,6 +2436,8 @@
                 // Active device/profile owners must remain active admins.
                 if (isDeviceOwner(adminReceiver, userHandle)
                         || isProfileOwner(adminReceiver, userHandle)) {
+                    Slog.e(LOG_TAG, "Device/profile owner cannot be removed: component=" +
+                            adminReceiver);
                     return;
                 }
                 mContext.enforceCallingOrSelfPermission(
@@ -3184,7 +3186,8 @@
         if (!mHasFeature) {
             return false;
         }
-        final int userHandle = UserHandle.getCallingUserId();
+        final int callingUid = mInjector.binderGetCallingUid();
+        final int userHandle = mInjector.userHandleGetCallingUserId();
 
         long ident = mInjector.binderClearCallingIdentity();
         try {
@@ -3200,10 +3203,16 @@
 
         int quality;
         synchronized (this) {
-            // This api can only be called by an active device admin,
-            // so try to retrieve it to check that the caller is one.
-            final ActiveAdmin admin = getActiveAdminForCallerLocked(null,
-                    DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
+            // If caller has PO (or DO), it can clear the password, so see if that's the case
+            // first.
+            ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
+                    null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
+            if (admin == null) {
+                // Otherwise, make sure the caller has any active admin with the right policy.
+                admin = getActiveAdminForCallerLocked(null,
+                        DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
+            }
+
             final ComponentName adminComponent = admin.info.getComponent();
 
             // As of N, only profile owners and device owners can reset the password.
@@ -3316,7 +3325,6 @@
             }
         }
 
-        int callingUid = mInjector.binderGetCallingUid();
         DevicePolicyData policy = getUserData(userHandle);
         if (policy.mPasswordOwner >= 0 && policy.mPasswordOwner != callingUid) {
             Slog.w(LOG_TAG, "resetPassword: already set by another uid and not entered by user");
diff --git a/tests/RenderScriptTests/Fountain/Android.mk b/tests/RenderScriptTests/Fountain/Android.mk
deleted file mode 100644
index 0517aef..0000000
--- a/tests/RenderScriptTests/Fountain/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2008 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
-
-LOCAL_SDK_VERSION := 17
-
-LOCAL_PACKAGE_NAME := RsFountain
-
-include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/Fountain/AndroidManifest.xml b/tests/RenderScriptTests/Fountain/AndroidManifest.xml
deleted file mode 100644
index d19b8c3..0000000
--- a/tests/RenderScriptTests/Fountain/AndroidManifest.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.example.android.rs.fountain">
-    <uses-sdk android:minSdkVersion="14" />
-    <application
-        android:label="RsFountain"
-        android:hardwareAccelerated="true"
-        android:icon="@drawable/test_pattern">
-        <activity android:name="Fountain">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/tests/RenderScriptTests/Fountain/_index.html b/tests/RenderScriptTests/Fountain/_index.html
deleted file mode 100644
index 223242f..0000000
--- a/tests/RenderScriptTests/Fountain/_index.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<p>An example that renders many dots on the screen that follow a user's touch. The dots fall 
-to the bottom of the screen when the user releases the finger.</p>
-
-
-
diff --git a/tests/RenderScriptTests/Fountain/res/drawable/test_pattern.png b/tests/RenderScriptTests/Fountain/res/drawable/test_pattern.png
deleted file mode 100644
index e7d1455..0000000
--- a/tests/RenderScriptTests/Fountain/res/drawable/test_pattern.png
+++ /dev/null
Binary files differ
diff --git a/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/Fountain.java b/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/Fountain.java
deleted file mode 100644
index 311455a..0000000
--- a/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/Fountain.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2008 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.example.android.rs.fountain;
-
-import android.renderscript.RSSurfaceView;
-import android.renderscript.RenderScript;
-
-import android.app.Activity;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.provider.Settings.System;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.Window;
-import android.widget.Button;
-import android.widget.ListView;
-
-import java.lang.Runtime;
-
-public class Fountain extends Activity {
-    //EventListener mListener = new EventListener();
-
-    private static final String LOG_TAG = "libRS_jni";
-    private static final boolean DEBUG  = false;
-    private static final boolean LOG_ENABLED = false;
-
-    private FountainView mView;
-
-    // get the current looper (from your Activity UI thread for instance
-
-
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        // Create our Preview view and set it as the content of our
-        // Activity
-        mView = new FountainView(this);
-        setContentView(mView);
-    }
-
-    @Override
-    protected void onResume() {
-        Log.e("rs", "onResume");
-
-        // Ideally a game should implement onResume() and onPause()
-        // to take appropriate action when the activity looses focus
-        super.onResume();
-        mView.resume();
-    }
-
-    @Override
-    protected void onPause() {
-        Log.e("rs", "onPause");
-
-        // Ideally a game should implement onResume() and onPause()
-        // to take appropriate action when the activity looses focus
-        super.onPause();
-        mView.pause();
-
-
-
-        //Runtime.getRuntime().exit(0);
-    }
-
-
-    static void log(String message) {
-        if (LOG_ENABLED) {
-            Log.v(LOG_TAG, message);
-        }
-    }
-
-
-}
-
diff --git a/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/FountainRS.java b/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/FountainRS.java
deleted file mode 100644
index 646c807..0000000
--- a/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/FountainRS.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2008 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.example.android.rs.fountain;
-
-import android.content.res.Resources;
-import android.renderscript.*;
-import android.util.Log;
-
-
-public class FountainRS {
-    public static final int PART_COUNT = 50000;
-
-    public FountainRS() {
-    }
-
-    private Resources mRes;
-    private RenderScriptGL mRS;
-    private ScriptC_fountain mScript;
-    public void init(RenderScriptGL rs, Resources res) {
-        mRS = rs;
-        mRes = res;
-
-        ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);
-        pfb.setVaryingColor(true);
-        rs.bindProgramFragment(pfb.create());
-
-        ScriptField_Point points = new ScriptField_Point(mRS, PART_COUNT);//
- //                                                        Allocation.USAGE_GRAPHICS_VERTEX);
-
-        Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
-        smb.addVertexAllocation(points.getAllocation());
-        smb.addIndexSetType(Mesh.Primitive.POINT);
-        Mesh sm = smb.create();
-
-        mScript = new ScriptC_fountain(mRS, mRes, R.raw.fountain);
-        mScript.set_partMesh(sm);
-        mScript.bind_point(points);
-        mRS.bindRootScript(mScript);
-    }
-
-    boolean holdingColor[] = new boolean[10];
-    public void newTouchPosition(float x, float y, float pressure, int id) {
-        if (id >= holdingColor.length) {
-            return;
-        }
-        int rate = (int)(pressure * pressure * 500.f);
-        if (rate > 500) {
-            rate = 500;
-        }
-        if (rate > 0) {
-            mScript.invoke_addParticles(rate, x, y, id, !holdingColor[id]);
-            holdingColor[id] = true;
-        } else {
-            holdingColor[id] = false;
-        }
-
-    }
-}
diff --git a/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/FountainView.java b/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/FountainView.java
deleted file mode 100644
index 98cec55..0000000
--- a/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/FountainView.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2008 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.example.android.rs.fountain;
-
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.concurrent.Semaphore;
-
-import android.renderscript.RSSurfaceView;
-import android.renderscript.RenderScript;
-import android.renderscript.RenderScriptGL;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-public class FountainView extends RSSurfaceView {
-
-    public FountainView(Context context) {
-        super(context);
-        //setFocusable(true);
-    }
-
-    private RenderScriptGL mRS;
-    private FountainRS mRender;
-
-    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-        super.surfaceChanged(holder, format, w, h);
-        if (mRS == null) {
-            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
-            mRS = createRenderScriptGL(sc);
-            mRS.setSurface(holder, w, h);
-            mRender = new FountainRS();
-            mRender.init(mRS, getResources());
-        }
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        if (mRS != null) {
-            mRS = null;
-            destroyRenderScriptGL();
-        }
-    }
-
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev)
-    {
-        int act = ev.getActionMasked();
-        if (act == ev.ACTION_UP) {
-            mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0));
-            return false;
-        } else if (act == MotionEvent.ACTION_POINTER_UP) {
-            // only one pointer going up, we can get the index like this
-            int pointerIndex = ev.getActionIndex();
-            int pointerId = ev.getPointerId(pointerIndex);
-            mRender.newTouchPosition(0, 0, 0, pointerId);
-        }
-        int count = ev.getHistorySize();
-        int pcount = ev.getPointerCount();
-
-        for (int p=0; p < pcount; p++) {
-            int id = ev.getPointerId(p);
-            mRender.newTouchPosition(ev.getX(p),
-                                     ev.getY(p),
-                                     ev.getPressure(p),
-                                     id);
-
-            for (int i=0; i < count; i++) {
-                mRender.newTouchPosition(ev.getHistoricalX(p, i),
-                                         ev.getHistoricalY(p, i),
-                                         ev.getHistoricalPressure(p, i),
-                                         id);
-            }
-        }
-        return true;
-    }
-}
-
-
diff --git a/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/fountain.rs b/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/fountain.rs
deleted file mode 100644
index 151b689..0000000
--- a/tests/RenderScriptTests/Fountain/src/com/example/android/rs/fountain/fountain.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-// Fountain test script
-#pragma version(1)
-#pragma rs_fp_relaxed
-
-#pragma rs java_package_name(com.example.android.rs.fountain)
-
-#pragma stateFragment(parent)
-
-#include "rs_graphics.rsh"
-
-static int newPart = 0;
-rs_mesh partMesh;
-
-typedef struct __attribute__((packed, aligned(4))) Point {
-    float2 delta;
-    float2 position;
-    uchar4 color;
-} Point_t;
-Point_t *point;
-
-int root() {
-    float dt = min(rsGetDt(), 0.1f);
-    rsgClearColor(0.f, 0.f, 0.f, 1.f);
-    const float height = rsgGetHeight();
-    const int size = rsAllocationGetDimX(rsGetAllocation(point));
-    float dy2 = dt * (10.f);
-    Point_t * p = point;
-    for (int ct=0; ct < size; ct++) {
-        p->delta.y += dy2;
-        p->position += p->delta;
-        if ((p->position.y > height) && (p->delta.y > 0)) {
-            p->delta.y *= -0.3f;
-        }
-        p++;
-    }
-
-    rsgDrawMesh(partMesh);
-    return 1;
-}
-
-static float4 partColor[10];
-void addParticles(int rate, float x, float y, int index, bool newColor)
-{
-    if (newColor) {
-        partColor[index].x = rsRand(0.5f, 1.0f);
-        partColor[index].y = rsRand(1.0f);
-        partColor[index].z = rsRand(1.0f);
-    }
-    float rMax = ((float)rate) * 0.02f;
-    int size = rsAllocationGetDimX(rsGetAllocation(point));
-    uchar4 c = rsPackColorTo8888(partColor[index]);
-
-    Point_t * np = &point[newPart];
-    float2 p = {x, y};
-    while (rate--) {
-        float angle = rsRand(3.14f * 2.f);
-        float len = rsRand(rMax);
-        np->delta.x = len * sin(angle);
-        np->delta.y = len * cos(angle);
-        np->position = p;
-        np->color = c;
-        newPart++;
-        np++;
-        if (newPart >= size) {
-            newPart = 0;
-            np = &point[newPart];
-        }
-    }
-}
-
diff --git a/tests/RenderScriptTests/FountainFbo/Android.mk b/tests/RenderScriptTests/FountainFbo/Android.mk
deleted file mode 100644
index c0f3323..0000000
--- a/tests/RenderScriptTests/FountainFbo/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (C) 2008 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
-
-# TODO: build fails with this set
-# LOCAL_SDK_VERSION := current
-
-LOCAL_PACKAGE_NAME := RsFountainFbo
-LOCAL_SDK_VERSION := 14
-
-include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/FountainFbo/AndroidManifest.xml b/tests/RenderScriptTests/FountainFbo/AndroidManifest.xml
deleted file mode 100644
index 082744b..0000000
--- a/tests/RenderScriptTests/FountainFbo/AndroidManifest.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.example.android.rs.fountainfbo">
-    <uses-sdk android:minSdkVersion="14" />
-    <application
-        android:label="RsFountainFbo"
-        android:hardwareAccelerated="true"
-        android:icon="@drawable/test_pattern">
-        <activity android:name="FountainFbo">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/tests/RenderScriptTests/FountainFbo/_index.html b/tests/RenderScriptTests/FountainFbo/_index.html
deleted file mode 100644
index 5508657..0000000
--- a/tests/RenderScriptTests/FountainFbo/_index.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<p>An example that renders many dots on the screen that follow a user's touch. The dots fall 
-to the bottom of the screen when no touch is detected. This example modifies
-the <a href="../Fountain/index.html">Fountain</a> sample to include rendering to a
-a framebuffer object as well as the default framebuffer.</p>
-
-
-
diff --git a/tests/RenderScriptTests/FountainFbo/res/drawable/test_pattern.png b/tests/RenderScriptTests/FountainFbo/res/drawable/test_pattern.png
deleted file mode 100644
index e7d1455..0000000
--- a/tests/RenderScriptTests/FountainFbo/res/drawable/test_pattern.png
+++ /dev/null
Binary files differ
diff --git a/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/FountainFbo.java b/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/FountainFbo.java
deleted file mode 100644
index d8ba30fd..0000000
--- a/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/FountainFbo.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2008 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.example.android.rs.fountainfbo;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-
-public class FountainFbo extends Activity {
-    private static final String LOG_TAG = "libRS_jni";
-    private static final boolean DEBUG  = false;
-    private static final boolean LOG_ENABLED = false;
-
-    private FountainFboView mView;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        /* Create our Preview view and set it as the content of our Activity */
-        mView = new FountainFboView(this);
-        setContentView(mView);
-    }
-
-    @Override
-    protected void onResume() {
-        Log.e("rs", "onResume");
-
-        /* Ideally a game should implement onResume() and onPause()
-         to take appropriate action when the activity loses focus */
-        super.onResume();
-        mView.resume();
-    }
-
-    @Override
-    protected void onPause() {
-        Log.e("rs", "onPause");
-
-        /* Ideally a game should implement onResume() and onPause()
-        to take appropriate action when the activity loses focus */
-        super.onPause();
-        mView.pause();
-    }
-
-    static void log(String message) {
-        if (LOG_ENABLED) {
-            Log.v(LOG_TAG, message);
-        }
-    }
-}
-
diff --git a/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/FountainFboRS.java b/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/FountainFboRS.java
deleted file mode 100644
index 3bf3ff1..0000000
--- a/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/FountainFboRS.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2008 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.example.android.rs.fountainfbo;
-
-import android.content.res.Resources;
-import android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.Mesh;
-import android.renderscript.ProgramFragment;
-import android.renderscript.ProgramFragmentFixedFunction;
-import android.renderscript.RenderScriptGL;
-import android.renderscript.Type;
-
-public class FountainFboRS {
-    public static final int PART_COUNT = 50000;
-
-    public FountainFboRS() {
-    }
-
-    private Resources mRes;
-    private RenderScriptGL mRS;
-    private ScriptC_fountainfbo mScript;
-    private Allocation mColorBuffer;
-    private ProgramFragment mProgramFragment;
-    private ProgramFragment mTextureProgramFragment;
-    public void init(RenderScriptGL rs, Resources res) {
-      mRS = rs;
-      mRes = res;
-
-      ScriptField_Point points = new ScriptField_Point(mRS, PART_COUNT);
-
-      Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
-      smb.addVertexAllocation(points.getAllocation());
-      smb.addIndexSetType(Mesh.Primitive.POINT);
-      Mesh sm = smb.create();
-
-      mScript = new ScriptC_fountainfbo(mRS, mRes, R.raw.fountainfbo);
-      mScript.set_partMesh(sm);
-      mScript.bind_point(points);
-
-      ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);
-      pfb.setVaryingColor(true);
-      mProgramFragment = pfb.create();
-      mScript.set_gProgramFragment(mProgramFragment);
-
-      /* Second fragment shader to use a texture (framebuffer object) to draw with */
-      pfb.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
-          ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
-
-      /* Set the fragment shader in the Renderscript runtime */
-      mTextureProgramFragment = pfb.create();
-      mScript.set_gTextureProgramFragment(mTextureProgramFragment);
-
-      /* Create the allocation for the color buffer */
-      Type.Builder colorBuilder = new Type.Builder(mRS, Element.RGBA_8888(mRS));
-      colorBuilder.setX(256).setY(256);
-      mColorBuffer = Allocation.createTyped(mRS, colorBuilder.create(),
-      Allocation.USAGE_GRAPHICS_TEXTURE |
-      Allocation.USAGE_GRAPHICS_RENDER_TARGET);
-
-      /* Set the allocation in the Renderscript runtime */
-      mScript.set_gColorBuffer(mColorBuffer);
-
-      mRS.bindRootScript(mScript);
-  }
-
-    boolean holdingColor[] = new boolean[10];
-    public void newTouchPosition(float x, float y, float pressure, int id) {
-        if (id >= holdingColor.length) {
-            return;
-        }
-        int rate = (int)(pressure * pressure * 500.f);
-        if (rate > 500) {
-            rate = 500;
-        }
-        if (rate > 0) {
-            mScript.invoke_addParticles(rate, x, y, id, !holdingColor[id]);
-            holdingColor[id] = true;
-        } else {
-            holdingColor[id] = false;
-        }
-
-    }
-}
-
diff --git a/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/FountainFboView.java b/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/FountainFboView.java
deleted file mode 100644
index 8636717..0000000
--- a/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/FountainFboView.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2008 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.example.android.rs.fountainfbo;
-
-
-import android.renderscript.RSSurfaceView;
-import android.renderscript.RenderScriptGL;
-import android.content.Context;
-import android.view.SurfaceHolder;
-import android.view.MotionEvent;
-
-public class FountainFboView extends RSSurfaceView {
-
-    public FountainFboView(Context context) {
-        super(context);
-    }
-
-    private RenderScriptGL mRS;
-    private FountainFboRS mRender;
-
-    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-        super.surfaceChanged(holder, format, w, h);
-        if (mRS == null) {
-            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
-            mRS = createRenderScriptGL(sc);
-            mRS.setSurface(holder, w, h);
-            mRender = new FountainFboRS();
-            mRender.init(mRS, getResources());
-        }
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        android.util.Log.e("rs", "onDetachedFromWindow");
-        if (mRS != null) {
-            mRS = null;
-            destroyRenderScriptGL();
-        }
-    }
-
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev)
-    {
-        int act = ev.getActionMasked();
-        if (act == ev.ACTION_UP) {
-            mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0));
-            return false;
-        } else if (act == MotionEvent.ACTION_POINTER_UP) {
-            // only one pointer going up, we can get the index like this
-            int pointerIndex = ev.getActionIndex();
-            int pointerId = ev.getPointerId(pointerIndex);
-            mRender.newTouchPosition(0, 0, 0, pointerId);
-        }
-        int count = ev.getHistorySize();
-        int pcount = ev.getPointerCount();
-
-        for (int p=0; p < pcount; p++) {
-            int id = ev.getPointerId(p);
-            mRender.newTouchPosition(ev.getX(p),
-                                     ev.getY(p),
-                                     ev.getPressure(p),
-                                     id);
-
-            for (int i=0; i < count; i++) {
-                mRender.newTouchPosition(ev.getHistoricalX(p, i),
-                                         ev.getHistoricalY(p, i),
-                                         ev.getHistoricalPressure(p, i),
-                                         id);
-            }
-        }
-        return true;
-    }
-}
-
-
diff --git a/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/fountainfbo.rs b/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/fountainfbo.rs
deleted file mode 100644
index 763f6ba..0000000
--- a/tests/RenderScriptTests/FountainFbo/src/com/example/android/rs/fountainfbo/fountainfbo.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-// Fountain test script
-#pragma version(1)
-
-#pragma rs java_package_name(com.example.android.rs.fountainfbo)
-
-#pragma stateFragment(parent)
-
-#include "rs_graphics.rsh"
-
-static int newPart = 0;
-rs_mesh partMesh;
-rs_program_vertex gProgramVertex;
-
-//allocation for color buffer
-rs_allocation gColorBuffer;
-//fragment shader for rendering without a texture (used for rendering to framebuffer object)
-rs_program_fragment gProgramFragment;
-//fragment shader for rendering with a texture (used for rendering to default framebuffer)
-rs_program_fragment gTextureProgramFragment;
-
-typedef struct __attribute__((packed, aligned(4))) Point {
-    float2 delta;
-    float2 position;
-    uchar4 color;
-} Point_t;
-Point_t *point;
-
-int root() {
-    float dt = min(rsGetDt(), 0.1f);
-    rsgClearColor(0.f, 0.f, 0.f, 1.f);
-    const float height = rsgGetHeight();
-    const int size = rsAllocationGetDimX(rsGetAllocation(point));
-    float dy2 = dt * (10.f);
-    Point_t * p = point;
-    for (int ct=0; ct < size; ct++) {
-        p->delta.y += dy2;
-        p->position += p->delta;
-        if ((p->position.y > height) && (p->delta.y > 0)) {
-            p->delta.y *= -0.3f;
-        }
-        p++;
-    }
-    //Tell Renderscript runtime to render to the frame buffer object
-    rsgBindColorTarget(gColorBuffer, 0);
-
-    //Begin rendering on a white background
-    rsgClearColor(1.f, 1.f, 1.f, 1.f);
-    rsgDrawMesh(partMesh);
-
-    //When done, tell Renderscript runtime to stop rendering to framebuffer object
-    rsgClearAllRenderTargets();
-
-    //Bind a new fragment shader that declares the framebuffer object to be used as a texture
-    rsgBindProgramFragment(gTextureProgramFragment);
-
-    //Bind the framebuffer object to the fragment shader at slot 0 as a texture
-    rsgBindTexture(gTextureProgramFragment, 0, gColorBuffer);
-
-    //Draw a quad using the framebuffer object as the texture
-    float startX = 10, startY = 10;
-    float s = 256;
-    rsgDrawQuadTexCoords(startX, startY, 0, 0, 1,
-                         startX, startY + s, 0, 0, 0,
-                         startX + s, startY + s, 0, 1, 0,
-                         startX + s, startY, 0, 1, 1);
-
-    //Rebind the original fragment shader to render as normal
-    rsgBindProgramFragment(gProgramFragment);
-
-    //Render the main scene
-    rsgDrawMesh(partMesh);
-
-    return 1;
-}
-
-static float4 partColor[10];
-void addParticles(int rate, float x, float y, int index, bool newColor)
-{
-    if (newColor) {
-        partColor[index].x = rsRand(0.5f, 1.0f);
-        partColor[index].y = rsRand(1.0f);
-        partColor[index].z = rsRand(1.0f);
-    }
-    float rMax = ((float)rate) * 0.02f;
-    int size = rsAllocationGetDimX(rsGetAllocation(point));
-    uchar4 c = rsPackColorTo8888(partColor[index]);
-
-    Point_t * np = &point[newPart];
-    float2 p = {x, y};
-    while (rate--) {
-        float angle = rsRand(3.14f * 2.f);
-        float len = rsRand(rMax);
-        np->delta.x = len * sin(angle);
-        np->delta.y = len * cos(angle);
-        np->position = p;
-        np->color = c;
-        newPart++;
-        np++;
-        if (newPart >= size) {
-            newPart = 0;
-            np = &point[newPart];
-        }
-    }
-}
-
-
diff --git a/tests/RenderScriptTests/Fountain_v11/Android.mk b/tests/RenderScriptTests/Fountain_v11/Android.mk
deleted file mode 100644
index ac2690c..0000000
--- a/tests/RenderScriptTests/Fountain_v11/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2008 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
-#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
-
-LOCAL_PACKAGE_NAME := Fountain_v11
-LOCAL_SDK_VERSION := 11
-
-include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/Fountain_v11/AndroidManifest.xml b/tests/RenderScriptTests/Fountain_v11/AndroidManifest.xml
deleted file mode 100644
index fcb4faf..0000000
--- a/tests/RenderScriptTests/Fountain_v11/AndroidManifest.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.fountain_v11">
-    <uses-sdk android:minSdkVersion="11" />
-    <application 
-        android:label="Fountain_v11"
-        android:icon="@drawable/test_pattern">
-        <activity android:name="Fountain_v11">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/tests/RenderScriptTests/Fountain_v11/_index.html b/tests/RenderScriptTests/Fountain_v11/_index.html
deleted file mode 100644
index 223242f..0000000
--- a/tests/RenderScriptTests/Fountain_v11/_index.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<p>An example that renders many dots on the screen that follow a user's touch. The dots fall 
-to the bottom of the screen when the user releases the finger.</p>
-
-
-
diff --git a/tests/RenderScriptTests/Fountain_v11/res/drawable/test_pattern.png b/tests/RenderScriptTests/Fountain_v11/res/drawable/test_pattern.png
deleted file mode 100644
index e7d1455..0000000
--- a/tests/RenderScriptTests/Fountain_v11/res/drawable/test_pattern.png
+++ /dev/null
Binary files differ
diff --git a/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/FountainRS.java b/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/FountainRS.java
deleted file mode 100644
index e858100..0000000
--- a/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/FountainRS.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2008 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.fountain_v11;
-
-import android.content.res.Resources;
-import android.renderscript.*;
-import android.util.Log;
-
-
-public class FountainRS {
-    public static final int PART_COUNT = 50000;
-
-    public FountainRS() {
-    }
-
-    private Resources mRes;
-    private RenderScriptGL mRS;
-    private ScriptC_fountain mScript;
-    public void init(RenderScriptGL rs, Resources res, int width, int height) {
-        mRS = rs;
-        mRes = res;
-
-        ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);
-        pfb.setVaryingColor(true);
-        rs.bindProgramFragment(pfb.create());
-
-        ScriptField_Point points = new ScriptField_Point(mRS, PART_COUNT);//
- //                                                        Allocation.USAGE_GRAPHICS_VERTEX);
-
-        Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
-        smb.addVertexAllocation(points.getAllocation());
-        smb.addIndexSetType(Mesh.Primitive.POINT);
-        Mesh sm = smb.create();
-
-        mScript = new ScriptC_fountain(mRS, mRes, R.raw.fountain);
-        mScript.set_partMesh(sm);
-        mScript.bind_point(points);
-        mRS.bindRootScript(mScript);
-    }
-
-    boolean holdingColor[] = new boolean[10];
-    public void newTouchPosition(float x, float y, float pressure, int id) {
-        if (id >= holdingColor.length) {
-            return;
-        }
-        int rate = (int)(pressure * pressure * 500.f);
-        if (rate > 500) {
-            rate = 500;
-        }
-        if (rate > 0) {
-            mScript.invoke_addParticles(rate, x, y, id, !holdingColor[id]);
-            holdingColor[id] = true;
-        } else {
-            holdingColor[id] = false;
-        }
-
-    }
-}
diff --git a/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/FountainView.java b/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/FountainView.java
deleted file mode 100644
index e82376c..0000000
--- a/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/FountainView.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2008 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.fountain_v11;
-
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.concurrent.Semaphore;
-
-import android.renderscript.RSSurfaceView;
-import android.renderscript.RenderScript;
-import android.renderscript.RenderScriptGL;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-public class FountainView extends RSSurfaceView {
-
-    public FountainView(Context context) {
-        super(context);
-        //setFocusable(true);
-    }
-
-    private RenderScriptGL mRS;
-    private FountainRS mRender;
-
-    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-        super.surfaceChanged(holder, format, w, h);
-        if (mRS == null) {
-            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
-            mRS = createRenderScriptGL(sc);
-            mRS.setSurface(holder, w, h);
-            mRender = new FountainRS();
-            mRender.init(mRS, getResources(), w, h);
-        }
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        if (mRS != null) {
-            mRS = null;
-            destroyRenderScriptGL();
-        }
-    }
-
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev)
-    {
-        int act = ev.getActionMasked();
-        if (act == ev.ACTION_UP) {
-            mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0));
-            return false;
-        } else if (act == MotionEvent.ACTION_POINTER_UP) {
-            // only one pointer going up, we can get the index like this
-            int pointerIndex = ev.getActionIndex();
-            int pointerId = ev.getPointerId(pointerIndex);
-            mRender.newTouchPosition(0, 0, 0, pointerId);
-        }
-        int count = ev.getHistorySize();
-        int pcount = ev.getPointerCount();
-
-        for (int p=0; p < pcount; p++) {
-            int id = ev.getPointerId(p);
-            mRender.newTouchPosition(ev.getX(p),
-                                     ev.getY(p),
-                                     ev.getPressure(p),
-                                     id);
-
-            for (int i=0; i < count; i++) {
-                mRender.newTouchPosition(ev.getHistoricalX(p, i),
-                                         ev.getHistoricalY(p, i),
-                                         ev.getHistoricalPressure(p, i),
-                                         id);
-            }
-        }
-        return true;
-    }
-}
-
-
diff --git a/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/Fountain_v11.java b/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/Fountain_v11.java
deleted file mode 100644
index 2c07b27..0000000
--- a/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/Fountain_v11.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2008 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.fountain_v11;
-
-import android.renderscript.RSSurfaceView;
-import android.renderscript.RenderScript;
-
-import android.app.Activity;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.provider.Settings.System;
-import android.util.Config;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.Window;
-import android.widget.Button;
-import android.widget.ListView;
-
-import java.lang.Runtime;
-
-public class Fountain_v11 extends Activity {
-    //EventListener mListener = new EventListener();
-
-    private static final String LOG_TAG = "libRS_jni";
-    private static final boolean DEBUG  = false;
-    private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
-
-    private FountainView mView;
-
-    // get the current looper (from your Activity UI thread for instance
-
-
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        // Create our Preview view and set it as the content of our
-        // Activity
-        mView = new FountainView(this);
-        setContentView(mView);
-    }
-
-    @Override
-    protected void onResume() {
-        Log.e("rs", "onResume");
-
-        // Ideally a game should implement onResume() and onPause()
-        // to take appropriate action when the activity looses focus
-        super.onResume();
-        mView.resume();
-    }
-
-    @Override
-    protected void onPause() {
-        Log.e("rs", "onPause");
-
-        // Ideally a game should implement onResume() and onPause()
-        // to take appropriate action when the activity looses focus
-        super.onPause();
-        mView.pause();
-
-
-
-        //Runtime.getRuntime().exit(0);
-    }
-
-
-    static void log(String message) {
-        if (LOG_ENABLED) {
-            Log.v(LOG_TAG, message);
-        }
-    }
-
-
-}
-
diff --git a/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/fountain.rs b/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/fountain.rs
deleted file mode 100644
index 3b6c89a..0000000
--- a/tests/RenderScriptTests/Fountain_v11/src/com/android/fountain/fountain.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-// Fountain test script
-#pragma version(1)
-
-#pragma rs java_package_name(com.android.fountain_v11)
-
-#pragma stateFragment(parent)
-
-#include "rs_graphics.rsh"
-
-static int newPart = 0;
-rs_mesh partMesh;
-
-typedef struct __attribute__((packed, aligned(4))) Point {
-    float2 delta;
-    float2 position;
-    uchar4 color;
-} Point_t;
-Point_t *point;
-
-int root() {
-    float dt = min(rsGetDt(), 0.1f);
-    rsgClearColor(0.f, 0.f, 0.f, 1.f);
-    const float height = rsgGetHeight();
-    const int size = rsAllocationGetDimX(rsGetAllocation(point));
-    float dy2 = dt * (10.f);
-    Point_t * p = point;
-    for (int ct=0; ct < size; ct++) {
-        p->delta.y += dy2;
-        p->position += p->delta;
-        if ((p->position.y > height) && (p->delta.y > 0)) {
-            p->delta.y *= -0.3f;
-        }
-        p++;
-    }
-
-    rsgDrawMesh(partMesh);
-    return 1;
-}
-
-static float4 partColor[10];
-void addParticles(int rate, float x, float y, int index, bool newColor)
-{
-    if (newColor) {
-        partColor[index].x = rsRand(0.5f, 1.0f);
-        partColor[index].y = rsRand(1.0f);
-        partColor[index].z = rsRand(1.0f);
-    }
-    float rMax = ((float)rate) * 0.02f;
-    int size = rsAllocationGetDimX(rsGetAllocation(point));
-    uchar4 c = rsPackColorTo8888(partColor[index]);
-
-    Point_t * np = &point[newPart];
-    float2 p = {x, y};
-    while (rate--) {
-        float angle = rsRand(3.14f * 2.f);
-        float len = rsRand(rMax);
-        np->delta.x = len * sin(angle);
-        np->delta.y = len * cos(angle);
-        np->position = p;
-        np->color = c;
-        newPart++;
-        np++;
-        if (newPart >= size) {
-            newPart = 0;
-            np = &point[newPart];
-        }
-    }
-}
-
diff --git a/tools/layoutlib/.idea/encodings.xml b/tools/layoutlib/.idea/encodings.xml
index e206d70..f758959 100644
--- a/tools/layoutlib/.idea/encodings.xml
+++ b/tools/layoutlib/.idea/encodings.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
-</project>
-
+  <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false">
+    <file url="PROJECT" charset="UTF-8" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
index b67afeb..cdcf0ea 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
@@ -76,19 +76,18 @@
             Class[] constructorParams = {View.class};
             Object[] constructorArgs = {getDecorContent()};
             LayoutlibCallback callback = params.getLayoutlibCallback();
-            // First try to load the class as was available before appcompat v23.1.1, without
-            // logging warnings.
+
+            // Check if the old action bar class is present.
+            String actionBarClass = WINDOW_ACTION_BAR_CLASS;
             try {
-                mWindowDecorActionBar = callback.loadClass(WINDOW_ACTION_BAR_CLASS,
-                        constructorParams, constructorArgs);
-            } catch (ClassNotFoundException ignore) {
-            }
-            if (mWindowDecorActionBar == null) {
-                // If failed, load the new class, while logging warnings.
-                mWindowDecorActionBar = callback.loadView(WINDOW_ACTION_BAR_CLASS_NEW,
-                        constructorParams, constructorArgs);
+                callback.findClass(actionBarClass);
+            } catch (ClassNotFoundException expected) {
+                // Failed to find the old class, use the newer one.
+                actionBarClass = WINDOW_ACTION_BAR_CLASS_NEW;
             }
 
+            mWindowDecorActionBar = callback.loadView(actionBarClass,
+                    constructorParams, constructorArgs);
             mWindowActionBarClass = mWindowDecorActionBar == null ? null :
                     mWindowDecorActionBar.getClass();
             setupActionBar();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 42e55e2..a6e5fb8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -33,7 +33,6 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.res.ColorStateList;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
@@ -228,18 +227,16 @@
      * Find the background color for this bar from the theme attributes. Only relevant to StatusBar
      * and NavigationBar.
      * <p/>
-     * Returns null if not found.
+     * Returns 0 if not found.
      *
      * @param colorAttrName the attribute name for the background color
      * @param translucentAttrName the attribute name for the translucency property of the bar.
      *
      * @throws NumberFormatException if color resolved to an invalid string.
      */
-    @Nullable
-    protected Integer getBarColor(@NonNull String colorAttrName,
-            @NonNull String translucentAttrName) {
+    protected int getBarColor(@NonNull String colorAttrName, @NonNull String translucentAttrName) {
         if (!Config.isGreaterOrEqual(mSimulatedPlatformVersion, LOLLIPOP)) {
-            return null;
+            return 0;
         }
         RenderResources renderResources = getContext().getRenderResources();
         // First check if the bar is translucent.
@@ -254,11 +251,10 @@
         if (transparent) {
             return getColor(renderResources, colorAttrName);
         }
-        return null;
+        return 0;
     }
 
-    @Nullable
-    private static Integer getColor(RenderResources renderResources, String attr) {
+    private static int getColor(RenderResources renderResources, String attr) {
         // From ?attr/foo to @color/bar. This is most likely an ItemResourceValue.
         ResourceValue resource = renderResources.findItemInTheme(attr, true);
         // Form @color/bar to the #AARRGGBB
@@ -279,7 +275,7 @@
                 }
             }
         }
-        return null;
+        return 0;
     }
 
     private ResourceValue getResourceValue(String reference) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
index d50ce23..9c89bfe2 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -65,8 +65,8 @@
         super(context, orientation, getShortestWidth(context)>= 600 ? LAYOUT_600DP_XML : LAYOUT_XML,
                 "navigation_bar.xml", simulatedPlatformVersion);
 
-        Integer color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
-        setBackgroundColor(color == null ? 0xFF000000 : color);
+        int color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
+        setBackgroundColor(color == 0 ? 0xFF000000 : color);
 
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 95a5a58..2dc7c65 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -71,9 +71,8 @@
         // FIXME: use FILL_H?
         setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
 
-        Integer color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
-        setBackgroundColor(
-                color == null ? Config.getStatusBarColor(simulatedPlatformVersion) : color);
+        int color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
+        setBackgroundColor(color == 0 ? Config.getStatusBarColor(simulatedPlatformVersion) : color);
 
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 2a4f583..0ffa357 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -421,7 +421,8 @@
                     gc.setComposite(AlphaComposite.Src);
 
                     gc.setColor(new Color(0x00000000, true));
-                    gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
+                    gc.fillRect(0, 0,
+                            mMeasuredScreenWidth, mMeasuredScreenHeight);
 
                     // done
                     gc.dispose();