Merge "Zen: Track next-alarm condition across reboots." into lmp-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index a8c2ddc..476d9f5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5323,6 +5323,7 @@
     method public boolean getScreenCaptureDisabled(android.content.ComponentName);
     method public boolean getStorageEncryption(android.content.ComponentName);
     method public int getStorageEncryptionStatus();
+    method public java.util.List<android.os.PersistableBundle> getTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName);
     method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
     method public boolean hasGrantedPolicy(android.content.ComponentName, int);
     method public boolean installCaCert(android.content.ComponentName, byte[]);
@@ -5371,6 +5372,7 @@
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
+    method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
     method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
     method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
     method public void uninstallAllUserCaCerts(android.content.ComponentName);
@@ -28104,6 +28106,7 @@
     method public final int getCapabilities();
     method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
     method public final java.util.List<android.telecom.Connection> getConnections();
+    method public final android.telecom.DisconnectCause getDisconnectCause();
     method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle();
     method public android.telecom.Connection getPrimaryConnection();
     method public final int getState();
@@ -28223,6 +28226,7 @@
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int BUSY = 7; // 0x7
     field public static final int CANCELED = 4; // 0x4
+    field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
     field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
     field public static final int ERROR = 1; // 0x1
     field public static final int LOCAL = 2; // 0x2
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 500634c..59daaab 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -885,7 +885,8 @@
     }
 
     /**
-     * Sets the target object whose property will be animated by this animation
+     * Sets the target object whose property will be animated by this animation. If the
+     * animator has been started, it will be canceled.
      *
      * @param target The object being animated
      */
@@ -893,6 +894,9 @@
     public void setTarget(@Nullable Object target) {
         final Object oldTarget = getTarget();
         if (oldTarget != target) {
+            if (isStarted()) {
+                cancel();
+            }
             mTarget = target == null ? null : new WeakReference<Object>(target);
             // New target should cause re-initialization prior to starting
             mInitialized = false;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 74502fc..d3ff79d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -31,6 +31,7 @@
 import android.net.ProxyInfo;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
@@ -40,6 +41,7 @@
 import android.provider.Settings;
 import android.security.Credentials;
 import android.service.restrictions.RestrictionsReceiver;
+import android.service.trust.TrustAgentService;
 import android.util.Log;
 
 import com.android.org.conscrypt.TrustedCertificateStore;
@@ -2604,25 +2606,29 @@
     }
 
     /**
-     * Sets a list of features to enable for a TrustAgent component. This is meant to be
-     * used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which will disable all
-     * trust agents but those with features enabled by this function call.
+     * Sets a list of configuration features to enable for a TrustAgent component. This is meant
+     * to be used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which disables all
+     * trust agents but those enabled by this function call. If flag
+     * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is not set, then this call has no effect.
      *
      * <p>The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call
-     * this method; if it has not, a security exception will be thrown.
+     * this method; if not, a security exception will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param agent Which component to enable features for.
-     * @param features List of features to enable. Consult specific TrustAgent documentation for
-     * the feature list.
-     * @hide
+     * @param target Component name of the agent to be enabled.
+     * @param options TrustAgent-specific feature bundle. If null for any admin, agent
+     * will be strictly disabled according to the state of the
+     *  {@link #KEYGUARD_DISABLE_TRUST_AGENTS} flag.
+     * <p>If {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is set and options is not null for all admins,
+     * then it's up to the TrustAgent itself to aggregate the values from all device admins.
+     * <p>Consult documentation for the specific TrustAgent to determine legal options parameters.
      */
-    public void setTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent,
-            List<String> features) {
+    public void setTrustAgentConfiguration(ComponentName admin, ComponentName target,
+            PersistableBundle options) {
         if (mService != null) {
             try {
-                mService.setTrustAgentFeaturesEnabled(admin, agent, features, UserHandle.myUserId());
+                mService.setTrustAgentConfiguration(admin, target, options, UserHandle.myUserId());
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -2630,24 +2636,30 @@
     }
 
     /**
-     * Gets list of enabled features for the given TrustAgent component. If admin is
-     * null, this will return the intersection of all features enabled for the given agent by all
-     * admins.
+     * Gets configuration for the given trust agent based on aggregating all calls to
+     * {@link #setTrustAgentConfiguration(ComponentName, ComponentName, PersistableBundle)} for
+     * all device admins.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param agent Which component to get enabled features for.
-     * @return List of enabled features.
-     * @hide
+     * @return configuration for the given trust agent.
      */
-    public List<String> getTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent) {
+    public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
+            ComponentName agent) {
+        return getTrustAgentConfiguration(admin, agent, UserHandle.myUserId());
+    }
+
+    /** @hide per-user version */
+    public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
+            ComponentName agent, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getTrustAgentFeaturesEnabled(admin, agent, UserHandle.myUserId());
+                return mService.getTrustAgentConfiguration(admin, agent, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
         }
-        return new ArrayList<String>(); // empty list
+        return new ArrayList<PersistableBundle>(); // empty list
     }
 
     /**
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c8e1780..07aa800 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -22,6 +22,7 @@
 import android.content.IntentFilter;
 import android.net.ProxyInfo;
 import android.os.Bundle;
+import android.os.PersistableBundle;
 import android.os.RemoteCallback;
 import android.os.UserHandle;
 import java.util.List;
@@ -183,8 +184,10 @@
     boolean getCrossProfileCallerIdDisabled(in ComponentName who);
     boolean getCrossProfileCallerIdDisabledForUser(int userId);
 
-    void setTrustAgentFeaturesEnabled(in ComponentName admin, in ComponentName agent, in List<String> features, int userId);
-    List<String> getTrustAgentFeaturesEnabled(in ComponentName admin, in ComponentName agent, int userId);
+    void setTrustAgentConfiguration(in ComponentName admin, in ComponentName agent,
+            in PersistableBundle args, int userId);
+    List<PersistableBundle> getTrustAgentConfiguration(in ComponentName admin,
+            in ComponentName agent, int userId);
 
     boolean addCrossProfileWidgetProvider(in ComponentName admin, String packageName);
     boolean removeCrossProfileWidgetProvider(in ComponentName admin, String packageName);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 9194ca8..a09c6c7 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1012,60 +1012,57 @@
         return null;
     }
 
+    /**
+     * Guess what the network request was trying to say so that the resulting
+     * network is accessible via the legacy (deprecated) API such as
+     * requestRouteToHost.
+     * This means we should try to be fairly preceise about transport and
+     * capability but ignore things such as networkSpecifier.
+     * If the request has more than one transport or capability it doesn't
+     * match the old legacy requests (they selected only single transport/capability)
+     * so this function cannot map the request to a single legacy type and
+     * the resulting network will not be available to the legacy APIs.
+     *
+     * TODO - This should be removed when the legacy APIs are removed.
+     */
     private int inferLegacyTypeForNetworkCapabilities(NetworkCapabilities netCap) {
         if (netCap == null) {
             return TYPE_NONE;
         }
+
         if (!netCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
             return TYPE_NONE;
         }
+
+        String type = null;
+        int result = TYPE_NONE;
+
         if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
-            if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableCBS"))) {
-                return TYPE_MOBILE_CBS;
-            } else {
-                return TYPE_NONE;
-            }
+            type = "enableCBS";
+            result = TYPE_MOBILE_CBS;
+        } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
+            type = "enableIMS";
+            result = TYPE_MOBILE_IMS;
+        } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
+            type = "enableFOTA";
+            result = TYPE_MOBILE_FOTA;
+        } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
+            type = "enableDUN";
+            result = TYPE_MOBILE_DUN;
+        } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
+            type = "enableSUPL";
+            result = TYPE_MOBILE_SUPL;
+        } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+            type = "enableMMS";
+            result = TYPE_MOBILE_MMS;
+        } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
+            type = "enableHIPRI";
+            result = TYPE_MOBILE_HIPRI;
         }
-        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
-            if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableIMS"))) {
-                return TYPE_MOBILE_IMS;
-            } else {
-                return TYPE_NONE;
-            }
-        }
-        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
-            if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableFOTA"))) {
-                return TYPE_MOBILE_FOTA;
-            } else {
-                return TYPE_NONE;
-            }
-        }
-        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
-            if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableDUN"))) {
-                return TYPE_MOBILE_DUN;
-            } else {
-                return TYPE_NONE;
-            }
-        }
-        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
-            if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableSUPL"))) {
-                return TYPE_MOBILE_SUPL;
-            } else {
-                return TYPE_NONE;
-            }
-        }
-        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
-            if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableMMS"))) {
-                return TYPE_MOBILE_MMS;
-            } else {
-                return TYPE_NONE;
-            }
-        }
-        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
-            if (netCap.equals(networkCapabilitiesForFeature(TYPE_MOBILE, "enableHIPRI"))) {
-                return TYPE_MOBILE_HIPRI;
-            } else {
-                return TYPE_NONE;
+        if (type != null) {
+            NetworkCapabilities testCap = networkCapabilitiesForFeature(TYPE_MOBILE, type);
+            if (testCap.equalsNetCapabilities(netCap) && testCap.equalsTransportTypes(netCap)) {
+                return result;
             }
         }
         return TYPE_NONE;
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 1efe478..ce7ad65 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -235,7 +235,8 @@
         return ((nc.mNetworkCapabilities & this.mNetworkCapabilities) == this.mNetworkCapabilities);
     }
 
-    private boolean equalsNetCapabilities(NetworkCapabilities nc) {
+    /** @hide */
+    public boolean equalsNetCapabilities(NetworkCapabilities nc) {
         return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
     }
 
@@ -344,7 +345,8 @@
         return ((this.mTransportTypes == 0) ||
                 ((this.mTransportTypes & nc.mTransportTypes) != 0));
     }
-    private boolean equalsTransportTypes(NetworkCapabilities nc) {
+    /** @hide */
+    public boolean equalsTransportTypes(NetworkCapabilities nc) {
         return (nc.mTransportTypes == this.mTransportTypes);
     }
 
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 03a2085..a939cce 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -192,12 +192,15 @@
     /**
      * Set the active scorer to a new package and clear existing scores.
      *
+     * <p>Should never be called directly without obtaining user consent. This can be done by using
+     * the {@link #ACTION_CHANGE_ACTIVE} broadcast, or using a custom configuration activity.
+     *
      * @return true if the operation succeeded, or false if the new package is not a valid scorer.
      * @throws SecurityException if the caller does not hold the
-     *         {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission
-     *         indicating that it can manage scorer applications.
+     *         {@link android.Manifest.permission#SCORE_NETWORKS} permission.
      * @hide
      */
+    @SystemApi
     public boolean setActiveScorer(String packageName) throws SecurityException {
         try {
             return mService.setActiveScorer(packageName);
diff --git a/core/java/android/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl
index bd80a3f..bb0c2b2 100644
--- a/core/java/android/service/trust/ITrustAgentService.aidl
+++ b/core/java/android/service/trust/ITrustAgentService.aidl
@@ -15,7 +15,7 @@
  */
 package android.service.trust;
 
-import android.os.Bundle;
+import android.os.PersistableBundle;
 import android.service.trust.ITrustAgentServiceCallback;
 
 /**
@@ -25,6 +25,6 @@
 interface ITrustAgentService {
     oneway void onUnlockAttempt(boolean successful);
     oneway void onTrustTimeout();
+    oneway void onConfigure(in List<PersistableBundle> options, IBinder token);
     oneway void setCallback(ITrustAgentServiceCallback callback);
-    oneway void setTrustAgentFeaturesEnabled(in Bundle options, IBinder token);
 }
diff --git a/core/java/android/service/trust/ITrustAgentServiceCallback.aidl b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
index b107bcc..76b2be0 100644
--- a/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
+++ b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
@@ -27,5 +27,5 @@
     void grantTrust(CharSequence message, long durationMs, boolean initiatedByUser);
     void revokeTrust();
     void setManagingTrust(boolean managingTrust);
-    void onSetTrustAgentFeaturesEnabledCompleted(boolean result, IBinder token);
+    void onConfigureCompleted(boolean result, IBinder token);
 }
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index 3ef5b37..00d60c0 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -29,11 +29,14 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.Log;
 import android.util.Slog;
 
+import java.util.List;
+
 /**
  * A service that notifies the system about whether it believes the environment of the device
  * to be trusted.
@@ -86,17 +89,47 @@
      */
     public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
 
-    /**
-     * A white list of features that the given trust agent should support when otherwise disabled
-     * by device policy.
-     * @hide
-     */
-    public static final String KEY_FEATURES = "trust_agent_features";
-
     private static final int MSG_UNLOCK_ATTEMPT = 1;
-    private static final int MSG_SET_TRUST_AGENT_FEATURES_ENABLED = 2;
+    private static final int MSG_CONFIGURE = 2;
     private static final int MSG_TRUST_TIMEOUT = 3;
 
+    /**
+     * Container class for a list of configuration options and helper methods
+     */
+    public static final class Configuration {
+        public final List<PersistableBundle> options;
+        public Configuration(List<PersistableBundle> opts) {
+            options = opts;
+        }
+
+        /**
+         * Very basic method to determine if all bundles have the given feature, regardless
+         * of type.
+         * @param option String to search for.
+         * @return true if found in all bundles.
+         */
+        public boolean hasOption(String option) {
+            if (options == null || options.size() == 0) return false;
+            final int N = options.size();
+            for (int i = 0; i < N; i++) {
+                if (!options.get(i).containsKey(option)) return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Class containing raw data for a given configuration request.
+     */
+    private static final class ConfigurationData {
+        final IBinder token;
+        final List<PersistableBundle> options;
+        ConfigurationData(List<PersistableBundle> opts, IBinder t) {
+            options = opts;
+            token = t;
+        }
+    }
+
     private ITrustAgentServiceCallback mCallback;
 
     private Runnable mPendingGrantTrustTask;
@@ -112,13 +145,12 @@
                 case MSG_UNLOCK_ATTEMPT:
                     onUnlockAttempt(msg.arg1 != 0);
                     break;
-                case MSG_SET_TRUST_AGENT_FEATURES_ENABLED:
-                    Bundle features = msg.peekData();
-                    IBinder token = (IBinder) msg.obj;
-                    boolean result = onSetTrustAgentFeaturesEnabled(features);
+                case MSG_CONFIGURE:
+                    ConfigurationData data = (ConfigurationData) msg.obj;
+                    boolean result = onConfigure(new Configuration(data.options));
                     try {
                         synchronized (mLock) {
-                            mCallback.onSetTrustAgentFeaturesEnabledCompleted(result, token);
+                            mCallback.onConfigureCompleted(result, data.token);
                         }
                     } catch (RemoteException e) {
                         onError("calling onSetTrustAgentFeaturesEnabledCompleted()");
@@ -171,23 +203,16 @@
     }
 
     /**
-     * Called when device policy wants to restrict features in the agent in response to
-     * {@link DevicePolicyManager#setTrustAgentFeaturesEnabled(ComponentName, ComponentName, java.util.List) }.
-     * Agents that support this feature should overload this method and return 'true'.
+     * Called when device policy admin wants to enable specific options for agent in response to
+     * {@link DevicePolicyManager#setKeyguardDisabledFeatures(ComponentName, int)} and
+     * {@link DevicePolicyManager#setTrustAgentConfiguration(ComponentName, ComponentName,
+     * PersistableBundle)}.
+     * <p>Agents that support configuration options should overload this method and return 'true'.
      *
-     * The list of options can be obtained by calling
-     * options.getStringArrayList({@link #KEY_FEATURES}). Presence of a feature string in the list
-     * means it should be enabled ("white-listed"). Absence of the feature means it should be
-     * disabled. An empty list means all features should be disabled.
-     *
-     * This function is only called if {@link DevicePolicyManager#KEYGUARD_DISABLE_TRUST_AGENTS} is
-     * set.
-     *
-     * @param options Option feature bundle.
-     * @return true if the {@link TrustAgentService} supports this feature.
-     * @hide
+     * @param options bundle containing all options or null if none.
+     * @return true if the {@link TrustAgentService} supports configuration options.
      */
-    public boolean onSetTrustAgentFeaturesEnabled(Bundle options) {
+    public boolean onConfigure(Configuration options) {
         return false;
     }
 
@@ -295,6 +320,12 @@
         }
 
         @Override /* Binder API */
+        public void onConfigure(List<PersistableBundle> args, IBinder token) {
+            mHandler.obtainMessage(MSG_CONFIGURE, new ConfigurationData(args, token))
+                    .sendToTarget();
+        }
+
+        @Override /* Binder API */
         public void setCallback(ITrustAgentServiceCallback callback) {
             synchronized (mLock) {
                 mCallback = callback;
@@ -313,13 +344,6 @@
                 }
             }
         }
-
-        @Override /* Binder API */
-        public void setTrustAgentFeaturesEnabled(Bundle features, IBinder token) {
-            Message msg = mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_ENABLED, token);
-            msg.setData(features);
-            msg.sendToTarget();
-        }
     }
 
 }
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index b0cbcd2..b467f5a 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -110,6 +110,7 @@
     private static final int SECONDS_PER_MINUTE = 60;
     private static final int SECONDS_PER_HOUR = 60 * 60;
     private static final int SECONDS_PER_DAY = 24 * 60 * 60;
+    private static final int MILLIS_PER_MINUTE = 1000 * 60;
 
     /**
      * Returns elapsed time for the given millis, in the following format:
@@ -171,4 +172,24 @@
             return context.getString(com.android.internal.R.string.durationSeconds, seconds);
         }
     }
+
+    /**
+     * Returns elapsed time for the given millis, in the following format:
+     * 1 day 5 hrs; will include at most two units, can go down to minutes precision.
+     * @param context the application context
+     * @param millis the elapsed time in milli seconds
+     * @return the formatted elapsed time
+     * @hide
+     */
+    public static String formatShortElapsedTimeRoundingUpToMinutes(Context context, long millis) {
+        long minutesRoundedUp = (millis + MILLIS_PER_MINUTE - 1) / MILLIS_PER_MINUTE;
+
+        if (minutesRoundedUp == 0) {
+            return context.getString(com.android.internal.R.string.durationMinutes, 0);
+        } else if (minutesRoundedUp == 1) {
+            return context.getString(com.android.internal.R.string.durationMinute, 1);
+        }
+
+        return formatShortElapsedTime(context, minutesRoundedUp * MILLIS_PER_MINUTE);
+    }
 }
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 70cf9a8..d7eef6e 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -17,7 +17,7 @@
 
 #include <jni.h>
 
-#include <Caches.h>
+#include <ResourceCache.h>
 
 #if 0
     #define TRACE_BITMAP(code)  code
@@ -365,8 +365,8 @@
 static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {
     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
 #ifdef USE_OPENGL_RENDERER
-    if (android::uirenderer::Caches::hasInstance()) {
-        android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap);
+    if (android::uirenderer::ResourceCache::hasInstance()) {
+        android::uirenderer::ResourceCache::getInstance().destructor(bitmap);
         return;
     }
 #endif // USE_OPENGL_RENDERER
@@ -376,9 +376,9 @@
 static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
 #ifdef USE_OPENGL_RENDERER
-    if (android::uirenderer::Caches::hasInstance()) {
+    if (android::uirenderer::ResourceCache::hasInstance()) {
         bool result;
-        result = android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
+        result = android::uirenderer::ResourceCache::getInstance().recycle(bitmap);
         return result ? JNI_TRUE : JNI_FALSE;
     }
 #endif // USE_OPENGL_RENDERER
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index cf23771..be62fdd 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -21,7 +21,7 @@
 #include <androidfw/ResourceTypes.h>
 #include <utils/Log.h>
 
-#include <Caches.h>
+#include <ResourceCache.h>
 
 #include "Paint.h"
 #include "Canvas.h"
@@ -80,9 +80,9 @@
     static void finalize(JNIEnv* env, jobject, jlong patchHandle) {
         int8_t* patch = reinterpret_cast<int8_t*>(patchHandle);
 #ifdef USE_OPENGL_RENDERER
-        if (android::uirenderer::Caches::hasInstance()) {
+        if (android::uirenderer::ResourceCache::hasInstance()) {
             Res_png_9patch* p = (Res_png_9patch*) patch;
-            android::uirenderer::Caches::getInstance().resourceCache.destructor(p);
+            android::uirenderer::ResourceCache::getInstance().destructor(p);
             return;
         }
 #endif // USE_OPENGL_RENDERER
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index 9d3e74b..30ce58d 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -27,7 +27,7 @@
 #include "SkPath.h"
 #include "SkPathOps.h"
 
-#include <Caches.h>
+#include <ResourceCache.h>
 #include <vector>
 #include <map>
 
@@ -39,8 +39,8 @@
     static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
 #ifdef USE_OPENGL_RENDERER
-        if (android::uirenderer::Caches::hasInstance()) {
-            android::uirenderer::Caches::getInstance().resourceCache.destructor(obj);
+        if (android::uirenderer::ResourceCache::hasInstance()) {
+            android::uirenderer::ResourceCache::getInstance().destructor(obj);
             return;
         }
 #endif
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 91a8598..67ba27da 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -6388,7 +6388,7 @@
         <!-- The summary for the Preference in a PreferenceActivity screen. -->
         <attr name="summary" />
         <!-- The order for the Preference (lower values are to be ordered first). If this is not
-             specified, the default orderin will be alphabetic. -->
+             specified, the default ordering will be alphabetic. -->
         <attr name="order" format="integer" />
         <!-- When used inside of a modern PreferenceActivity, this declares
              a new PreferenceFragment to be shown when the user selects this item. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c5bd495..9e25ee2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -61,6 +61,9 @@
     <!-- [CHAR_LIMIT=10] Suffix added to signify duration in minutes -->
     <string name="durationMinutes"><xliff:g id="minutes">%1$d</xliff:g> mins</string>
 
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one minute -->
+    <string name="durationMinute"><xliff:g id="minutes">%1$d</xliff:g> min</string>
+
     <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one minute with seconds -->
     <string name="durationMinuteSeconds"><xliff:g id="minutes">%1$d</xliff:g> min
             <xliff:g id="seconds">%2$d</xliff:g> secs</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6e881a7..513510a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -574,6 +574,7 @@
   <java-symbol type="string" name="durationHourMinutes" />
   <java-symbol type="string" name="durationHourMinute" />
   <java-symbol type="string" name="durationMinutes" />
+  <java-symbol type="string" name="durationMinute" />
   <java-symbol type="string" name="durationMinuteSeconds" />
   <java-symbol type="string" name="durationMinuteSecond" />
   <java-symbol type="string" name="durationSeconds" />
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 7aa628c..e338686 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -340,7 +340,6 @@
     TessellationCache tessellationCache;
     TextDropShadowCache dropShadowCache;
     FboCache fboCache;
-    ResourceCache resourceCache;
 
     GammaFontRenderer* fontRenderer;
 
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 4a927cf..8953166 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -39,29 +39,28 @@
 }
 
 void DisplayListData::cleanupResources() {
-    Caches& caches = Caches::getInstance();
-    caches.unregisterFunctors(functors.size());
-    caches.resourceCache.lock();
+    ResourceCache& resourceCache = ResourceCache::getInstance();
+    resourceCache.lock();
 
     for (size_t i = 0; i < bitmapResources.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i));
+        resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i));
     }
 
     for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
         const SkBitmap* bitmap = ownedBitmapResources.itemAt(i);
-        caches.resourceCache.decrementRefcountLocked(bitmap);
-        caches.resourceCache.destructorLocked(bitmap);
+        resourceCache.decrementRefcountLocked(bitmap);
+        resourceCache.destructorLocked(bitmap);
     }
 
     for (size_t i = 0; i < patchResources.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
+        resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
     }
 
     for (size_t i = 0; i < sourcePaths.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
+        resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
     }
 
-    caches.resourceCache.unlock();
+    resourceCache.unlock();
 
     for (size_t i = 0; i < paints.size(); i++) {
         delete paints.itemAt(i);
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index c17dd09..1b1f6cc 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -21,7 +21,7 @@
 
 #include <private/hwui/DrawGlInfo.h>
 
-#include "Caches.h"
+#include "ResourceCache.h"
 #include "DeferredDisplayList.h"
 #include "DisplayListLogBuffer.h"
 #include "DisplayListOp.h"
@@ -32,7 +32,7 @@
 namespace uirenderer {
 
 DisplayListRenderer::DisplayListRenderer()
-    : mCaches(Caches::getInstance())
+    : mResourceCache(ResourceCache::getInstance())
     , mDisplayListData(NULL)
     , mTranslateX(0.0f)
     , mTranslateY(0.0f)
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 901e8f0..8068663 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -24,6 +24,7 @@
 
 #include "DisplayListLogBuffer.h"
 #include "RenderNode.h"
+#include "ResourceCache.h"
 
 namespace android {
 namespace uirenderer {
@@ -209,7 +210,7 @@
             mDisplayListData->paths.add(pathCopy);
         }
         if (mDisplayListData->sourcePaths.indexOf(path) < 0) {
-            mCaches.resourceCache.incrementRefcount(path);
+            mResourceCache.incrementRefcount(path);
             mDisplayListData->sourcePaths.add(path);
         }
         return pathCopy;
@@ -273,19 +274,19 @@
         // contents, and drawing again. The only fix would be to always copy it the first time,
         // which doesn't seem worth the extra cycles for this unlikely case.
         mDisplayListData->bitmapResources.add(bitmap);
-        mCaches.resourceCache.incrementRefcount(bitmap);
+        mResourceCache.incrementRefcount(bitmap);
         return bitmap;
     }
 
     inline const SkBitmap* refBitmapData(const SkBitmap* bitmap) {
         mDisplayListData->ownedBitmapResources.add(bitmap);
-        mCaches.resourceCache.incrementRefcount(bitmap);
+        mResourceCache.incrementRefcount(bitmap);
         return bitmap;
     }
 
     inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
         mDisplayListData->patchResources.add(patch);
-        mCaches.resourceCache.incrementRefcount(patch);
+        mResourceCache.incrementRefcount(patch);
         return patch;
     }
 
@@ -293,7 +294,7 @@
     DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
     DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
 
-    Caches& mCaches;
+    ResourceCache& mResourceCache;
     DisplayListData* mDisplayListData;
 
     float mTranslateX;
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index cc72ae0..0dad0dc 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -141,11 +141,12 @@
     GLint status;
     glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
     if (status != GL_TRUE) {
+        ALOGE("Error while compiling this shader:\n===\n%s\n===", source);
         // Some drivers return wrong values for GL_INFO_LOG_LENGTH
         // use a fixed size instead
         GLchar log[512];
         glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
-        LOG_ALWAYS_FATAL("Error while compiling shader: %s", log);
+        LOG_ALWAYS_FATAL("Shader info log: %s", log);
         return 0;
     }
 
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index c9ed9a7..13c5499 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -98,9 +98,6 @@
     mNeedsDisplayListDataSync = true;
     delete mStagingDisplayListData;
     mStagingDisplayListData = data;
-    if (mStagingDisplayListData) {
-        Caches::getInstance().registerFunctors(mStagingDisplayListData->functors.size());
-    }
 }
 
 /**
@@ -305,6 +302,10 @@
         // changes in isRenderable or, in the future, bounds
         damageSelf(info);
         deleteDisplayListData();
+        // TODO: Remove this caches stuff
+        if (mStagingDisplayListData && mStagingDisplayListData->functors.size()) {
+            Caches::getInstance().registerFunctors(mStagingDisplayListData->functors.size());
+        }
         mDisplayListData = mStagingDisplayListData;
         mStagingDisplayListData = NULL;
         if (mDisplayListData) {
@@ -321,6 +322,9 @@
         for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
             mDisplayListData->children()[i]->mRenderNode->decParentRefCount();
         }
+        if (mDisplayListData->functors.size()) {
+            Caches::getInstance().unregisterFunctors(mDisplayListData->functors.size());
+        }
     }
     delete mDisplayListData;
     mDisplayListData = NULL;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 329d92f..12d4928 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -21,6 +21,12 @@
 #include "Caches.h"
 
 namespace android {
+
+#ifdef USE_OPENGL_RENDERER
+using namespace uirenderer;
+ANDROID_SINGLETON_STATIC_INSTANCE(ResourceCache);
+#endif
+
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 8539d12..a922d53 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -22,6 +22,7 @@
 #include <SkBitmap.h>
 
 #include <utils/KeyedVector.h>
+#include <utils/Singleton.h>
 
 #include <androidfw/ResourceTypes.h>
 
@@ -53,11 +54,14 @@
     ResourceType resourceType;
 };
 
-class ANDROID_API ResourceCache {
-public:
+class ANDROID_API ResourceCache: public Singleton<ResourceCache> {
     ResourceCache();
     ~ResourceCache();
 
+    friend class Singleton<ResourceCache>;
+
+public:
+
     /**
      * When using these two methods, make sure to only invoke the *Locked()
      * variants of increment/decrementRefcount(), recyle() and destructor()
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 3b8cb19..7959841 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -572,6 +572,14 @@
      */
     public native List<byte[]> getSecureStops();
 
+    /**
+     * Access secure stop by secure stop ID.
+     *
+     * @param ssid - The secure stop ID provided by the license server.
+     *
+     * @hide - not part of the public API at this time
+     */
+    public native byte[] getSecureStop(byte[] ssid);
 
     /**
      * Process the SecureStop server response message ssRelease.  After authenticating
@@ -581,6 +589,12 @@
      */
     public native void releaseSecureStops(byte[] ssRelease);
 
+    /**
+     * Remove all secure stops without requiring interaction with the server.
+     *
+     * @hide - not part of the public API at this time
+     */
+     public native void releaseAllSecureStops();
 
     /**
      * String property name: identifies the maker of the DRM engine plugin
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 0fed27e..8e07ec0 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -1003,6 +1003,27 @@
     return ListOfVectorsToArrayListOfByteArray(env, secureStops);
 }
 
+static jbyteArray android_media_MediaDrm_getSecureStop(
+    JNIEnv *env, jobject thiz, jbyteArray ssid) {
+    sp<IDrm> drm = GetDrm(env, thiz);
+
+    if (drm == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                          "MediaDrm obj is null");
+        return NULL;
+    }
+
+    Vector<uint8_t> secureStop;
+
+    status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
+
+    if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
+        return NULL;
+    }
+
+    return VectorToJByteArray(env, secureStop);
+}
+
 static void android_media_MediaDrm_releaseSecureStops(
     JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
     sp<IDrm> drm = GetDrm(env, thiz);
@@ -1020,6 +1041,21 @@
     throwExceptionAsNecessary(env, err, "Failed to release secure stops");
 }
 
+static void android_media_MediaDrm_releaseAllSecureStops(
+    JNIEnv *env, jobject thiz) {
+    sp<IDrm> drm = GetDrm(env, thiz);
+
+    if (drm == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                          "MediaDrm obj is null");
+        return;
+    }
+
+    status_t err = drm->releaseAllSecureStops();
+
+    throwExceptionAsNecessary(env, err, "Failed to release all secure stops");
+}
+
 static jstring android_media_MediaDrm_getPropertyString(
     JNIEnv *env, jobject thiz, jstring jname) {
     sp<IDrm> drm = GetDrm(env, thiz);
@@ -1384,9 +1420,15 @@
     { "getSecureStops", "()Ljava/util/List;",
       (void *)android_media_MediaDrm_getSecureStops },
 
+    { "getSecureStop", "([B)[B",
+      (void *)android_media_MediaDrm_getSecureStop },
+
     { "releaseSecureStops", "([B)V",
       (void *)android_media_MediaDrm_releaseSecureStops },
 
+    { "releaseAllSecureStops", "()V",
+      (void *)android_media_MediaDrm_releaseAllSecureStops },
+
     { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
       (void *)android_media_MediaDrm_getPropertyString },
 
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index c9cefbd..c364d469 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -803,28 +803,12 @@
 android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz __unused,
                                                      jint audioSession)
 {
-    // kDefaultNumEffects is a "reasonable" value ensuring that only one query will be enough on
-    // most devices to get all active audio pre processing on a given session.
-    static const uint32_t kDefaultNumEffects = 5;
-
-    effect_descriptor_t *descriptors = new effect_descriptor_t[kDefaultNumEffects];
-    uint32_t numEffects = kDefaultNumEffects;
+    effect_descriptor_t *descriptors = new effect_descriptor_t[AudioEffect::kMaxPreProcessing];
+    uint32_t numEffects = AudioEffect::kMaxPreProcessing;
 
     status_t status = AudioEffect::queryDefaultPreProcessing(audioSession,
                                            descriptors,
                                            &numEffects);
-    if ((status != NO_ERROR && status != NO_MEMORY) ||
-            numEffects == 0) {
-        delete[] descriptors;
-        return NULL;
-    }
-    if (status == NO_MEMORY) {
-        delete [] descriptors;
-        descriptors = new effect_descriptor_t[numEffects];
-        status = AudioEffect::queryDefaultPreProcessing(audioSession,
-                                               descriptors,
-                                               &numEffects);
-    }
     if (status != NO_ERROR || numEffects == 0) {
         delete[] descriptors;
         return NULL;
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
index c650a0f..09c7165 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -21,7 +21,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
-import android.os.Bundle;
+import android.os.PersistableBundle;
 import android.preference.PreferenceManager;
 import android.service.trust.TrustAgentService;
 import android.support.v4.content.LocalBroadcastManager;
@@ -90,8 +90,15 @@
     }
 
     @Override
-    public boolean onSetTrustAgentFeaturesEnabled(Bundle options) {
-        Log.v(TAG, "Policy options received: " + options.getStringArrayList(KEY_FEATURES));
+    public boolean onConfigure(Configuration config) {
+        if (config != null && config.options != null) {
+           for (int i = 0; i < config.options.size(); i++) {
+               PersistableBundle options = config.options.get(i);
+               Log.v(TAG, "Policy options received: " + options.toString());
+           }
+        } else {
+            Log.w(TAG, "onConfigure() called with no options");
+        }
         // TODO: Handle options
         return true; // inform DPM that we support it
     }
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6e6f302..51ef0c3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -63,6 +63,8 @@
 
     <!-- thickness (height) of the navigation bar on phones that require it -->
     <dimen name="navigation_bar_size">@*android:dimen/navigation_bar_height</dimen>
+    <!-- Minimum swipe distance to catch the swipe gestures to invoke assist or switch tasks. -->
+    <dimen name="navigation_bar_min_swipe_distance">48dp</dimen>
 
     <!-- thickness (height) of the dead zone at the top of the navigation bar,
          reducing false presses on navbar buttons; approx 2mm -->
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 76e8181..be7d322 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -54,7 +54,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /** A proxy implementation for the recents component */
-public class AlternateRecentsComponent {
+public class AlternateRecentsComponent implements ActivityOptions.OnAnimationStartedListener {
 
     final public static String EXTRA_FROM_HOME = "recents.triggeredOverHome";
     final public static String EXTRA_FROM_SEARCH_HOME = "recents.triggeredOverSearchHome";
@@ -62,7 +62,9 @@
     final public static String EXTRA_FROM_TASK_ID = "recents.activeTaskId";
     final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "recents.triggeredFromAltTab";
     final public static String EXTRA_TRIGGERED_FROM_HOME_KEY = "recents.triggeredFromHomeKey";
+    final public static String EXTRA_REUSE_TASK_STACK_VIEWS = "recents.reuseTaskStackViews";
 
+    final public static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation";
     final public static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
     final public static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity";
 
@@ -77,7 +79,10 @@
     Context mContext;
     LayoutInflater mInflater;
     SystemServicesProxy mSystemServicesProxy;
+    Handler mHandler;
     boolean mBootCompleted;
+    boolean mStartAnimationTriggered;
+    boolean mCanReuseTaskStackViews = true;
 
     // Task launching
     RecentsConfiguration mConfig;
@@ -103,6 +108,7 @@
         mInflater = LayoutInflater.from(context);
         mContext = context;
         mSystemServicesProxy = new SystemServicesProxy(context);
+        mHandler = new Handler();
         mTaskStackBounds = new Rect();
     }
 
@@ -128,7 +134,7 @@
         }
 
         // When we start, preload the metadata associated with the previous tasks
-        RecentsTaskLoader.getInstance().preload(mContext);
+        RecentsTaskLoader.getInstance().preload(mContext, RecentsTaskLoader.ALL_TASKS);
     }
 
     public void onBootCompleted() {
@@ -176,7 +182,9 @@
     }
 
     public void onPreloadRecents() {
-        // Do nothing
+        // When we start, preload the metadata associated with the previous tasks
+        RecentsTaskLoader.getInstance().preload(mContext,
+                Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
     }
 
     public void onCancelPreloadingRecents() {
@@ -186,7 +194,7 @@
     void showRelativeAffiliatedTask(boolean showNextTask) {
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
         TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(),
-                -1, -1, false, true, null, null);
+                -1, -1, RecentsTaskLoader.ALL_TASKS, false, true, null, null);
         // Return early if there are no tasks
         if (stack.getTaskCount() == 0) return;
 
@@ -251,6 +259,8 @@
     }
 
     public void onConfigurationChanged(Configuration newConfig) {
+        // Don't reuse task stack views if the configuration changes
+        mCanReuseTaskStackViews = false;
         // Reload the header bar layout
         reloadHeaderBarLayout();
     }
@@ -364,23 +374,28 @@
      * Creates the activity options for a unknown state->recents transition.
      */
     ActivityOptions getUnknownTransitionActivityOptions() {
+        mStartAnimationTriggered = false;
         return ActivityOptions.makeCustomAnimation(mContext,
                 R.anim.recents_from_unknown_enter,
-                R.anim.recents_from_unknown_exit);
+                R.anim.recents_from_unknown_exit,
+                mHandler, this);
     }
 
     /**
      * Creates the activity options for a home->recents transition.
      */
     ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) {
+        mStartAnimationTriggered = false;
         if (fromSearchHome) {
             return ActivityOptions.makeCustomAnimation(mContext,
                     R.anim.recents_from_search_launcher_enter,
-                    R.anim.recents_from_search_launcher_exit);
+                    R.anim.recents_from_search_launcher_exit,
+                    mHandler, this);
         }
         return ActivityOptions.makeCustomAnimation(mContext,
                 R.anim.recents_from_launcher_enter,
-                R.anim.recents_from_launcher_exit);
+                R.anim.recents_from_launcher_exit,
+                mHandler, this);
     }
 
     /**
@@ -408,9 +423,10 @@
                 c.setBitmap(null);
             }
 
+            mStartAnimationTriggered = false;
             return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
                     thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
-                    toTaskRect.height(), null);
+                    toTaskRect.height(), this);
         }
 
         // If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -423,7 +439,7 @@
         // Get the stack of tasks that we are animating into
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
         TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(),
-                runningTaskId, -1, false, isTopTaskHome, null, null);
+                runningTaskId, -1, RecentsTaskLoader.ALL_TASKS, false, isTopTaskHome, null, null);
         if (stack.getTaskCount() == 0) {
             return null;
         }
@@ -529,11 +545,13 @@
         }
         intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, mTriggeredFromAltTab);
         intent.putExtra(EXTRA_FROM_TASK_ID, (topTask != null) ? topTask.id : -1);
+        intent.putExtra(EXTRA_REUSE_TASK_STACK_VIEWS, mCanReuseTaskStackViews);
         if (opts != null) {
             mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
         } else {
             mContext.startActivityAsUser(intent, UserHandle.CURRENT);
         }
+        mCanReuseTaskStackViews = true;
     }
 
     /** Sets the RecentsComponent callbacks. */
@@ -547,4 +565,42 @@
             sRecentsComponentCallbacks.onVisibilityChanged(visible);
         }
     }
+
+    /**** OnAnimationStartedListener Implementation ****/
+
+    @Override
+    public void onAnimationStarted() {
+        // Notify recents to start the enter animation
+        if (!mStartAnimationTriggered) {
+            // There can be a race condition between the start animation callback and
+            // the start of the new activity (where we register the receiver that listens
+            // to this broadcast, so we add our own receiver and if that gets called, then
+            // we know the activity has not yet started and we can retry sending the broadcast.
+            BroadcastReceiver fallbackReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if (getResultCode() == Activity.RESULT_OK) {
+                        mStartAnimationTriggered = true;
+                        return;
+                    }
+
+                    // Schedule for the broadcast to be sent again after some time
+                    mHandler.postDelayed(new Runnable() {
+                        @Override
+                        public void run() {
+                            onAnimationStarted();
+                        }
+                    }, 25);
+                }
+            };
+
+            // Send the broadcast to notify Recents that the animation has started
+            Intent intent = new Intent(ACTION_START_ENTER_ANIMATION);
+            intent.setPackage(mContext.getPackageName());
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+                    Intent.FLAG_RECEIVER_FOREGROUND);
+            mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
+                    fallbackReceiver, null, Activity.RESULT_CANCELED, null, null);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d2c55f7..f8d981f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -27,6 +27,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.content.res.Configuration;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -142,6 +143,12 @@
             } else if (action.equals(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
                 // If we are toggling Recents, then first unfilter any filtered stacks first
                 dismissRecentsToFocusedTaskOrHome(true);
+            } else if (action.equals(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION)) {
+                // Trigger the enter animation
+                onEnterAnimationTriggered();
+                // Notify the fallback receiver that we have successfully got the broadcast
+                // See AlternateRecentsComponent.onAnimationStarted()
+                setResultCode(Activity.RESULT_OK);
             }
         }
     };
@@ -157,7 +164,8 @@
                 // When the screen turns off, dismiss Recents to Home
                 dismissRecentsToHome(false);
                 // Start preloading some tasks in the background
-                RecentsTaskLoader.getInstance().preload(RecentsActivity.this);
+                RecentsTaskLoader.getInstance().preload(RecentsActivity.this,
+                        Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
             } else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
                 // When the search activity changes, update the Search widget
                 refreshSearchWidget();
@@ -188,6 +196,8 @@
                 AlternateRecentsComponent.EXTRA_FROM_TASK_ID, -1);
         mConfig.launchedWithAltTab = launchIntent.getBooleanExtra(
                 AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false);
+        mConfig.launchedReuseTaskStackViews = launchIntent.getBooleanExtra(
+                AlternateRecentsComponent.EXTRA_REUSE_TASK_STACK_VIEWS, false);
 
         // Load all the tasks
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
@@ -397,8 +407,12 @@
 
         // Update if we are getting a configuration change
         if (savedInstanceState != null) {
+            // Update RecentsConfiguration
+            mConfig = RecentsConfiguration.reinitialize(this,
+                    RecentsTaskLoader.getInstance().getSystemServicesProxy());
             mConfig.updateOnConfigurationChange();
-            onConfigurationChange();
+            // Trigger the enter animation
+            onEnterAnimationTriggered();
         }
 
         // Start listening for widget package changes if there is one bound, post it since we don't
@@ -428,19 +442,6 @@
         }
     }
 
-    /** Called when the configuration changes. */
-    void onConfigurationChange() {
-        // Update RecentsConfiguration
-        mConfig = RecentsConfiguration.reinitialize(this,
-                RecentsTaskLoader.getInstance().getSystemServicesProxy());
-
-        // Try and start the enter animation (or restart it on configuration changed)
-        ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
-        mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
-        // Animate the SystemUI scrim views
-        mScrimViews.startEnterRecentsAnimation();
-    }
-
     /** Handles changes to the activity visibility. */
     void onRecentsActivityVisibilityChanged(boolean visible) {
         if (!visible) {
@@ -474,6 +475,7 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(AlternateRecentsComponent.ACTION_HIDE_RECENTS_ACTIVITY);
         filter.addAction(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY);
+        filter.addAction(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION);
         registerReceiver(mServiceBroadcastReceiver, filter);
 
         // Register any broadcast receivers for the task loader
@@ -492,8 +494,8 @@
     protected void onStop() {
         super.onStop();
 
-        // Remove all the views
-        mRecentsView.removeAllTaskStacks();
+        // Notify the views that we are no longer visible
+        mRecentsView.onRecentsHidden();
 
         // Unregister the RecentsService receiver
         unregisterReceiver(mServiceBroadcastReceiver);
@@ -515,8 +517,7 @@
         }
     }
 
-    @Override
-    public void onEnterAnimationComplete() {
+    public void onEnterAnimationTriggered() {
         // Try and start the enter animation (or restart it on configuration changed)
         ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
         mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
@@ -584,7 +585,6 @@
 
     /** Called when debug mode is triggered */
     public void onDebugModeTriggered() {
-
         if (mConfig.developerOptionsEnabled) {
             SharedPreferences settings = getSharedPreferences(getPackageName(), 0);
             if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index bfea3f7..e0c76b1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -115,8 +115,8 @@
     public boolean launchedWithAltTab;
     public boolean launchedWithNoRecentTasks;
     public boolean launchedFromAppWithThumbnail;
-    public boolean launchedFromAppWithScreenshot;
     public boolean launchedFromHome;
+    public boolean launchedReuseTaskStackViews;
     public int launchedToTaskId;
 
     /** Misc **/
@@ -308,6 +308,7 @@
         launchedWithNoRecentTasks = false;
         launchedFromAppWithThumbnail = false;
         launchedFromHome = false;
+        launchedReuseTaskStackViews = false;
         launchedToTaskId = -1;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
index 4456066..735f79f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
@@ -82,4 +82,9 @@
     public boolean hasTriggered() {
         return mHasTriggered;
     }
+
+    /** Resets the doze trigger state. */
+    public void resetTrigger() {
+        mHasTriggered = false;
+    }
 }
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 b4f62d5..390507f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -260,6 +260,7 @@
     private static final String TAG = "RecentsTaskLoader";
 
     static RecentsTaskLoader sInstance;
+    public static final int ALL_TASKS = -1;
 
     SystemServicesProxy mSystemServicesProxy;
     DrawableLruCache mApplicationIconCache;
@@ -326,10 +327,9 @@
 
     /** Gets the list of recent tasks, ordered from back to front. */
     private static List<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp,
-            boolean isTopTaskHome) {
-        RecentsConfiguration config = RecentsConfiguration.getInstance();
+            int numTasksToLoad, boolean isTopTaskHome) {
         List<ActivityManager.RecentTaskInfo> tasks =
-                ssp.getRecentTasks(config.maxNumTasksToLoad, UserHandle.CURRENT.getIdentifier(),
+                ssp.getRecentTasks(numTasksToLoad, UserHandle.CURRENT.getIdentifier(),
                         isTopTaskHome);
         Collections.reverse(tasks);
         return tasks;
@@ -416,7 +416,8 @@
         ArrayList<Task.TaskKey> taskKeys = new ArrayList<Task.TaskKey>();
         ArrayList<Task> tasksToLoad = new ArrayList<Task>();
         TaskStack stack = getTaskStack(mSystemServicesProxy, context.getResources(),
-                -1, preloadCount, true, isTopTaskHome, taskKeys, tasksToLoad);
+                -1, preloadCount, RecentsTaskLoader.ALL_TASKS, true, isTopTaskHome, taskKeys,
+                tasksToLoad);
         SpaceNode root = new SpaceNode();
         root.setStack(stack);
 
@@ -428,10 +429,10 @@
     }
 
     /** Preloads the set of recent tasks (not including thumbnails). */
-    public void preload(Context context) {
+    public void preload(Context context, int numTasksToPreload) {
         ArrayList<Task> tasksToLoad = new ArrayList<Task>();
         getTaskStack(mSystemServicesProxy, context.getResources(),
-                -1, -1, true, true, null, tasksToLoad);
+                -1, -1, numTasksToPreload, true, true, null, tasksToLoad);
 
         // Start the task loader and add all the tasks we need to load
         mLoadQueue.addTasks(tasksToLoad);
@@ -440,11 +441,13 @@
 
     /** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */
     public synchronized TaskStack getTaskStack(SystemServicesProxy ssp, Resources res,
-            int preloadTaskId, int preloadTaskCount,
+            int preloadTaskId, int preloadTaskCount, int loadTaskCount,
             boolean loadTaskThumbnails, boolean isTopTaskHome,
             List<Task.TaskKey> taskKeysOut, List<Task> tasksToLoadOut) {
         RecentsConfiguration config = RecentsConfiguration.getInstance();
-        List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, isTopTaskHome);
+        List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp,
+                (loadTaskCount == ALL_TASKS ? config.maxNumTasksToLoad : loadTaskCount),
+                isTopTaskHome);
         HashMap<Task.ComponentNameKey, ActivityInfoHandle> activityInfoCache =
                 new HashMap<Task.ComponentNameKey, ActivityInfoHandle>();
         ArrayList<Task> tasksToAdd = new ArrayList<Task>();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index ff0330d..81ee839 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -95,42 +95,57 @@
 
     /** Set/get the bsp root node */
     public void setTaskStacks(ArrayList<TaskStack> stacks) {
-        // Remove all TaskStackViews (but leave the search bar)
+        int numStacks = stacks.size();
+
+        // Make a list of the stack view children only
+        ArrayList<TaskStackView> stackViews = new ArrayList<TaskStackView>();
         int childCount = getChildCount();
-        for (int i = childCount - 1; i >= 0; i--) {
-            View v = getChildAt(i);
-            if (v != mSearchBar) {
-                removeViewAt(i);
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child != mSearchBar) {
+                stackViews.add((TaskStackView) child);
             }
         }
 
-        // Create and add all the stacks for this partition of space.
+        // Remove all/extra stack views
+        int numTaskStacksToKeep = 0; // Keep no tasks if we are recreating the layout
+        if (mConfig.launchedReuseTaskStackViews) {
+            numTaskStacksToKeep = Math.min(childCount, numStacks);
+        }
+        for (int i = stackViews.size() - 1; i >= numTaskStacksToKeep; i--) {
+            removeView(stackViews.get(i));
+            stackViews.remove(i);
+        }
+
+        // Update the stack views that we are keeping
+        for (int i = 0; i < numTaskStacksToKeep; i++) {
+            stackViews.get(i).setStack(stacks.get(i));
+        }
+
+        // Add remaining/recreate stack views
         mStacks = stacks;
-        int numStacks = mStacks.size();
-        for (int i = 0; i < numStacks; i++) {
-            TaskStack stack = mStacks.get(i);
+        for (int i = stackViews.size(); i < numStacks; i++) {
+            TaskStack stack = stacks.get(i);
             TaskStackView stackView = new TaskStackView(getContext(), stack);
             stackView.setCallbacks(this);
-            // Enable debug mode drawing
-            if (mConfig.debugModeEnabled) {
-                stackView.setDebugOverlay(mDebugOverlay);
-            }
             addView(stackView);
         }
 
+        // Enable debug mode drawing on all the stacks if necessary
+        if (mConfig.debugModeEnabled) {
+            for (int i = childCount - 1; i >= 0; i--) {
+                View v = getChildAt(i);
+                if (v != mSearchBar) {
+                    TaskStackView stackView = (TaskStackView) v;
+                    stackView.setDebugOverlay(mDebugOverlay);
+                }
+            }
+        }
+
         // Reset the launched state
         mAlreadyLaunchingTask = false;
-    }
-
-    /** Removes all the task stack views from this recents view. */
-    public void removeAllTaskStacks() {
-        int childCount = getChildCount();
-        for (int i = childCount - 1; i >= 0; i--) {
-            View child = getChildAt(i);
-            if (child != mSearchBar) {
-                removeViewAt(i);
-            }
-        }
+        // Trigger a new layout
+        requestLayout();
     }
 
     /** Launches the focused task from the first stack if possible */
@@ -529,6 +544,19 @@
         mCb.onAllTaskViewsDismissed();
     }
 
+    /** Final callback after Recents is finally hidden. */
+    public void onRecentsHidden() {
+        // Notify each task stack view
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child != mSearchBar) {
+                TaskStackView stackView = (TaskStackView) child;
+                stackView.onRecentsHidden();
+            }
+        }
+    }
+
     @Override
     public void onTaskStackFilterTriggered() {
         // Hide the search bar
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 dee26e6..9df0db6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -40,6 +40,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 
 
 /* The visual representation of a task stack view */
@@ -99,25 +100,11 @@
         }
     };
 
-    // A convenience runnable to return all views to the pool
-    Runnable mReturnAllViewsToPoolRunnable = new Runnable() {
-        @Override
-        public void run() {
-            int childCount = getChildCount();
-            for (int i = childCount - 1; i >= 0; i--) {
-                TaskView tv = (TaskView) getChildAt(i);
-                mViewPool.returnViewToPool(tv);
-                // Also hide the view since we don't need it anymore
-                tv.setVisibility(View.INVISIBLE);
-            }
-        }
-    };
-
     public TaskStackView(Context context, TaskStack stack) {
         super(context);
+        // Set the stack first
+        setStack(stack);
         mConfig = RecentsConfiguration.getInstance();
-        mStack = stack;
-        mStack.setCallbacks(this);
         mViewPool = new ViewPool<TaskView, Task>(context, this);
         mInflater = LayoutInflater.from(context);
         mLayoutAlgorithm = new TaskStackViewLayoutAlgorithm(mConfig);
@@ -143,11 +130,62 @@
         mCb = cb;
     }
 
+    /** Sets the task stack */
+    void setStack(TaskStack stack) {
+        // Unset the old stack
+        if (mStack != null) {
+            mStack.setCallbacks(null);
+
+            // Return all existing views to the pool
+            reset();
+            // Layout again with the new stack
+            requestLayout();
+        }
+
+        // Set the new stack
+        mStack = stack;
+        if (mStack != null) {
+            mStack.setCallbacks(this);
+        }
+    }
+
     /** Sets the debug overlay */
     public void setDebugOverlay(DebugOverlayView overlay) {
         mDebugOverlay = overlay;
     }
 
+    /** Resets this TaskStackView for reuse. */
+    void reset() {
+        // Return all the views to the pool
+        int childCount = getChildCount();
+        for (int i = childCount - 1; i >= 0; i--) {
+            TaskView tv = (TaskView) getChildAt(i);
+            mViewPool.returnViewToPool(tv);
+        }
+
+        // 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();
+                }
+            }
+        }
+
+        // Reset the stack state
+        resetFocusedTask();
+        mStackViewsDirty = true;
+        mStackViewsClipDirty = true;
+        mAwaitingFirstLayout = true;
+        mPrevAccessibilityFocusedIndex = -1;
+        if (mUIDozeTrigger != null) {
+            mUIDozeTrigger.stopDozing();
+            mUIDozeTrigger.resetTrigger();
+        }
+    }
+
     /** Requests that the views be synchronized with the model */
     void requestSynchronizeStackViewsWithModel() {
         requestSynchronizeStackViewsWithModel(0);
@@ -510,6 +548,16 @@
         tv.dismissTask();
     }
 
+    /** Resets the focused task. */
+    void resetFocusedTask() {
+        if (mFocusedTaskIndex > -1) {
+            Task t = mStack.getTasks().get(mFocusedTaskIndex);
+            TaskView tv = getChildViewForTask(t);
+            tv.unsetFocusedTask();
+        }
+        mFocusedTaskIndex = -1;
+    }
+
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
@@ -543,6 +591,8 @@
 
     @Override
     public void computeScroll() {
+        if (mStack == null) return;
+
         mStackScroller.computeScroll();
         // Synchronize the views
         synchronizeStackViewsWithModel();
@@ -758,9 +808,6 @@
             TaskView tv = (TaskView) getChildAt(i);
             tv.startExitToHomeAnimation(ctx);
         }
-
-        // Add a runnable to the post animation ref counter to clear all the views
-        ctx.postAnimationTrigger.addLastDecrementRunnable(mReturnAllViewsToPoolRunnable);
     }
 
     /** Animates a task view in this stack as it launches. */
@@ -780,6 +827,12 @@
         }
     }
 
+    /** Final callback after Recents is finally hidden. */
+    void onRecentsHidden() {
+        reset();
+        setStack(null);
+    }
+
     public boolean isTransformedTouchPointInView(float x, float y, View child) {
         return isTransformedTouchPointInView(x, y, child, null);
     }
@@ -944,20 +997,23 @@
 
         // Reset the view properties
         tv.resetViewProperties();
+
+        // Reset the clip state of the task view
+        tv.setClipViewInStack(false);
     }
 
     @Override
     public void prepareViewToLeavePool(TaskView tv, Task task, boolean isNewView) {
+        // It is possible for a view to be returned to the view pool before it is laid out,
+        // which means that we will need to relayout the view when it is first used next.
+        boolean requiresRelayout = tv.getWidth() <= 0 && !isNewView;
+
         // Rebind the task and request that this task's data be filled into the TaskView
         tv.onTaskBound(task);
 
         // Load the task data
         RecentsTaskLoader.getInstance().loadTaskData(task);
 
-        // Sanity check, the task view should always be clipping against the stack at this point,
-        // but just in case, re-enable it here
-        tv.setClipViewInStack(true);
-
         // If the doze trigger has already fired, then update the state for this task view
         if (mUIDozeTrigger.hasTriggered()) {
             tv.setNoUserInteractionState();
@@ -985,13 +1041,17 @@
         // Add/attach the view to the hierarchy
         if (isNewView) {
             addView(tv, insertIndex);
-
-            // Set the callbacks and listeners for this new view
-            tv.setTouchEnabled(true);
-            tv.setCallbacks(this);
         } else {
             attachViewToParent(tv, insertIndex, tv.getLayoutParams());
+            if (requiresRelayout) {
+                tv.requestLayout();
+            }
         }
+
+        // Set the new state for this view, including the callbacks and view clipping
+        tv.setCallbacks(this);
+        tv.setTouchEnabled(true);
+        tv.setClipViewInStack(true);
     }
 
     @Override
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 7b4e10a..790130a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -112,6 +112,14 @@
         mCb = cb;
     }
 
+    /** Resets this TaskView for reuse. */
+    void reset() {
+        resetViewProperties();
+        resetNoUserInteractionState();
+        setClipViewInStack(false);
+        setCallbacks(null);
+    }
+
     /** Gets the task */
     Task getTask() {
         return mTask;
@@ -191,6 +199,7 @@
     /** Resets this view's properties */
     void resetViewProperties() {
         setDim(0);
+        setLayerType(View.LAYER_TYPE_NONE, null);
         TaskViewTransform.reset(this);
     }
 
@@ -448,6 +457,11 @@
         mHeaderView.setNoUserInteractionState();
     }
 
+    /** Resets the state tracking that the user has not interacted with the stack after a certain time. */
+    void resetNoUserInteractionState() {
+        mHeaderView.resetNoUserInteractionState();
+    }
+
     /** Dismisses this task. */
     void dismissTask() {
         // Animate out the view and call the callback
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index ba868f5..5de84bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -263,6 +263,11 @@
         }
     }
 
+    /** Resets the state tracking that the user has not interacted with the stack after a certain time. */
+    void resetNoUserInteractionState() {
+        mDismissButton.setVisibility(View.INVISIBLE);
+    }
+
     @Override
     protected int[] onCreateDrawableState(int extraSpace) {
 
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 af0094e..12b91af 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
@@ -75,4 +75,12 @@
         mViewCreator.prepareViewToLeavePool(v, prepareData, isNewView);
         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;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 7bbf9e2..725a1a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -59,7 +59,6 @@
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.view.Display;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
index 628aab8..7ae6764 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
@@ -17,10 +17,11 @@
 package com.android.systemui.statusbar;
 
 import android.app.StatusBarManager;
+import android.content.res.Resources;
 import android.graphics.RectF;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewConfiguration;
+import com.android.systemui.R;
 
 public class DelegateViewHelper {
     private View mDelegateView;
@@ -106,8 +107,8 @@
     public void setSourceView(View view) {
         mSourceView = view;
         if (mSourceView != null) {
-            mTriggerThreshhold =
-                    ViewConfiguration.get(mSourceView.getContext()).getScaledPagingTouchSlop();
+            Resources r = mSourceView.getContext().getResources();
+            mTriggerThreshhold = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index a4e5e74..f8332ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -22,6 +22,7 @@
 import android.graphics.drawable.Drawable;
 import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewStub;
 import android.view.accessibility.AccessibilityEvent;
@@ -68,6 +69,7 @@
     private NotificationGuts mGuts;
 
     private StatusBarNotification mStatusBarNotification;
+    private boolean mIsHeadsUp;
 
     public void setIconAnimationRunning(boolean running) {
         setIconAnimationRunning(running, mPublicLayout);
@@ -122,6 +124,10 @@
         return mStatusBarNotification;
     }
 
+    public void setHeadsUp(boolean isHeadsUp) {
+        mIsHeadsUp = isHeadsUp;
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
@@ -147,14 +153,16 @@
         mShowingPublicInitialized = false;
         mIsSystemExpanded = false;
         mExpansionDisabled = false;
-        mPublicLayout.reset();
-        mPrivateLayout.reset();
+        mPublicLayout.reset(mIsHeadsUp);
+        mPrivateLayout.reset(mIsHeadsUp);
         resetHeight();
         logExpansionEvent(false, wasExpanded);
     }
 
     public void resetHeight() {
-        super.resetHeight();
+        if (mIsHeadsUp) {
+            resetActualHeight();
+        }
         mMaxExpandHeight = 0;
         mWasReset = true;
         onHeightReset();
@@ -162,6 +170,11 @@
     }
 
     @Override
+    protected boolean filterMotionEvent(MotionEvent event) {
+        return mIsHeadsUp || super.filterMotionEvent(event);
+    }
+
+    @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
         mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index edfbe86..bf1e78e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -103,9 +103,13 @@
         }
     }
 
-    protected void resetHeight() {
+    /**
+     * Resets the height of the view on the next layout pass
+     */
+    protected void resetActualHeight() {
         mActualHeight = 0;
         mActualHeightInitialized = false;
+        requestLayout();
     }
 
     protected int getInitialHeight() {
@@ -120,7 +124,7 @@
         return false;
     }
 
-    private boolean filterMotionEvent(MotionEvent event) {
+    protected boolean filterMotionEvent(MotionEvent event) {
         return event.getActionMasked() != MotionEvent.ACTION_DOWN
                 || event.getY() > mClipTopAmount && event.getY() < mActualHeight;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 992aa9f..58067c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -146,8 +146,8 @@
         try {
             long chargingTimeRemaining = mBatteryInfo.computeChargeTimeRemaining();
             if (chargingTimeRemaining > 0) {
-                String chargingTimeFormatted =
-                        Formatter.formatShortElapsedTime(mContext, chargingTimeRemaining);
+                String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
+                        mContext, chargingTimeRemaining);
                 return mContext.getResources().getString(
                         R.string.keyguard_indication_charging_time, chargingTimeFormatted);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 9b11f9b..99214a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -74,7 +74,7 @@
     public NotificationContentView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
-        reset();
+        reset(true);
     }
 
     @Override
@@ -89,7 +89,7 @@
         updateVisibility();
     }
 
-    public void reset() {
+    public void reset(boolean resetActualHeight) {
         if (mContractedChild != null) {
             mContractedChild.animate().cancel();
         }
@@ -100,8 +100,10 @@
         mContractedChild = null;
         mExpandedChild = null;
         mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
-        mActualHeight = mSmallHeight;
         mContractedVisible = true;
+        if (resetActualHeight) {
+            mActualHeight = mSmallHeight;
+        }
     }
 
     public View getContractedChild() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 9bb52e7..1e4dfb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -21,6 +21,7 @@
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
+import android.app.ActivityManagerNative;
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -30,6 +31,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Message;
+import android.os.RemoteException;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Display;
@@ -43,6 +45,7 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+
 import com.android.systemui.R;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.DelegateViewHelper;
@@ -332,7 +335,7 @@
         mDisabledFlags = disabledFlags;
 
         final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
-        final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
+        boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
         final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
                 && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
         final boolean disableSearch = ((disabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0);
@@ -357,6 +360,11 @@
                 }
             }
         }
+        if (inLockTask() && disableRecent && !disableHome) {
+            // Don't hide recents when in lock task, it is used for exiting.
+            // Unless home is hidden, then in DPM locked mode and no exit available.
+            disableRecent = false;
+        }
 
         getBackButton()   .setVisibility(disableBack       ? View.INVISIBLE : View.VISIBLE);
         getHomeButton()   .setVisibility(disableHome       ? View.INVISIBLE : View.VISIBLE);
@@ -365,6 +373,14 @@
         mBarTransitions.applyBackButtonQuiescentAlpha(mBarTransitions.getMode(), true /*animate*/);
     }
 
+    private boolean inLockTask() {
+        try {
+            return ActivityManagerNative.getDefault().isInLockTaskMode();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
     private void setVisibleOrGone(View view, boolean visible) {
         if (view != null) {
             view.setVisibility(visible ? VISIBLE : GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
index c253e19..fdfcdfb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
@@ -17,9 +17,11 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
+import com.android.systemui.R;
 import com.android.systemui.statusbar.BaseStatusBar;
 
 public class NavigationBarViewTaskSwitchHelper extends GestureDetector.SimpleOnGestureListener {
@@ -36,7 +38,8 @@
 
     public NavigationBarViewTaskSwitchHelper(Context context) {
         ViewConfiguration configuration = ViewConfiguration.get(context);
-        mScrollTouchSlop = 4 * configuration.getScaledTouchSlop();
+        Resources r = context.getResources();
+        mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
         mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
         mTaskSwitcherDetector = new GestureDetector(context, this);
     }
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 84ebcdfb..5928845 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3968,6 +3968,8 @@
                 // long-pressed 'together'
                 if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) {
                     activityManager.stopLockTaskModeOnCurrent();
+                    // When exiting refresh disabled flags.
+                    mNavigationBarView.setDisabledFlags(mDisabled, true);
                 } else if ((v.getId() == R.id.back)
                         && !mNavigationBarView.getRecentsButton().isPressed()) {
                     // If we aren't pressing recents right now then they presses
@@ -3983,6 +3985,8 @@
                     // When in accessibility mode a long press that is recents (not back)
                     // should stop lock task.
                     activityManager.stopLockTaskModeOnCurrent();
+                    // When exiting refresh disabled flags.
+                    mNavigationBarView.setDisabledFlags(mDisabled, true);
                 }
             }
             if (sendBackLongPress) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index 84216a4..11ff272 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -54,7 +54,6 @@
     private EdgeSwipeHelper mEdgeSwipeHelper;
 
     private PhoneStatusBar mBar;
-    private ExpandHelper mExpandHelper;
 
     private long mStartTouchTime;
     private ViewGroup mContentHolder;
@@ -102,6 +101,7 @@
         if (mHeadsUp != null) {
             mHeadsUp.row.setSystemExpanded(true);
             mHeadsUp.row.setSensitive(false);
+            mHeadsUp.row.setHeadsUp(true);
             mHeadsUp.row.setHideSensitive(
                     false, false /* animated */, 0 /* delay */, 0 /* duration */);
             if (mContentHolder == null) {
@@ -205,7 +205,6 @@
 
         int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
         int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_max_height);
-        mExpandHelper = new ExpandHelper(getContext(), this, minHeight, maxHeight);
 
         mContentHolder = (ViewGroup) findViewById(R.id.content_holder);
         mContentHolder.setOutlineProvider(CONTENT_HOLDER_OUTLINE_PROVIDER);
@@ -226,7 +225,6 @@
         }
         return mEdgeSwipeHelper.onInterceptTouchEvent(ev)
                 || mSwipeHelper.onInterceptTouchEvent(ev)
-                || mExpandHelper.onInterceptTouchEvent(ev)
                 || super.onInterceptTouchEvent(ev);
     }
 
@@ -254,7 +252,6 @@
         mBar.resetHeadsUpDecayTimer();
         return mEdgeSwipeHelper.onTouchEvent(ev)
                 || mSwipeHelper.onTouchEvent(ev)
-                || mExpandHelper.onTouchEvent(ev)
                 || super.onTouchEvent(ev);
     }
 
@@ -399,15 +396,12 @@
                     final float dY = ev.getY() - mFirstY;
                     final float daX = Math.abs(ev.getX() - mFirstX);
                     final float daY = Math.abs(dY);
-                    if (!mConsuming && (4f * daX) < daY && daY > mTouchSlop) {
+                    if (!mConsuming && daX < daY && daY > mTouchSlop) {
+                        releaseAndClose();
                         if (dY > 0) {
                             if (DEBUG_EDGE_SWIPE) Log.d(TAG, "found an open");
                             mBar.animateExpandNotificationsPanel();
                         }
-                        if (dY < 0) {
-                            if (DEBUG_EDGE_SWIPE) Log.d(TAG, "found a close");
-                            mBar.onHeadsUpDismissed();
-                        }
                         mConsuming = true;
                     }
                     break;
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index bb91a14..738917f 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -130,7 +130,16 @@
 
     @Override
     public boolean setActiveScorer(String packageName) {
-        mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+        // TODO: For now, since SCORE_NETWORKS requires an app to be privileged, we allow such apps
+        // to directly set the scorer app rather than having to use the consent dialog. The
+        // assumption is that anyone bundling a scorer app with the system is trusted by the OEM to
+        // do the right thing and not enable this feature without explaining it to the user.
+        // In the future, should this API be opened to 3p apps, we will need to lock this down and
+        // figure out another way to streamline the UX.
+
+        // mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+        mContext.enforceCallingOrSelfPermission(permission.SCORE_NETWORKS, TAG);
+
         return setScorerInternal(packageName);
     }
 
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index fcc5339..ba93213 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -596,7 +596,7 @@
                                 + " phoneId=" + phoneId + " state=" + state);
                     }
                     if (((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) &&
-                            subIdMatch(r.subId, subId)) {
+                            idMatch(r.subId, subId, phoneId)) {
                         try {
                             if (DBG) {
                                 log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
@@ -641,7 +641,7 @@
                                 + " phoneId=" + phoneId + " ss=" + signalStrength);
                     }
                     if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) &&
-                            subIdMatch(r.subId, subId)) {
+                            idMatch(r.subId, subId, phoneId)) {
                         try {
                             if (DBG) {
                                 log("notifySignalStrengthForSubscriber: callback.onSsS r=" + r
@@ -654,7 +654,7 @@
                         }
                     }
                     if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) &&
-                            subIdMatch(r.subId, subId)){
+                            idMatch(r.subId, subId, phoneId)){
                         try {
                             int gsmSignalStrength = signalStrength.getGsmSignalStrength();
                             int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
@@ -696,7 +696,7 @@
                 mCellInfo.set(phoneId, cellInfo);
                 for (Record r : mRecords) {
                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
-                            subIdMatch(r.subId, subId)) {
+                            idMatch(r.subId, subId, phoneId)) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyCellInfo: mCellInfo=" + cellInfo + " r=" + r);
@@ -751,7 +751,7 @@
                 mMessageWaiting[phoneId] = mwi;
                 for (Record r : mRecords) {
                     if (((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) &&
-                            subIdMatch(r.subId, subId)) {
+                            idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onMessageWaitingIndicatorChanged(mwi);
                         } catch (RemoteException ex) {
@@ -782,7 +782,7 @@
                 mCallForwarding[phoneId] = cfi;
                 for (Record r : mRecords) {
                     if (((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) &&
-                            subIdMatch(r.subId, subId)) {
+                            idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onCallForwardingIndicatorChanged(cfi);
                         } catch (RemoteException ex) {
@@ -879,7 +879,7 @@
                 }
                 for (Record r : mRecords) {
                     if (((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) &&
-                            subIdMatch(r.subId, subId)) {
+                            idMatch(r.subId, subId, phoneId)) {
                         try {
                             log("Notify data connection state changed on sub: " +
                                     subId);
@@ -965,7 +965,7 @@
                 mCellLocation[phoneId] = cellLocation;
                 for (Record r : mRecords) {
                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
-                            subIdMatch(r.subId, subId)) {
+                            idMatch(r.subId, subId, phoneId)) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyCellLocation: cellLocation=" + cellLocation
@@ -1386,7 +1386,7 @@
 
         @Override
         public String toString() {
-            return mS + " " + mTime.toString() + " " + mSubId + " " + mPhoneId + " " + mState;
+            return mS + " Time " + mTime.toString() + " mSubId " + mSubId + " mPhoneId " + mPhoneId + "  mState " + mState;
         }
     }
 
@@ -1429,8 +1429,12 @@
         }
     }
 
-    boolean subIdMatch(int rSubId, int subId) {
+    boolean idMatch(int rSubId, int subId, int phoneId) {
         if(rSubId == SubscriptionManager.DEFAULT_SUB_ID) {
+            if(subId < 0) {
+                // Invalid case, we need compare phoneId with default one.
+                return (mDefaultPhoneId == phoneId);
+            }
             return (subId == mDefaultSubId);
         } else {
             return (rSubId == subId);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index d703989..53740fe 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -29,11 +29,16 @@
     static final int ERROR_SOURCE = 1;
     static final int ERROR_DESTINATION = 2;
     static final int ERROR_PARAMETER = 3;
+    static final int ERROR_PARAMETER_SHORT = 4;
 
     private final HdmiControlService mService;
 
     interface ParameterValidator {
-        boolean isValid(byte[] params);
+        /**
+         * @return errorCode errorCode can be {@link #OK}, {@link #ERROR_PARAMETER} or
+         *         {@link #ERROR_PARAMETER_SHORT}.
+         */
+        int isValid(byte[] params);
     }
 
     // Only the direct addressing is allowed.
@@ -74,7 +79,7 @@
         addValidationInfo(Constants.MESSAGE_SET_STREAM_PATH,
                 physicalAddressValidator, DEST_BROADCAST);
         addValidationInfo(Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST,
-                physicalAddressValidator, DEST_DIRECT);
+                new SystemAudioModeRequestValidator(), DEST_DIRECT);
 
         // Messages have no parameter.
         FixedLengthValidator noneValidator = new FixedLengthValidator(0);
@@ -213,9 +218,10 @@
         }
 
         // Check the parameter type.
-        if (!info.parameterValidator.isValid(message.getParams())) {
+        int errorCode = info.parameterValidator.isValid(message.getParams());
+        if (errorCode != OK) {
             HdmiLogger.warning("Unexpected parameters: " + message);
-            return ERROR_PARAMETER;
+            return errorCode;
         }
         return OK;
     }
@@ -228,8 +234,10 @@
         }
 
         @Override
-        public boolean isValid(byte[] params) {
-            return params.length == mLength;
+        public int isValid(byte[] params) {
+            // If the length is longer than expected, we assume it's OK since the parameter can be
+            // extended in the future version.
+            return params.length < mLength ? ERROR_PARAMETER_SHORT : OK;
         }
     }
 
@@ -243,8 +251,8 @@
         }
 
         @Override
-        public boolean isValid(byte[] params) {
-            return params.length >= mMinLength && params.length <= mMaxLength;
+        public int isValid(byte[] params) {
+            return params.length < mMinLength ? ERROR_PARAMETER_SHORT : OK;
         }
     }
 
@@ -270,8 +278,7 @@
      * Check if the given type is valid. A valid type is one of the actual logical device types
      * defined in the standard ({@link HdmiDeviceInfo#DEVICE_TV},
      * {@link HdmiDeviceInfo#DEVICE_PLAYBACK}, {@link HdmiDeviceInfo#DEVICE_TUNER},
-     * {@link HdmiDeviceInfo#DEVICE_RECORDER}, and
-     * {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM}).
+     * {@link HdmiDeviceInfo#DEVICE_RECORDER}, and {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM}).
      *
      * @param type device type
      * @return true if the given type is valid
@@ -282,33 +289,49 @@
                 && type != HdmiDeviceInfo.DEVICE_RESERVED;
     }
 
+    private static int toErrorCode(boolean success) {
+        return success ? OK : ERROR_PARAMETER;
+    }
+
     private class PhysicalAddressValidator implements ParameterValidator {
         @Override
-        public boolean isValid(byte[] params) {
-            if (params.length != 2) {
-                return false;
+        public int isValid(byte[] params) {
+            if (params.length < 2) {
+                return ERROR_PARAMETER_SHORT;
             }
-            return isValidPhysicalAddress(params, 0);
+            return toErrorCode(isValidPhysicalAddress(params, 0));
+        }
+    }
+
+    private class SystemAudioModeRequestValidator extends PhysicalAddressValidator {
+        @Override
+        public int isValid(byte[] params) {
+            // TV can send <System Audio Mode Request> with no parameters to terminate system audio.
+            if (params.length == 0) {
+                return OK;
+            }
+            return super.isValid(params);
         }
     }
 
     private class ReportPhysicalAddressValidator implements ParameterValidator {
         @Override
-        public boolean isValid(byte[] params) {
-            if (params.length != 3) {
-                return false;
+        public int isValid(byte[] params) {
+            if (params.length < 3) {
+                return ERROR_PARAMETER_SHORT;
             }
-            return isValidPhysicalAddress(params, 0) && isValidType(params[2]);
+            return toErrorCode(isValidPhysicalAddress(params, 0) && isValidType(params[2]));
         }
     }
 
     private class RoutingChangeValidator implements ParameterValidator {
         @Override
-        public boolean isValid(byte[] params) {
-            if (params.length != 4) {
-                return false;
+        public int isValid(byte[] params) {
+            if (params.length < 4) {
+                return ERROR_PARAMETER_SHORT;
             }
-            return isValidPhysicalAddress(params, 0) && isValidPhysicalAddress(params, 2);
+            return toErrorCode(
+                    isValidPhysicalAddress(params, 0) && isValidPhysicalAddress(params, 2));
         }
     }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index d8d513e..907a49a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -719,7 +719,8 @@
         assertRunOnServiceThread();
         int errorCode = mMessageValidator.isValid(message);
         if (errorCode != HdmiCecMessageValidator.OK) {
-            // We'll not response on the messages with the invalid source or destination.
+            // We'll not response on the messages with the invalid source or destination
+            // or with parameter length shorter than specified in the standard.
             if (errorCode == HdmiCecMessageValidator.ERROR_PARAMETER) {
                 maySendFeatureAbortCommand(message, Constants.ABORT_INVALID_OPERAND);
             }
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java
index 203d990..6d18531 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java
@@ -141,4 +141,11 @@
         return "CrossProfileIntentFilter{0x" + Integer.toHexString(System.identityHashCode(this))
                 + " " + Integer.toString(mTargetUserId) + "}";
     }
+
+    boolean equalsIgnoreFilter(CrossProfileIntentFilter other) {
+        return mTargetUserId == other.mTargetUserId
+                && mOwnerUserId == other.mOwnerUserId
+                && mOwnerPackage.equals(other.mOwnerPackage)
+                && mFlags == other.mFlags;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f9a85df..c75fb9a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11844,9 +11844,21 @@
             return;
         }
         synchronized (mPackages) {
-            CrossProfileIntentFilter filter = new CrossProfileIntentFilter(intentFilter,
+            CrossProfileIntentFilter newFilter = new CrossProfileIntentFilter(intentFilter,
                     ownerPackage, UserHandle.getUserId(callingUid), targetUserId, flags);
-            mSettings.editCrossProfileIntentResolverLPw(sourceUserId).addFilter(filter);
+            CrossProfileIntentResolver resolver =
+                    mSettings.editCrossProfileIntentResolverLPw(sourceUserId);
+            ArrayList<CrossProfileIntentFilter> existing = resolver.findFilters(intentFilter);
+            // We have all those whose filter is equal. Now checking if the rest is equal as well.
+            if (existing != null) {
+                int size = existing.size();
+                for (int i = 0; i < size; i++) {
+                    if (newFilter.equalsIgnoreFilter(existing.get(i))) {
+                        return;
+                    }
+                }
+            }
+            resolver.addFilter(newFilter);
             scheduleWritePackageRestrictionsLocked(sourceUserId);
         }
     }
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index b1c918d..b2bcf75 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -27,11 +27,11 @@
 import android.content.ServiceConnection;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.PatternMatcher;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -218,7 +218,7 @@
         }
 
         @Override
-        public void onSetTrustAgentFeaturesEnabledCompleted(boolean result, IBinder token) {
+        public void onConfigureCompleted(boolean result, IBinder token) {
             if (DEBUG) Slog.v(TAG, "onSetTrustAgentFeaturesEnabledCompleted(result=" + result);
             mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_COMPLETED,
                     result ? 1 : 0, 0, token).sendToTarget();
@@ -318,23 +318,19 @@
                 DevicePolicyManager dpm =
                     (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
 
-                if ((dpm.getKeyguardDisabledFeatures(null)
+                if ((dpm.getKeyguardDisabledFeatures(null, mUserId)
                         & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) {
-                    List<String> features = dpm.getTrustAgentFeaturesEnabled(null, mName);
+                    List<PersistableBundle> config = dpm.getTrustAgentConfiguration(
+                            null, mName, mUserId);
                     trustDisabled = true;
-                    if (DEBUG) Slog.v(TAG, "Detected trust agents disabled. Features = "
-                            + features);
-                    if (features != null && features.size() > 0) {
-                        Bundle bundle = new Bundle();
-                        bundle.putStringArrayList(TrustAgentService.KEY_FEATURES,
-                                (ArrayList<String>)features);
+                    if (DEBUG) Slog.v(TAG, "Detected trust agents disabled. Config = " + config);
+                    if (config != null && config.size() > 0) {
                         if (DEBUG) {
                             Slog.v(TAG, "TrustAgent " + mName.flattenToShortString()
-                                    + " disabled until it acknowledges "+ features);
+                                    + " disabled until it acknowledges "+ config);
                         }
                         mSetTrustAgentFeaturesToken = new Binder();
-                        mTrustAgentService.setTrustAgentFeaturesEnabled(bundle,
-                                mSetTrustAgentFeaturesToken);
+                        mTrustAgentService.onConfigure(config, mSetTrustAgentFeaturesToken);
                     }
                 }
                 final long maxTimeToLock = dpm.getMaximumTimeToLock(null);
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 4437e12..fe5cb33 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -48,6 +48,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -228,10 +229,10 @@
 
                 if (!enabledAgents.contains(name)) continue;
                 if (disableTrustAgents) {
-                    List<String> features =
-                            dpm.getTrustAgentFeaturesEnabled(null /* admin */, name);
+                    List<PersistableBundle> config =
+                            dpm.getTrustAgentConfiguration(null /* admin */, name, userInfo.id);
                     // Disable agent if no features are enabled.
-                    if (features == null || features.isEmpty()) continue;
+                    if (config == null || config.isEmpty()) continue;
                 }
 
                 AgentInfo agentInfo = new AgentInfo();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 308fcd8..2c6a222 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -60,6 +60,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IPowerManager;
+import android.os.PersistableBundle;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RecoverySystem;
@@ -96,6 +97,7 @@
 import com.android.org.conscrypt.TrustedCertificateStore;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
 
 import org.xmlpull.v1.XmlPullParser;
 
@@ -322,7 +324,7 @@
                 = "permitted-accessiblity-services";
         private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
         private static final String TAG_MANAGE_TRUST_AGENT_FEATURES = "manage-trust-agent-features";
-        private static final String TAG_TRUST_AGENT_FEATURE = "feature";
+        private static final String TAG_TRUST_AGENT_COMPONENT_OPTIONS = "trust-agent-component-options";
         private static final String TAG_TRUST_AGENT_COMPONENT = "component";
         private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date";
         private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout";
@@ -389,6 +391,7 @@
         long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
 
         static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
+
         int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
 
         boolean encryptionRequested = false;
@@ -397,6 +400,13 @@
         boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
         boolean requireAutoTime = false; // Can only be set by a device owner.
 
+        static class TrustAgentInfo {
+            public PersistableBundle options;
+            TrustAgentInfo(PersistableBundle bundle) {
+                options = bundle;
+            }
+        }
+
         Set<String> accountTypesWithManagementDisabled = new HashSet<String>();
 
         // The list of permitted accessibility services package namesas set by a profile
@@ -413,7 +423,8 @@
         boolean specifiesGlobalProxy = false;
         String globalProxySpec = null;
         String globalProxyExclusionList = null;
-        HashMap<String, List<String>> trustAgentFeatures = new HashMap<String, List<String>>();
+
+        HashMap<String, TrustAgentInfo> trustAgentInfos = new HashMap<String, TrustAgentInfo>();
 
         List<String> crossProfileWidgetProviders;
 
@@ -551,16 +562,21 @@
                 }
                 out.endTag(null,  TAG_DISABLE_ACCOUNT_MANAGEMENT);
             }
-            if (!trustAgentFeatures.isEmpty()) {
-                Set<Entry<String, List<String>>> set = trustAgentFeatures.entrySet();
+            if (!trustAgentInfos.isEmpty()) {
+                Set<Entry<String, TrustAgentInfo>> set = trustAgentInfos.entrySet();
                 out.startTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
-                for (Entry<String, List<String>> component : set) {
+                for (Entry<String, TrustAgentInfo> entry : set) {
+                    TrustAgentInfo trustAgentInfo = entry.getValue();
                     out.startTag(null, TAG_TRUST_AGENT_COMPONENT);
-                    out.attribute(null, ATTR_VALUE, component.getKey());
-                    for (String feature : component.getValue()) {
-                        out.startTag(null, TAG_TRUST_AGENT_FEATURE);
-                        out.attribute(null, ATTR_VALUE, feature);
-                        out.endTag(null, TAG_TRUST_AGENT_FEATURE);
+                    out.attribute(null, ATTR_VALUE, entry.getKey());
+                    if (trustAgentInfo.options != null) {
+                        out.startTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
+                        try {
+                            trustAgentInfo.options.saveToXml(out);
+                        } catch (XmlPullParserException e) {
+                            Log.e(LOG_TAG, "Failed to save TrustAgent options", e);
+                        }
+                        out.endTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
                     }
                     out.endTag(null, TAG_TRUST_AGENT_COMPONENT);
                 }
@@ -679,7 +695,7 @@
                 } else if (TAG_DISABLE_ACCOUNT_MANAGEMENT.equals(tag)) {
                     accountTypesWithManagementDisabled = readDisableAccountInfo(parser, tag);
                 } else if (TAG_MANAGE_TRUST_AGENT_FEATURES.equals(tag)) {
-                    trustAgentFeatures = getAllTrustAgentFeatures(parser, tag);
+                    trustAgentInfos = getAllTrustAgentInfos(parser, tag);
                 } else if (TAG_CROSS_PROFILE_WIDGET_PROVIDERS.equals(tag)) {
                     crossProfileWidgetProviders = getCrossProfileWidgetProviders(parser, tag);
                 } else if (TAG_PERMITTED_ACCESSIBILITY_SERVICES.equals(tag)) {
@@ -738,11 +754,11 @@
             return result;
         }
 
-        private HashMap<String, List<String>> getAllTrustAgentFeatures(XmlPullParser parser,
-                String tag) throws XmlPullParserException, IOException {
+        private HashMap<String, TrustAgentInfo> getAllTrustAgentInfos(
+                XmlPullParser parser, String tag) throws XmlPullParserException, IOException {
             int outerDepthDAM = parser.getDepth();
             int typeDAM;
-            HashMap<String, List<String>> result = new HashMap<String, List<String>>();
+            HashMap<String, TrustAgentInfo> result = new HashMap<String, TrustAgentInfo>();
             while ((typeDAM=parser.next()) != END_DOCUMENT
                     && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
                 if (typeDAM == END_TAG || typeDAM == TEXT) {
@@ -751,7 +767,8 @@
                 String tagDAM = parser.getName();
                 if (TAG_TRUST_AGENT_COMPONENT.equals(tagDAM)) {
                     final String component = parser.getAttributeValue(null, ATTR_VALUE);
-                    result.put(component, getTrustAgentFeatures(parser, tag));
+                    final TrustAgentInfo trustAgentInfo = getTrustAgentInfo(parser, tag);
+                    result.put(component, trustAgentInfo);
                 } else {
                     Slog.w(LOG_TAG, "Unknown tag under " + tag +  ": " + tagDAM);
                 }
@@ -759,20 +776,21 @@
             return result;
         }
 
-        private List<String> getTrustAgentFeatures(XmlPullParser parser, String tag)
+        private TrustAgentInfo getTrustAgentInfo(XmlPullParser parser, String tag)
                 throws XmlPullParserException, IOException  {
             int outerDepthDAM = parser.getDepth();
             int typeDAM;
-            ArrayList<String> result = new ArrayList<String>();
+            TrustAgentInfo result = new TrustAgentInfo(null);
             while ((typeDAM=parser.next()) != END_DOCUMENT
                     && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
                 if (typeDAM == END_TAG || typeDAM == TEXT) {
                     continue;
                 }
                 String tagDAM = parser.getName();
-                if (TAG_TRUST_AGENT_FEATURE.equals(tagDAM)) {
-                    final String feature = parser.getAttributeValue(null, ATTR_VALUE);
-                    result.add(feature);
+                if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
+                    PersistableBundle bundle = new PersistableBundle();
+                    bundle.restoreFromXml(parser);
+                    result.options = bundle;
                 } else {
                     Slog.w(LOG_TAG, "Unknown tag under " + tag +  ": " + tagDAM);
                 }
@@ -1174,7 +1192,7 @@
             int userHandle) {
         List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
         for (UserInfo ui : profiles) {
-            int id = ui.getUserHandle().getIdentifier();
+            int id = ui.id;
             sendAdminCommandLocked(action, reqPolicy, id);
         }
     }
@@ -1591,7 +1609,7 @@
 
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo ui : profiles) {
-                int profileUserHandle = ui.getUserHandle().getIdentifier();
+                int profileUserHandle = ui.id;
                 final DevicePolicyData policy = getUserData(profileUserHandle);
                 final int count = policy.mAdminList.size();
                 if (count > 0) {
@@ -1878,7 +1896,7 @@
             // Return strictest policy for this user and profiles that are visible from this user.
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i=0; i<N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -1925,7 +1943,7 @@
             // Return strictest policy for this user and profiles that are visible from this user.
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i=0; i<N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -1972,7 +1990,7 @@
             // Return strictest policy for this user and profiles that are visible from this user.
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i = 0; i < N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2033,7 +2051,7 @@
 
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i = 0; i < N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2131,7 +2149,7 @@
 
         List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
         for (UserInfo userInfo : profiles) {
-            DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+            DevicePolicyData policy = getUserData(userInfo.id);
             final int N = policy.mAdminList.size();
             for (int i = 0; i < N; i++) {
                 ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2188,7 +2206,7 @@
             // Return strictest policy for this user and profiles that are visible from this user.
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i=0; i<N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2232,7 +2250,7 @@
             // Return strictest policy for this user and profiles that are visible from this user.
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i=0; i<N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2279,7 +2297,7 @@
             // Return strictest policy for this user and profiles that are visible from this user.
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i=0; i<N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2326,7 +2344,7 @@
             // Return strictest policy for this user and profiles that are visible from this user.
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i = 0; i < N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2373,7 +2391,7 @@
             // Return strictest policy for this user and profiles that are visible from this user.
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i=0; i<N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2420,7 +2438,7 @@
             // Return strictest policy for this user and profiles that are visible from this user.
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i=0; i<N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -2526,7 +2544,7 @@
         int count = 0;
         ActiveAdmin strictestAdmin = null;
         for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
-            DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+            DevicePolicyData policy = getUserData(userInfo.id);
             for (ActiveAdmin admin : policy.mAdminList) {
                 if (admin.maximumFailedPasswordsForWipe ==
                         ActiveAdmin.DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
@@ -2738,7 +2756,7 @@
             // Return strictest policy for this user and profiles that are visible from this user.
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
                 for (int i=0; i<N; i++) {
                     ActiveAdmin admin = policy.mAdminList.get(i);
@@ -3055,7 +3073,7 @@
     private void updatePasswordExpirationsLocked(int userHandle) {
             List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             for (UserInfo userInfo : profiles) {
-                int profileId = userInfo.getUserHandle().getIdentifier();
+                int profileId = userInfo.id;
                 DevicePolicyData policy = getUserData(profileId);
                 final int N = policy.mAdminList.size();
                 if (N > 0) {
@@ -4106,13 +4124,13 @@
         }
     }
 
-    public void setTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent,
-            List<String>features, int userHandle) {
+    public void setTrustAgentConfiguration(ComponentName admin, ComponentName agent,
+            PersistableBundle args, int userHandle) {
         if (!mHasFeature) {
             return;
         }
         enforceCrossUserPermission(userHandle);
-        enforceNotManagedProfile(userHandle, "manage trust agent features");
+        enforceNotManagedProfile(userHandle, "set trust agent configuration");
         synchronized (this) {
             if (admin == null) {
                 throw new NullPointerException("admin is null");
@@ -4122,57 +4140,68 @@
             }
             ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
                     DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
-            ap.trustAgentFeatures.put(agent.flattenToString(), features);
+            ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
             saveSettingsLocked(userHandle);
             syncDeviceCapabilitiesLocked(getUserData(userHandle));
         }
     }
 
-    public List<String> getTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent,
-            int userHandle) {
+    public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
+            ComponentName agent, int userHandle) {
         if (!mHasFeature) {
             return null;
         }
         enforceCrossUserPermission(userHandle);
+        if (agent == null) {
+            throw new NullPointerException("agent is null");
+        }
+
         synchronized (this) {
-            if (agent == null) {
-                throw new NullPointerException("agent is null");
-            }
             final String componentName = agent.flattenToString();
             if (admin != null) {
                 final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle);
-                return (ap != null) ? ap.trustAgentFeatures.get(componentName) : null;
+                if (ap == null) return null;
+                TrustAgentInfo trustAgentInfo = ap.trustAgentInfos.get(componentName);
+                if (trustAgentInfo == null || trustAgentInfo.options == null) return null;
+                List<PersistableBundle> result = new ArrayList<PersistableBundle>();
+                result.add(trustAgentInfo.options);
+                return result;
             }
 
             // Return strictest policy for this user and profiles that are visible from this user.
-            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
-            List<String> result = null;
+            final List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            List<PersistableBundle> result = null;
+
+            // Search through all admins that use KEYGUARD_DISABLE_TRUST_AGENTS and keep track
+            // of the options. If any admin doesn't have options, discard options for the rest
+            // and return null.
+            boolean allAdminsHaveOptions = true;
             for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                DevicePolicyData policy = getUserData(userInfo.id);
                 final int N = policy.mAdminList.size();
-                for (int i=0; i<N; i++) {
-                    ActiveAdmin ap = policy.mAdminList.get(i);
-                    // Compute the intersection of all features for active admins that disable
-                    // trust agents:
-                    if ((ap.disabledKeyguardFeatures
-                            & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) {
-                        final List<String> features = ap.trustAgentFeatures.get(componentName);
-                        if (result == null) {
-                            if (features == null || features.size() == 0) {
-                                result = new ArrayList<String>();
-                                Slog.w(LOG_TAG, "admin " + ap.info.getPackageName()
-                                    + " has null trust agent feature set; all will be disabled");
-                            } else {
-                                result = new ArrayList<String>(features.size());
-                                result.addAll(features);
+                for (int i=0; i < N; i++) {
+                    final ActiveAdmin active = policy.mAdminList.get(i);
+                    final boolean disablesTrust = (active.disabledKeyguardFeatures
+                            & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
+                    final TrustAgentInfo info = active.trustAgentInfos.get(componentName);
+                    if (info != null && info.options != null && !info.options.isEmpty()) {
+                        if (disablesTrust) {
+                            if (result == null) {
+                                result = new ArrayList<PersistableBundle>();
                             }
+                            result.add(info.options);
                         } else {
-                            result.retainAll(features);
+                            Log.w(LOG_TAG, "Ignoring admin " + active.info
+                                    + " because it has trust options but doesn't declare "
+                                    + "KEYGUARD_DISABLE_TRUST_AGENTS");
                         }
+                    } else if (disablesTrust) {
+                        allAdminsHaveOptions = false;
+                        break;
                     }
                 }
             }
-            return result;
+            return allAdminsHaveOptions ? result : null;
         }
     }
 
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 003d5cd..6480a8a 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -207,6 +207,13 @@
     }
 
     /**
+     * @return The {@link DisconnectCause} for this connection.
+     */
+    public final DisconnectCause getDisconnectCause() {
+        return mDisconnectCause;
+    }
+
+    /**
      * Sets the capabilities of a conference. See {@link PhoneCapabilities} for valid values.
      *
      * @param capabilities A bitmask of the {@code PhoneCapabilities} of the conference call.
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 206046d..73bcd0c 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -58,6 +58,11 @@
     public static final int RESTRICTED = 8;
     /** Disconnected for reason not described by other disconnect codes. */
     public static final int OTHER = 9;
+    /**
+     * Disconnected because the connection manager did not support the call. The call will be tried
+     * again without a connection manager. See {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}.
+     */
+    public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10;
 
     private int mDisconnectCode;
     private CharSequence mDisconnectLabel;
@@ -220,7 +225,10 @@
     @Override
     public String toString() {
         String code = "";
-        switch (getCode()) {
+        switch (mDisconnectCode) {
+            case UNKNOWN:
+                code = "UNKNOWN";
+                break;
             case ERROR:
                 code = "ERROR";
                 break;
@@ -230,6 +238,9 @@
             case REMOTE:
                 code = "REMOTE";
                 break;
+            case CANCELED:
+                code = "CANCELED";
+                break;
             case MISSED:
                 code = "MISSED";
                 break;
@@ -245,9 +256,12 @@
             case OTHER:
                 code = "OTHER";
                 break;
-            case UNKNOWN:
+            case CONNECTION_MANAGER_NOT_SUPPORTED:
+                code = "CONNECTION_MANAGER_NOT_SUPPORTED";
+                break;
             default:
-                code = "UNKNOWN";
+                code = "invalid code: " + mDisconnectCode;
+                break;
         }
         String label = mDisconnectLabel == null ? "" : mDisconnectLabel.toString();
         String description = mDisconnectDescription == null
diff --git a/telephony/java/android/telephony/SubInfoRecord.java b/telephony/java/android/telephony/SubInfoRecord.java
index e08f255..8ab69cc 100644
--- a/telephony/java/android/telephony/SubInfoRecord.java
+++ b/telephony/java/android/telephony/SubInfoRecord.java
@@ -250,7 +250,7 @@
         dest.writeCharSequence(mDisplayName);
         dest.writeInt(mNameSource);
         dest.writeInt(mColor);
-        dest.writeString(mNumber.toString());
+        dest.writeString(mNumber);
         dest.writeInt(mDataRoaming);
         dest.writeIntArray(mSimIconRes);
         dest.writeInt(mMcc);
diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_start.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_start.xml
deleted file mode 100644
index c26c8ed..0000000
--- a/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_start.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="833"
-            android:propertyName="translateX"
-            android:valueFrom="144"
-            android:valueTo="144"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="100"
-            android:propertyName="translateX"
-            android:valueFrom="144"
-            android:valueTo="147.411817411"
-            android:interpolator="@interpolator/ic_open_ball_start_translatex_interpolator" />
-    </set>
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="167"
-            android:propertyName="translateY"
-            android:valueFrom="144.58457376"
-            android:valueTo="144.58457376"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="333"
-            android:propertyName="translateY"
-            android:valueFrom="144.58457376"
-            android:valueTo="196.11111456"
-            android:interpolator="@interpolator/ic_open_ball_start_translatey_interpolator_1" />
-        <objectAnimator
-            android:duration="333"
-            android:propertyName="translateY"
-            android:valueFrom="196.11111456"
-            android:valueTo="196.11111456"
-            android:interpolator="@interpolator/ic_open_ball_start_translatey_interpolator_2" />
-        <objectAnimator
-            android:duration="100"
-            android:propertyName="translateY"
-            android:valueFrom="196.11111456"
-            android:valueTo="129.468428513"
-            android:interpolator="@interpolator/ic_open_ball_start_translatey_interpolator_3" />
-    </set>
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="167"
-            android:propertyName="scaleX"
-            android:valueFrom="0"
-            android:valueTo="0.71187984"
-            android:interpolator="@interpolator/ic_open_ball_start_scalex_interpolator_1" />
-        <objectAnimator
-            android:duration="667"
-            android:propertyName="scaleX"
-            android:valueFrom="0.71187984"
-            android:valueTo="0.71187984"
-            android:interpolator="@interpolator/ic_open_ball_start_scalex_interpolator_2" />
-        <objectAnimator
-            android:duration="100"
-            android:propertyName="scaleX"
-            android:valueFrom="0.71187984"
-            android:valueTo="0.586201598553"
-            android:interpolator="@interpolator/ic_open_ball_start_scalex_interpolator_3" />
-    </set>
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="167"
-            android:propertyName="scaleY"
-            android:valueFrom="0"
-            android:valueTo="0.71187984"
-            android:interpolator="@interpolator/ic_open_ball_start_scaley_interpolator_1" />
-        <objectAnimator
-            android:duration="667"
-            android:propertyName="scaleY"
-            android:valueFrom="0.71187984"
-            android:valueTo="0.71187984"
-            android:interpolator="@interpolator/ic_open_ball_start_scaley_interpolator_2" />
-        <objectAnimator
-            android:duration="100"
-            android:propertyName="scaleY"
-            android:valueFrom="0.71187984"
-            android:valueTo="0.586201598553"
-            android:interpolator="@interpolator/ic_open_ball_start_scaley_interpolator_3" />
-    </set>
-</set>
diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_swoop.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_swoop.xml
deleted file mode 100644
index 5096514..0000000
--- a/tests/VectorDrawableTest/res/anim/ic_open_animation_ball_swoop.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="933"
-            android:propertyName="rotation"
-            android:valueFrom="-90"
-            android:valueTo="-90"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="1367"
-            android:propertyName="rotation"
-            android:valueFrom="-90"
-            android:valueTo="-87"
-            android:interpolator="@android:interpolator/linear" />
-    </set>
-</set>
diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1.xml
deleted file mode 100644
index ef8496e..0000000
--- a/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="500"
-            android:propertyName="pathData"
-            android:valueFrom="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z"
-            android:valueTo="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z"
-            android:valueType="pathType"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="267"
-            android:propertyName="pathData"
-            android:valueFrom="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z"
-            android:valueTo="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z"
-            android:valueType="pathType"
-            android:interpolator="@interpolator/ic_open_path_1_pathdata_interpolator_1" />
-        <objectAnimator
-            android:duration="33"
-            android:propertyName="pathData"
-            android:valueFrom="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z"
-            android:valueTo="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z"
-            android:valueType="pathType"
-            android:interpolator="@interpolator/ic_open_path_1_pathdata_interpolator_2" />
-        <objectAnimator
-            android:duration="67"
-            android:propertyName="pathData"
-            android:valueFrom="M 0,-6 c -9.625,0 -23.5648803711,6.97859191895 -23.5648803711,16.1035919189 c 0.0,8.875 6.62738037109,8.39640808105 23.5648803711,8.39640808105 c 17.0625,0.0 23.8825073242,0.375 23.8825073242,-8.25 c 0.0,-8.625 -14.2574920654,-16.25 -23.8825073242,-16.25 Z"
-            android:valueTo="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z"
-            android:valueType="pathType"
-            android:interpolator="@interpolator/ic_open_path_1_pathdata_interpolator_3" />
-    </set>
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="933"
-            android:propertyName="fillAlpha"
-            android:valueFrom="1"
-            android:valueTo="1"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="17"
-            android:propertyName="fillAlpha"
-            android:valueFrom="1"
-            android:valueTo="0"
-            android:interpolator="@android:interpolator/linear" />
-    </set>
-</set>
diff --git a/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1_1.xml b/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1_1.xml
deleted file mode 100644
index 4961204..0000000
--- a/tests/VectorDrawableTest/res/anim/ic_open_animation_path_1_1.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="917"
-            android:propertyName="strokeAlpha"
-            android:valueFrom="0"
-            android:valueTo="0"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="17"
-            android:propertyName="strokeAlpha"
-            android:valueFrom="0"
-            android:valueTo="1"
-            android:interpolator="@android:interpolator/linear" />
-    </set>
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="917"
-            android:propertyName="strokeWidth"
-            android:valueFrom="0"
-            android:valueTo="0"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="17"
-            android:propertyName="strokeWidth"
-            android:valueFrom="0"
-            android:valueTo="20"
-            android:interpolator="@android:interpolator/linear" />
-    </set>
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="933"
-            android:propertyName="trimPathStart"
-            android:valueFrom="0.06"
-            android:valueTo="0.06"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="383"
-            android:propertyName="trimPathStart"
-            android:valueFrom="0.06"
-            android:valueTo="0.19231"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="983"
-            android:propertyName="trimPathStart"
-            android:valueFrom="0.19231"
-            android:valueTo="0.999"
-            android:interpolator="@interpolator/ic_open_path_1_1_trimpathstart_interpolator_2" />
-    </set>
-    <set
-        android:ordering="sequentially" >
-        <objectAnimator
-            android:duration="933"
-            android:propertyName="trimPathEnd"
-            android:valueFrom="0.061"
-            android:valueTo="0.061"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="300"
-            android:propertyName="trimPathEnd"
-            android:valueFrom="0.061"
-            android:valueTo="0.19231"
-            android:interpolator="@android:interpolator/linear" />
-        <objectAnimator
-            android:duration="1067"
-            android:propertyName="trimPathEnd"
-            android:valueFrom="0.19231"
-            android:valueTo="1"
-            android:interpolator="@interpolator/ic_open_path_1_1_trimpathend_interpolator_2" />
-    </set>
-</set>
diff --git a/tests/VectorDrawableTest/res/drawable/ic_open.xml b/tests/VectorDrawableTest/res/drawable/ic_open.xml
deleted file mode 100644
index ad96094..0000000
--- a/tests/VectorDrawableTest/res/drawable/ic_open.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<!-- 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="288dp"
-    android:width="288dp"
-    android:viewportHeight="288"
-    android:viewportWidth="288" >
-    <group
-        android:name="ball_start"
-        android:translateX="147.411817411"
-        android:translateY="129.468428513"
-        android:scaleX="0.586201598553"
-        android:scaleY="0.586201598553" >
-        <group
-            android:name="shape_1"
-            android:scaleX="0.76"
-            android:scaleY="0.748114397321" >
-            <path
-                android:name="path_1"
-                android:pathData="M 0,-17.3838043213 c -9.625,0.0 -17.0795440674,8.28025817871 -17.0795440674,17.4052734375 c 0.0,9.75645446777 7.51704406738,17.6295623779 17.0795440674,17.353515625 c 11.5579986572,-0.333648681641 17.2784118652,-8.72853088379 17.2784118652,-17.353515625 c 0.0,-8.62501525879 -7.65341186523,-17.4052734375 -17.2784118652,-17.4052734375 Z"
-                android:fillColor="#FFFF9000"
-                android:fillAlpha="0" />
-        </group>
-    </group>
-    <group
-        android:name="ball_swoop"
-        android:translateX="144"
-        android:translateY="144"
-        android:scaleX="0.752248"
-        android:scaleY="0.752248"
-        android:rotation="-87.6585365854" >
-        <path
-            android:name="path_1_1"
-            android:pathData="M -56.7679443359,1.03857421875 c 0.0,0.0 191.916503906,-13.9097290039 191.916503906,88.0704345703 c 0.0,58.4487304688 -83.6709594727,90.1372070312 -137.004882812,90.1372070312 c -82.1782226562,0.0 -177.867431641,-63.5512695312 -177.867431641,-178.207641602 c 0.0,-115.985717773 98.7650146484,-178.160949707 177.986938477,-178.160949707 c 76.2376251221,0.0 178.1640625,60.6796875 178.1640625,178.185058594 "
-            android:strokeColor="#FFFF9000"
-            android:strokeAlpha="1"
-            android:strokeWidth="20"
-            android:strokeLineCap="round"
-            android:trimPathStart="0.93025"
-            android:trimPathEnd="0.96248"
-            android:trimPathOffset="0"
-            android:fillColor="#00000000" />
-    </group>
-</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/ic_open_animation.xml b/tests/VectorDrawableTest/res/drawable/ic_open_animation.xml
deleted file mode 100644
index 83ee90b..0000000
--- a/tests/VectorDrawableTest/res/drawable/ic_open_animation.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<!-- 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.
--->
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/ic_open" >
-    <target
-        android:name="ball_start"
-        android:animation="@anim/ic_open_animation_ball_start" />
-    <target
-        android:name="path_1"
-        android:animation="@anim/ic_open_animation_path_1" />
-    <target
-        android:name="ball_swoop"
-        android:animation="@anim/ic_open_animation_ball_swoop" />
-    <target
-        android:name="path_1_1"
-        android:animation="@anim/ic_open_animation_path_1_1" />
-</animated-vector>
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_1.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_1.xml
deleted file mode 100644
index 601cfc6..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_1.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.33333333,0.0 0.202777547991,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_2.xml
deleted file mode 100644
index 5011ef9..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.0103034467173,0.0 0.701918866569,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_3.xml
deleted file mode 100644
index 7b0af97..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scalex_interpolator_3.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.649706648701,0.0 0.884285938423,1.92358061843 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_1.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_1.xml
deleted file mode 100644
index 601cfc6..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_1.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.33333333,0.0 0.202777547991,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_2.xml
deleted file mode 100644
index 5011ef9..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.0103034467173,0.0 0.701918866569,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_3.xml
deleted file mode 100644
index 7b0af97..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_scaley_interpolator_3.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.649706648701,0.0 0.884285938423,1.92358061843 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatex_interpolator.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatex_interpolator.xml
deleted file mode 100644
index ea11d1f..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatex_interpolator.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.353876322169,0.0 0.686452288267,-1.02094740172 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_1.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_1.xml
deleted file mode 100644
index 7bd5c49..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_1.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.754478769148,0.0 0.97,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_2.xml
deleted file mode 100644
index b0ab6e8..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.33333333,0.0 0.83333333333,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_3.xml
deleted file mode 100644
index 61060a6..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_ball_start_translatey_interpolator_3.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.324310863613,0.0 0.735625629425,-0.0161527278292 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathend_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathend_interpolator_2.xml
deleted file mode 100644
index 7e19ef6..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathend_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.744517024668,0.120263649138 0.135947812437,0.994319475209 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathstart_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathstart_interpolator_2.xml
deleted file mode 100644
index 1280715..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_1_trimpathstart_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.781904890372,0.126303002187 0.188007240906,0.953418294755 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_1.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_1.xml
deleted file mode 100644
index ddf966e..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_1.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.000100000000012,0.0 0.0,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_2.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_2.xml
deleted file mode 100644
index 624e304..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_2.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 9.99999999007e-05,0.0 0.0,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_3.xml b/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_3.xml
deleted file mode 100644
index 3ebee0b..0000000
--- a/tests/VectorDrawableTest/res/interpolator/ic_open_path_1_pathdata_interpolator_3.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0 0 c 0.000100000000051,0.0 0.83333333333,1.0 1.0,1.0" />
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
index 3045839..c4dfb84 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
@@ -26,7 +26,6 @@
     private static final String LOGCAT = "AnimatedVectorDrawableTest";
 
     protected int[] icon = {
-            R.drawable.ic_open_animation,
             R.drawable.ic_rotate_2_portrait_v2_animation,
             R.drawable.ic_signal_airplane_v2_animation,
             R.drawable.ic_hourglass_animation,
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 5bf3470..75198e5 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -286,7 +286,7 @@
      * Returns the service set identifier (SSID) of the current 802.11 network.
      * If the SSID can be decoded as UTF-8, it will be returned surrounded by double
      * quotation marks. Otherwise, it is returned as a string of hex digits. The
-     * SSID may be {@code null} if there is no network currently connected.
+     * SSID may be &lt;unknown ssid&gt; if there is no network currently connected.
      * @return the SSID
      */
     public String getSSID() {