Merge "Fix issue #15828903: Intent.parseUri allows call to FLAG_GRANT_*_URI_PERMISSION" into lmp-mr1-dev
diff --git a/Android.mk b/Android.mk
index a596ee7..ea22d0f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -174,6 +174,7 @@
 	core/java/android/hardware/usb/IUsbManager.aidl \
 	core/java/android/net/IConnectivityManager.aidl \
 	core/java/android/net/IEthernetManager.aidl \
+	core/java/android/net/IEthernetServiceListener.aidl \
 	core/java/android/net/INetworkManagementEventObserver.aidl \
 	core/java/android/net/INetworkPolicyListener.aidl \
 	core/java/android/net/INetworkPolicyManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 553a30c..d25ae96 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2012,6 +2012,7 @@
     field public static final int Theme_DeviceDefault_Dialog = 16974126; // 0x103012e
     field public static final int Theme_DeviceDefault_DialogWhenLarge = 16974134; // 0x1030136
     field public static final int Theme_DeviceDefault_DialogWhenLarge_NoActionBar = 16974135; // 0x1030137
+    field public static final int Theme_DeviceDefault_Dialog_Alert = 16974545; // 0x10302d1
     field public static final int Theme_DeviceDefault_Dialog_MinWidth = 16974127; // 0x103012f
     field public static final int Theme_DeviceDefault_Dialog_NoActionBar = 16974128; // 0x1030130
     field public static final int Theme_DeviceDefault_Dialog_NoActionBar_MinWidth = 16974129; // 0x1030131
@@ -2021,6 +2022,7 @@
     field public static final int Theme_DeviceDefault_Light_Dialog = 16974130; // 0x1030132
     field public static final int Theme_DeviceDefault_Light_DialogWhenLarge = 16974136; // 0x1030138
     field public static final int Theme_DeviceDefault_Light_DialogWhenLarge_NoActionBar = 16974137; // 0x1030139
+    field public static final int Theme_DeviceDefault_Light_Dialog_Alert = 16974546; // 0x10302d2
     field public static final int Theme_DeviceDefault_Light_Dialog_MinWidth = 16974131; // 0x1030133
     field public static final int Theme_DeviceDefault_Light_Dialog_NoActionBar = 16974132; // 0x1030134
     field public static final int Theme_DeviceDefault_Light_Dialog_NoActionBar_MinWidth = 16974133; // 0x1030135
@@ -4414,7 +4416,7 @@
     method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
     method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
     method public boolean inKeyguardRestrictedInputMode();
-    method public boolean isKeyguardInTrustedState();
+    method public boolean isDeviceLocked();
     method public boolean isKeyguardLocked();
     method public boolean isKeyguardSecure();
     method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
@@ -16931,8 +16933,8 @@
     field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
     field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
     field public static final deprecated java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
-    field public static final java.lang.String EXTRA_NETWORK_REQUEST_NETWORK = "networkRequestNetwork";
-    field public static final java.lang.String EXTRA_NETWORK_REQUEST_NETWORK_REQUEST = "networkRequestNetworkRequest";
+    field public static final java.lang.String EXTRA_NETWORK = "android.net.extra.NETWORK";
+    field public static final java.lang.String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST";
     field public static final java.lang.String EXTRA_NETWORK_TYPE = "networkType";
     field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
     field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index a9eaf29..3f1845a 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -16,6 +16,7 @@
 
 package android.accessibilityservice;
 
+import android.annotation.NonNull;
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
@@ -27,6 +28,7 @@
 import android.view.KeyEvent;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -618,6 +620,23 @@
         }
     }
 
+    @Override
+    public Object getSystemService(@ServiceName @NonNull String name) {
+        if (getBaseContext() == null) {
+            throw new IllegalStateException(
+                    "System services not available to Activities before onCreate()");
+        }
+
+        // Guarantee that we always return the same window manager instance.
+        if (WINDOW_SERVICE.equals(name)) {
+            if (mWindowManager == null) {
+                mWindowManager = (WindowManager) getBaseContext().getSystemService(name);
+            }
+            return mWindowManager;
+        }
+        return super.getSystemService(name);
+    }
+
     /**
      * Implement to return the implementation of the internal accessibility
      * service interface.
@@ -645,8 +664,10 @@
                 mConnectionId = connectionId;
                 mWindowToken = windowToken;
 
-                // Let the window manager know about our shiny new token.
-                WindowManagerGlobal.getInstance().setDefaultToken(mWindowToken);
+                // The client may have already obtained the window manager, so
+                // update the default token on whatever manager we gave them.
+                final WindowManagerImpl wm = (WindowManagerImpl) getSystemService(WINDOW_SERVICE);
+                wm.setDefaultToken(windowToken);
             }
 
             @Override
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 5038df9..ddd21e6 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -225,28 +225,28 @@
     }
 
     /**
-     * Return whether unlocking the device is currently not requiring a password
-     * because of a trust agent.
+     * Returns whether the device is currently locked and requires a PIN, pattern or
+     * password to unlock.
      *
-     * @return true if the keyguard can currently be unlocked without entering credentials
-     *         because the device is in a trusted environment.
+     * @return true if unlocking the device currently requires a PIN, pattern or
+     * password.
      */
-    public boolean isKeyguardInTrustedState() {
-        return isKeyguardInTrustedState(UserHandle.getCallingUserId());
+    public boolean isDeviceLocked() {
+        return isDeviceLocked(UserHandle.getCallingUserId());
     }
 
     /**
-     * Return whether unlocking the device is currently not requiring a password
-     * because of a trust agent.
+     * Returns whether the device is currently locked and requires a PIN, pattern or
+     * password to unlock.
      *
-     * @param userId the user for which the trusted state should be reported.
-     * @return true if the keyguard can currently be unlocked without entering credentials
-     *         because the device is in a trusted environment.
+     * @param userId the user for which the locked state should be reported.
+     * @return true if unlocking the device currently requires a PIN, pattern or
+     * password.
      * @hide
      */
-    public boolean isKeyguardInTrustedState(int userId) {
+    public boolean isDeviceLocked(int userId) {
         try {
-            return mTrustManager.isTrusted(userId);
+            return mTrustManager.isDeviceLocked(userId);
         } catch (RemoteException e) {
             return false;
         }
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index aa98e97..ece2a33 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -632,55 +632,60 @@
     public void removeContextRegistrations(Context context,
             String who, String what) {
         final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
-        ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
-                mReceivers.remove(context);
-        if (rmap != null) {
-            for (int i=0; i<rmap.size(); i++) {
-                LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
-                IntentReceiverLeaked leak = new IntentReceiverLeaked(
-                        what + " " + who + " has leaked IntentReceiver "
-                        + rd.getIntentReceiver() + " that was " +
-                        "originally registered here. Are you missing a " +
-                        "call to unregisterReceiver()?");
-                leak.setStackTrace(rd.getLocation().getStackTrace());
-                Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
-                if (reportRegistrationLeaks) {
-                    StrictMode.onIntentReceiverLeaked(leak);
-                }
-                try {
-                    ActivityManagerNative.getDefault().unregisterReceiver(
-                            rd.getIIntentReceiver());
-                } catch (RemoteException e) {
-                    // system crashed, nothing we can do
+        synchronized (mReceivers) {
+            ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
+                    mReceivers.remove(context);
+            if (rmap != null) {
+                for (int i = 0; i < rmap.size(); i++) {
+                    LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
+                    IntentReceiverLeaked leak = new IntentReceiverLeaked(
+                            what + " " + who + " has leaked IntentReceiver "
+                            + rd.getIntentReceiver() + " that was " +
+                            "originally registered here. Are you missing a " +
+                            "call to unregisterReceiver()?");
+                    leak.setStackTrace(rd.getLocation().getStackTrace());
+                    Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
+                    if (reportRegistrationLeaks) {
+                        StrictMode.onIntentReceiverLeaked(leak);
+                    }
+                    try {
+                        ActivityManagerNative.getDefault().unregisterReceiver(
+                                rd.getIIntentReceiver());
+                    } catch (RemoteException e) {
+                        // system crashed, nothing we can do
+                    }
                 }
             }
+            mUnregisteredReceivers.remove(context);
         }
-        mUnregisteredReceivers.remove(context);
-        //Slog.i(TAG, "Receiver registrations: " + mReceivers);
-        ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
-            mServices.remove(context);
-        if (smap != null) {
-            for (int i=0; i<smap.size(); i++) {
-                LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
-                ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
-                        what + " " + who + " has leaked ServiceConnection "
-                        + sd.getServiceConnection() + " that was originally bound here");
-                leak.setStackTrace(sd.getLocation().getStackTrace());
-                Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
-                if (reportRegistrationLeaks) {
-                    StrictMode.onServiceConnectionLeaked(leak);
+
+        synchronized (mServices) {
+            //Slog.i(TAG, "Receiver registrations: " + mReceivers);
+            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
+                    mServices.remove(context);
+            if (smap != null) {
+                for (int i = 0; i < smap.size(); i++) {
+                    LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
+                    ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
+                            what + " " + who + " has leaked ServiceConnection "
+                            + sd.getServiceConnection() + " that was originally bound here");
+                    leak.setStackTrace(sd.getLocation().getStackTrace());
+                    Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
+                    if (reportRegistrationLeaks) {
+                        StrictMode.onServiceConnectionLeaked(leak);
+                    }
+                    try {
+                        ActivityManagerNative.getDefault().unbindService(
+                                sd.getIServiceConnection());
+                    } catch (RemoteException e) {
+                        // system crashed, nothing we can do
+                    }
+                    sd.doForget();
                 }
-                try {
-                    ActivityManagerNative.getDefault().unbindService(
-                            sd.getIServiceConnection());
-                } catch (RemoteException e) {
-                    // system crashed, nothing we can do
-                }
-                sd.doForget();
             }
+            mUnboundServices.remove(context);
+            //Slog.i(TAG, "Service registrations: " + mServices);
         }
-        mUnboundServices.remove(context);
-        //Slog.i(TAG, "Service registrations: " + mServices);
     }
 
     public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index 0193711..68ea0aa 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -29,5 +29,6 @@
     void reportRequireCredentialEntry(int userId);
     void registerTrustListener(in ITrustListener trustListener);
     void unregisterTrustListener(in ITrustListener trustListener);
-    boolean isTrusted(int userId);
+    void reportKeyguardShowingChanged();
+    boolean isDeviceLocked(int userId);
 }
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 3d262b1..705a144 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -88,6 +88,19 @@
     }
 
     /**
+     * Reports that the visibility of the keyguard has changed.
+     *
+     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+     */
+    public void reportKeyguardShowingChanged() {
+        try {
+            mService.reportKeyguardShowingChanged();
+        } catch (RemoteException e) {
+            onError(e);
+        }
+    }
+
+    /**
      * Registers a listener for trust events.
      *
      * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission.
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 271fc30..895ae04 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -490,12 +490,16 @@
      * <p>More specifically, this means that a size matching the
      * camera device's active array size is listed as a
      * supported size for the YUV_420_888 format in
-     * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}, and the
-     * minimum frame duration for that format and size is &lt;=
-     * 1/20 s.</p>
+     * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}, the minimum frame
+     * duration for that format and size is &lt;= 1/20 s, and
+     * the {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} entry
+     * lists at least one FPS range where the minimum FPS
+     * is &gt;= 1 / minimumFrameDuration for the maximum-size
+     * YUV_420_888 format.</p>
      * <p>In addition, the {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} field is
      * guaranted to have a value between 0 and 4, inclusive.</p>
      *
+     * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
      * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
      * @see CameraCharacteristics#SYNC_MAX_LATENCY
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1c9f4c68..ec24ded 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2381,15 +2381,14 @@
      * successfully finding a network for the applications request.  Retrieve it with
      * {@link android.content.Intent#getParcelableExtra(String)}.
      */
-    public static final String EXTRA_NETWORK_REQUEST_NETWORK = "networkRequestNetwork";
+    public static final String EXTRA_NETWORK = "android.net.extra.NETWORK";
 
     /**
      * The lookup key for a {@link NetworkRequest} object included with the intent after
      * successfully finding a network for the applications request.  Retrieve it with
      * {@link android.content.Intent#getParcelableExtra(String)}.
      */
-    public static final String EXTRA_NETWORK_REQUEST_NETWORK_REQUEST =
-            "networkRequestNetworkRequest";
+    public static final String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST";
 
 
     /**
@@ -2405,8 +2404,8 @@
      * &lt;receiver&gt; tag in an AndroidManifest.xml file
      * <p>
      * The operation Intent is delivered with two extras, a {@link Network} typed
-     * extra called {@link #EXTRA_NETWORK_REQUEST_NETWORK} and a {@link NetworkRequest}
-     * typed extra called {@link #EXTRA_NETWORK_REQUEST_NETWORK_REQUEST} containing
+     * extra called {@link #EXTRA_NETWORK} and a {@link NetworkRequest}
+     * typed extra called {@link #EXTRA_NETWORK_REQUEST} containing
      * the original requests parameters.  It is important to create a new,
      * {@link NetworkCallback} based request before completing the processing of the
      * Intent to reserve the network or it will be released shortly after the Intent
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index d965f27..f45737a 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -18,11 +18,14 @@
 
 import android.content.Context;
 import android.net.IEthernetManager;
+import android.net.IEthernetServiceListener;
 import android.net.IpConfiguration;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
+import android.os.Handler;
+import android.os.Message;
 import android.os.RemoteException;
 
+import java.util.ArrayList;
+
 /**
  * A class representing the IP configuration of the Ethernet network.
  *
@@ -30,9 +33,41 @@
  */
 public class EthernetManager {
     private static final String TAG = "EthernetManager";
+    private static final int MSG_AVAILABILITY_CHANGED = 1000;
 
     private final Context mContext;
     private final IEthernetManager mService;
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg.what == MSG_AVAILABILITY_CHANGED) {
+                boolean isAvailable = (msg.arg1 == 1);
+                for (Listener listener : mListeners) {
+                    listener.onAvailabilityChanged(isAvailable);
+                }
+            }
+        }
+    };
+    private final ArrayList<Listener> mListeners = new ArrayList<Listener>();
+    private final IEthernetServiceListener.Stub mServiceListener =
+            new IEthernetServiceListener.Stub() {
+                @Override
+                public void onAvailabilityChanged(boolean isAvailable) {
+                    mHandler.obtainMessage(
+                            MSG_AVAILABILITY_CHANGED, isAvailable ? 1 : 0, 0, null).sendToTarget();
+                }
+            };
+
+    /**
+     * A listener interface to receive notification on changes in Ethernet.
+     */
+    public interface Listener {
+        /**
+         * Called when Ethernet port's availability is changed.
+         * @param isAvailable {@code true} if one or more Ethernet port exists.
+         */
+        public void onAvailabilityChanged(boolean isAvailable);
+    }
 
     /**
      * Create a new EthernetManager instance.
@@ -50,12 +85,9 @@
      * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
      */
     public IpConfiguration getConfiguration() {
-        if (mService == null) {
-            return new IpConfiguration();
-        }
         try {
             return mService.getConfiguration();
-        } catch (RemoteException e) {
+        } catch (NullPointerException | RemoteException e) {
             return new IpConfiguration();
         }
     }
@@ -64,12 +96,57 @@
      * Set Ethernet configuration.
      */
     public void setConfiguration(IpConfiguration config) {
-        if (mService == null) {
-            return;
-        }
         try {
             mService.setConfiguration(config);
-        } catch (RemoteException e) {
+        } catch (NullPointerException | RemoteException e) {
+        }
+    }
+
+    /**
+     * Indicates whether the system currently has one or more
+     * Ethernet interfaces.
+     */
+    public boolean isAvailable() {
+        try {
+            return mService.isAvailable();
+        } catch (NullPointerException | RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Adds a listener.
+     * @param listener A {@link Listener} to add.
+     * @throws IllegalArgumentException If the listener is null.
+     */
+    public void addListener(Listener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+        mListeners.add(listener);
+        if (mListeners.size() == 1) {
+            try {
+                mService.addListener(mServiceListener);
+            } catch (NullPointerException | RemoteException e) {
+            }
+        }
+    }
+
+    /**
+     * Removes a listener.
+     * @param listener A {@link Listener} to remove.
+     * @throws IllegalArgumentException If the listener is null.
+     */
+    public void removeListener(Listener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+        mListeners.remove(listener);
+        if (mListeners.isEmpty()) {
+            try {
+                mService.removeListener(mServiceListener);
+            } catch (NullPointerException | RemoteException e) {
+            }
         }
     }
 }
diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl
index 3fa08f8..7a92eb9 100644
--- a/core/java/android/net/IEthernetManager.aidl
+++ b/core/java/android/net/IEthernetManager.aidl
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.net.IpConfiguration;
+import android.net.IEthernetServiceListener;
 
 /**
  * Interface that answers queries about, and allows changing
@@ -27,4 +28,7 @@
 {
     IpConfiguration getConfiguration();
     void setConfiguration(in IpConfiguration config);
+    boolean isAvailable();
+    void addListener(in IEthernetServiceListener listener);
+    void removeListener(in IEthernetServiceListener listener);
 }
diff --git a/core/java/android/net/IEthernetServiceListener.aidl b/core/java/android/net/IEthernetServiceListener.aidl
new file mode 100644
index 0000000..356690e8
--- /dev/null
+++ b/core/java/android/net/IEthernetServiceListener.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/** @hide */
+oneway interface IEthernetServiceListener
+{
+    void onAvailabilityChanged(boolean isAvailable);
+}
diff --git a/core/java/android/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl
index bb0c2b2..f07d0d0 100644
--- a/core/java/android/service/trust/ITrustAgentService.aidl
+++ b/core/java/android/service/trust/ITrustAgentService.aidl
@@ -25,6 +25,8 @@
 interface ITrustAgentService {
     oneway void onUnlockAttempt(boolean successful);
     oneway void onTrustTimeout();
+    oneway void onDeviceLocked();
+    oneway void onDeviceUnlocked();
     oneway void onConfigure(in List<PersistableBundle> options, IBinder token);
     oneway void setCallback(ITrustAgentServiceCallback callback);
 }
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index d6c997f..62fa978 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -92,6 +92,8 @@
     private static final int MSG_UNLOCK_ATTEMPT = 1;
     private static final int MSG_CONFIGURE = 2;
     private static final int MSG_TRUST_TIMEOUT = 3;
+    private static final int MSG_DEVICE_LOCKED = 4;
+    private static final int MSG_DEVICE_UNLOCKED = 5;
 
     /**
      * Class containing raw data for a given configuration request.
@@ -134,6 +136,12 @@
                 case MSG_TRUST_TIMEOUT:
                     onTrustTimeout();
                     break;
+                case MSG_DEVICE_LOCKED:
+                    onDeviceLocked();
+                    break;
+                case MSG_DEVICE_UNLOCKED:
+                    onDeviceUnlocked();
+                    break;
             }
         }
     };
@@ -173,6 +181,20 @@
     public void onTrustTimeout() {
     }
 
+    /**
+     * Called when the device enters a state where a PIN, pattern or
+     * password must be entered to unlock it.
+     */
+    public void onDeviceLocked() {
+    }
+
+    /**
+     * Called when the device leaves a state where a PIN, pattern or
+     * password must be entered to unlock it.
+     */
+    public void onDeviceUnlocked() {
+    }
+
     private void onError(String msg) {
         Slog.v(TAG, "Remote exception while " + msg);
     }
@@ -300,6 +322,16 @@
                     .sendToTarget();
         }
 
+        @Override
+        public void onDeviceLocked() throws RemoteException {
+            mHandler.obtainMessage(MSG_DEVICE_LOCKED).sendToTarget();
+        }
+
+        @Override
+        public void onDeviceUnlocked() throws RemoteException {
+            mHandler.obtainMessage(MSG_DEVICE_UNLOCKED).sendToTarget();
+        }
+
         @Override /* Binder API */
         public void setCallback(ITrustAgentServiceCallback callback) {
             synchronized (mLock) {
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index d120d79..dbd580d 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -216,7 +216,7 @@
     ///////////////////////////////////////////////////////////////////////////
 
     @Override
-    public int callDrawGLFunction(long drawGLFunction) {
+    public int callDrawGLFunction2(long drawGLFunction) {
         return nCallDrawGLFunction(mRenderer, drawGLFunction);
     }
 
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index e3eee71..18accb8 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -105,10 +105,7 @@
      *
      * @hide
      */
-    public int callDrawGLFunction(long drawGLFunction) {
-        // Noop - this is done in the display list recorder subclass
-        return RenderNode.STATUS_DONE;
-    }
+    public abstract int callDrawGLFunction2(long drawGLFunction);
 
     public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
             CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 2c8a499..131c039 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -340,6 +340,7 @@
                 recordDuration, view.getResources().getDisplayMetrics().density);
         if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
             setEnabled(false);
+            attachInfo.mViewRootImpl.mSurface.release();
             // Invalidate since we failed to draw. This should fetch a Surface
             // if it is still needed or do nothing if we are no longer drawing
             attachInfo.mViewRootImpl.invalidate();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fe17417..b12c747 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -245,7 +245,7 @@
 
     // These can be accessed by any thread, must be protected with a lock.
     // Surface can never be reassigned or cleared (use Surface.clear()).
-    private final Surface mSurface = new Surface();
+    final Surface mSurface = new Surface();
 
     boolean mAdded;
     boolean mAddedTouchMode;
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 8e27834..0d82087 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -118,9 +118,6 @@
 
     private Runnable mSystemPropertyUpdater;
 
-    /** Default token to apply to added views. */
-    private IBinder mDefaultToken;
-
     private WindowManagerGlobal() {
     }
 
@@ -181,17 +178,6 @@
         }
     }
 
-    /**
-     * Sets the default token to use in {@link #addView} when no parent window
-     * token is available and no token has been explicitly set in the view's
-     * layout params.
-     *
-     * @param token Default window token to apply to added views.
-     */
-    public void setDefaultToken(IBinder token) {
-        mDefaultToken = token;
-    }
-
     public String[] getViewRootNames() {
         synchronized (mLock) {
             final int numRoots = mRoots.size();
@@ -239,10 +225,6 @@
             }
         }
 
-        if (wparams.token == null && mDefaultToken != null) {
-            wparams.token = mDefaultToken;
-        }
-
         ViewRootImpl root;
         View panelParentView = null;
 
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 52d79f8..98e9f54 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -16,6 +16,9 @@
 
 package android.view;
 
+import android.annotation.NonNull;
+import android.os.IBinder;
+
 /**
  * Provides low-level communication with the system window manager for
  * operations that are bound to a particular context, display or parent window.
@@ -47,6 +50,8 @@
     private final Display mDisplay;
     private final Window mParentWindow;
 
+    private IBinder mDefaultToken;
+
     public WindowManagerImpl(Display display) {
         this(display, null);
     }
@@ -64,16 +69,43 @@
         return new WindowManagerImpl(display, mParentWindow);
     }
 
+    /**
+     * Sets the window token to assign when none is specified by the client or
+     * available from the parent window.
+     *
+     * @param token The default token to assign.
+     */
+    public void setDefaultToken(IBinder token) {
+        mDefaultToken = token;
+    }
+
     @Override
-    public void addView(View view, ViewGroup.LayoutParams params) {
+    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
+        applyDefaultToken(params);
         mGlobal.addView(view, params, mDisplay, mParentWindow);
     }
 
     @Override
-    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
+        applyDefaultToken(params);
         mGlobal.updateViewLayout(view, params);
     }
 
+    private void applyDefaultToken(@NonNull ViewGroup.LayoutParams params) {
+        // Only use the default token if we don't have a parent window.
+        if (mDefaultToken != null && mParentWindow == null) {
+            if (!(params instanceof WindowManager.LayoutParams)) {
+                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+            }
+
+            // Only use the default token if we don't already have a token.
+            final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
+            if (wparams.token == null) {
+                wparams.token = mDefaultToken;
+            }
+        }
+    }
+
     @Override
     public void removeView(View view) {
         mGlobal.removeView(view, false);
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 3dcfda3..e03445e 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -107,7 +107,7 @@
             throw new IllegalArgumentException(canvas.getClass().getName()
                     + " is not hardware accelerated");
         }
-        ((HardwareCanvas) canvas).callDrawGLFunction(nativeDrawGLFunctor);
+        ((HardwareCanvas) canvas).callDrawGLFunction2(nativeDrawGLFunctor);
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 3ccced5..8d3db5b 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -384,8 +384,16 @@
      * @return Whether a saved pattern exists.
      */
     public boolean savedPatternExists() {
+        return savedPatternExists(getCurrentOrCallingUserId());
+    }
+
+    /**
+     * Check to see if the user has stored a lock pattern.
+     * @return Whether a saved pattern exists.
+     */
+    public boolean savedPatternExists(int userId) {
         try {
-            return getLockSettings().havePattern(getCurrentOrCallingUserId());
+            return getLockSettings().havePattern(userId);
         } catch (RemoteException re) {
             return false;
         }
@@ -396,8 +404,16 @@
      * @return Whether a saved pattern exists.
      */
     public boolean savedPasswordExists() {
+        return savedPasswordExists(getCurrentOrCallingUserId());
+    }
+
+     /**
+     * Check to see if the user has stored a lock pattern.
+     * @return Whether a saved pattern exists.
+     */
+    public boolean savedPasswordExists(int userId) {
         try {
-            return getLockSettings().havePassword(getCurrentOrCallingUserId());
+            return getLockSettings().havePassword(userId);
         } catch (RemoteException re) {
             return false;
         }
@@ -955,8 +971,15 @@
      * @return true if the lockscreen method is set to biometric weak
      */
     public boolean usingBiometricWeak() {
-        int quality =
-                (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
+        return usingBiometricWeak(getCurrentOrCallingUserId());
+    }
+
+    /**
+     * @return true if the lockscreen method is set to biometric weak
+     */
+    public boolean usingBiometricWeak(int userId) {
+        int quality = (int) getLong(
+                PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
         return quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
     }
 
@@ -1096,15 +1119,22 @@
      * @return Whether the lock pattern is enabled, or if it is set as a backup for biometric weak
      */
     public boolean isLockPatternEnabled() {
+        return isLockPatternEnabled(getCurrentOrCallingUserId());
+    }
+
+    /**
+     * @return Whether the lock pattern is enabled, or if it is set as a backup for biometric weak
+     */
+    public boolean isLockPatternEnabled(int userId) {
         final boolean backupEnabled =
                 getLong(PASSWORD_TYPE_ALTERNATE_KEY,
-                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
+                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId)
                                 == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
 
-        return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false)
-                && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
-                        == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING ||
-                        (usingBiometricWeak() && backupEnabled));
+        return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false, userId)
+                && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
+                        userId) == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
+                        || (usingBiometricWeak(userId) && backupEnabled));
     }
 
     /**
@@ -1485,15 +1515,20 @@
     }
 
     public boolean isSecure() {
-        long mode = getKeyguardStoredPasswordQuality();
+        return isSecure(getCurrentOrCallingUserId());
+    }
+
+    public boolean isSecure(int userId) {
+        long mode = getKeyguardStoredPasswordQuality(userId);
         final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
         final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
                 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
                 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
                 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
-        final boolean secure = isPattern && isLockPatternEnabled() && savedPatternExists()
-                || isPassword && savedPasswordExists();
+        final boolean secure =
+                isPattern && isLockPatternEnabled(userId) && savedPatternExists(userId)
+                || isPassword && savedPasswordExists(userId);
         return secure;
     }
 
diff --git a/core/res/res/layout/select_dialog_material.xml b/core/res/res/layout/select_dialog_material.xml
index ee04039..19ad407 100644
--- a/core/res/res/layout/select_dialog_material.xml
+++ b/core/res/res/layout/select_dialog_material.xml
@@ -22,11 +22,14 @@
 -->
 <view class="com.android.internal.app.AlertController$RecycleListView"
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+android:id/select_dialog_listview"
+    android:id="@id/select_dialog_listview"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:cacheColorHint="@null"
-    android:divider="?android:attr/listDividerAlertDialog"
+    android:divider="?attr/listDividerAlertDialog"
     android:scrollbars="vertical"
     android:overScrollMode="ifContentScrolls"
-    android:textAlignment="viewStart" />
+    android:textAlignment="viewStart"
+    android:paddingTop="@dimen/dialog_list_padding_vertical_material"
+    android:paddingBottom="@dimen/dialog_list_padding_vertical_material"
+    android:clipToPadding="false" />
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index e3672c8..54f483d 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -97,4 +97,7 @@
 
     <dimen name="dialog_padding_material">24dp</dimen>
     <dimen name="dialog_padding_top_material">18dp</dimen>
+
+    <!-- Padding above and below selection dialog lists. -->
+    <dimen name="dialog_list_padding_vertical_material">8dp</dimen>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c01d406..1123813 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2602,4 +2602,7 @@
     <public type="attr" name="dialogPreferredPadding" />
     <public type="attr" name="searchHintIcon" />
 
+    <public type="style" name="Theme.DeviceDefault.Dialog.Alert" />
+    <public type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" />
+
 </resources>
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index 1649268..6bd8f6e 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -68,8 +68,9 @@
 
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
     <!-- This permission is added for API call setAirplaneMode() in ConnectivityManager -->
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index f3d5c87..e04c214 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -199,7 +199,7 @@
                 Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
         // set wifi sleep policy to never on while in sleep
         Settings.Global.putInt(mRunner.getContext().getContentResolver(),
-                Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_NEVER);
+                Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_DEFAULT);
         // set idle timeout for wifi to 15s
         Settings.Global.putLong(mRunner.getContext().getContentResolver(),
                 Settings.Global.WIFI_IDLE_MS, WIFI_IDLE_MS);
diff --git a/graphics/java/android/graphics/ColorMatrix.java b/graphics/java/android/graphics/ColorMatrix.java
index 1242eb5..64f0c05 100644
--- a/graphics/java/android/graphics/ColorMatrix.java
+++ b/graphics/java/android/graphics/ColorMatrix.java
@@ -21,23 +21,43 @@
 import java.util.Arrays;
 
 /**
- *  4x5 matrix for transforming the color+alpha components of a Bitmap.
- *  The matrix is stored in a single array, and its treated as follows:
+ * 4x5 matrix for transforming the color and alpha components of a Bitmap.
+ * The matrix can be passed as single array, and is treated as follows:
+ *
  * <pre>
  *  [ a, b, c, d, e,
  *    f, g, h, i, j,
  *    k, l, m, n, o,
- *    p, q, r, s, t ]
- * </pre>
+ *    p, q, r, s, t ]</pre>
  *
- * When applied to a color <code>[r, g, b, a]</code>, the resulting color
- * is computed as (after clamping):
+ * <p>
+ * When applied to a color <code>[R, G, B, A]</code>, the resulting color
+ * is computed as:
+ * </p>
+ *
  * <pre>
- *   R' = a*R + b*G + c*B + d*A + e;
- *   G' = f*R + g*G + h*B + i*A + j;
- *   B' = k*R + l*G + m*B + n*A + o;
- *   A' = p*R + q*G + r*B + s*A + t;
- * </pre>
+ *   R&rsquo; = a*R + b*G + c*B + d*A + e;
+ *   G&rsquo; = f*R + g*G + h*B + i*A + j;
+ *   B&rsquo; = k*R + l*G + m*B + n*A + o;
+ *   A&rsquo; = p*R + q*G + r*B + s*A + t;</pre>
+ *
+ * <p>
+ * That resulting color <code>[R&rsquo;, G&rsquo;, B&rsquo;, A&rsquo;]</code>
+ * then has each channel clamped to the <code>0</code> to <code>255</code>
+ * range.
+ * </p>
+ *
+ * <p>
+ * The sample ColorMatrix below inverts incoming colors by scaling each
+ * channel by <code>-1</code>, and then shifting the result up by
+ * <code>255</code> to remain in the standard color space.
+ * </p>
+ *
+ * <pre>
+ *   [ -1, 0, 0, 0, 255,
+ *     0, -1, 0, 0, 255,
+ *     0, 0, -1, 0, 255,
+ *     0, 0, 0, 1, 0 ]</pre>
  */
 @SuppressWarnings({ "MismatchedReadAndWriteOfArray", "PointlessArithmeticExpression" })
 public class ColorMatrix {
@@ -52,24 +72,24 @@
     }
 
     /**
-        * Create a new colormatrix initialized with the specified array of values.
+     * Create a new colormatrix initialized with the specified array of values.
      */
     public ColorMatrix(float[] src) {
         System.arraycopy(src, 0, mArray, 0, 20);
     }
-    
+
     /**
      * Create a new colormatrix initialized with the specified colormatrix.
      */
     public ColorMatrix(ColorMatrix src) {
         System.arraycopy(src.mArray, 0, mArray, 0, 20);
     }
-    
+
     /**
      * Return the array of floats representing this colormatrix.
      */
     public final float[] getArray() { return mArray; }
-    
+
     /**
      * Set this colormatrix to identity:
      * <pre>
@@ -84,7 +104,7 @@
         Arrays.fill(a, 0);
         a[0] = a[6] = a[12] = a[18] = 1;
     }
-    
+
     /**
      * Assign the src colormatrix into this matrix, copying all of its values.
      */
@@ -98,7 +118,7 @@
     public void set(float[] src) {
         System.arraycopy(src, 0, mArray, 0, 20);
     }
-    
+
     /**
      * Set this colormatrix to scale by the specified values.
      */
@@ -114,12 +134,14 @@
         a[12] = bScale;
         a[18] = aScale;
     }
-    
+
     /**
      * Set the rotation on a color axis by the specified values.
+     * <p>
      * <code>axis=0</code> correspond to a rotation around the RED color
      * <code>axis=1</code> correspond to a rotation around the GREEN color
      * <code>axis=2</code> correspond to a rotation around the BLUE color
+     * </p>
      */
     public void setRotate(int axis, float degrees) {
         reset();
@@ -153,8 +175,10 @@
     /**
      * Set this colormatrix to the concatenation of the two specified
      * colormatrices, such that the resulting colormatrix has the same effect
-     * as applying matB and then applying matA. It is legal for either matA or
-     * matB to be the same colormatrix as this.
+     * as applying matB and then applying matA.
+     * <p>
+     * It is legal for either matA or matB to be the same colormatrix as this.
+     * </p>
      */
     public void setConcat(ColorMatrix matA, ColorMatrix matB) {
         float[] tmp;
@@ -163,7 +187,7 @@
         } else {
             tmp = mArray;
         }
-        
+
         final float[] a = matA.mArray;
         final float[] b = matB.mArray;
         int index = 0;
@@ -176,38 +200,43 @@
                            a[j + 2] * b[14] + a[j + 3] * b[19] +
                            a[j + 4];
         }
-        
+
         if (tmp != mArray) {
             System.arraycopy(tmp, 0, mArray, 0, 20);
         }
     }
 
     /**
-     * Concat this colormatrix with the specified prematrix. This is logically
-     * the same as calling setConcat(this, prematrix);
+     * Concat this colormatrix with the specified prematrix.
+     * <p>
+     * This is logically the same as calling setConcat(this, prematrix);
+     * </p>
      */
     public void preConcat(ColorMatrix prematrix) {
         setConcat(this, prematrix);
     }
 
     /**
-     * Concat this colormatrix with the specified postmatrix. This is logically
-     * the same as calling setConcat(postmatrix, this);
+     * Concat this colormatrix with the specified postmatrix.
+     * <p>
+     * This is logically the same as calling setConcat(postmatrix, this);
+     * </p>
      */
     public void postConcat(ColorMatrix postmatrix) {
         setConcat(postmatrix, this);
     }
 
     ///////////////////////////////////////////////////////////////////////////
-    
+
     /**
-     * Set the matrix to affect the saturation of colors. A value of 0 maps the
-     * color to gray-scale. 1 is identity.
+     * Set the matrix to affect the saturation of colors.
+     *
+     * @param sat A value of 0 maps the color to gray-scale. 1 is identity.
      */
     public void setSaturation(float sat) {
         reset();
         float[] m = mArray;
-        
+
         final float invSat = 1 - sat;
         final float R = 0.213f * invSat;
         final float G = 0.715f * invSat;
@@ -217,7 +246,7 @@
         m[5] = R;       m[6] = G + sat; m[7] = B;
         m[10] = R;      m[11] = G;      m[12] = B + sat;
     }
-    
+
     /**
      * Set the matrix to convert RGB to YUV
      */
@@ -229,7 +258,7 @@
         m[5]  = -0.16874f; m[6]  = -0.33126f; m[7]  = 0.5f;
         m[10] = 0.5f;      m[11] = -0.41869f; m[12] = -0.08131f;
     }
-    
+
     /**
      * Set the matrix to convert from YUV to RGB
      */
@@ -242,4 +271,3 @@
         m[10] = 1;  m[11] = 1.772f;     m[12] = 0;
     }
 }
-
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 6d23634..f58a765 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -199,6 +199,8 @@
             return false;
         }
 
+        boolean hasReversibleFlag = state.transitionHasReversibleFlag(fromId, toId);
+
         // This may fail if we're already on the transition, but that's okay!
         selectDrawable(transitionIndex);
 
@@ -206,10 +208,14 @@
         final Drawable d = getCurrent();
         if (d instanceof AnimationDrawable) {
             final boolean reversed = state.isTransitionReversed(fromId, toId);
-            transition = new AnimationDrawableTransition((AnimationDrawable) d, reversed);
+
+            transition = new AnimationDrawableTransition((AnimationDrawable) d,
+                    reversed, hasReversibleFlag);
         } else if (d instanceof AnimatedVectorDrawable) {
             final boolean reversed = state.isTransitionReversed(fromId, toId);
-            transition = new AnimatedVectorDrawableTransition((AnimatedVectorDrawable) d, reversed);
+
+            transition = new AnimatedVectorDrawableTransition((AnimatedVectorDrawable) d,
+                    reversed, hasReversibleFlag);
         } else if (d instanceof Animatable) {
             transition = new AnimatableTransition((Animatable) d);
         } else {
@@ -260,7 +266,12 @@
     private static class AnimationDrawableTransition  extends Transition {
         private final ObjectAnimator mAnim;
 
-        public AnimationDrawableTransition(AnimationDrawable ad, boolean reversed) {
+        // Even AnimationDrawable is always reversible technically, but
+        // we should obey the XML's android:reversible flag.
+        private final boolean mHasReversibleFlag;
+
+        public AnimationDrawableTransition(AnimationDrawable ad,
+                boolean reversed, boolean hasReversibleFlag) {
             final int frameCount = ad.getNumberOfFrames();
             final int fromFrame = reversed ? frameCount - 1 : 0;
             final int toFrame = reversed ? 0 : frameCount - 1;
@@ -269,13 +280,13 @@
             anim.setAutoCancel(true);
             anim.setDuration(interp.getTotalDuration());
             anim.setInterpolator(interp);
-
+            mHasReversibleFlag = hasReversibleFlag;
             mAnim = anim;
         }
 
         @Override
         public boolean canReverse() {
-            return true;
+            return mHasReversibleFlag;
         }
 
         @Override
@@ -296,16 +307,28 @@
 
     private static class AnimatedVectorDrawableTransition  extends Transition {
         private final AnimatedVectorDrawable mAvd;
+
+        // mReversed is indicating the current transition's direction.
         private final boolean mReversed;
 
-        public AnimatedVectorDrawableTransition(AnimatedVectorDrawable avd, boolean reversed) {
+        // mHasReversibleFlag is indicating whether the whole transition has
+        // reversible flag set to true.
+        // If mHasReversibleFlag is false, then mReversed is always false.
+        private final boolean mHasReversibleFlag;
+
+        public AnimatedVectorDrawableTransition(AnimatedVectorDrawable avd,
+                boolean reversed, boolean hasReversibleFlag) {
             mAvd = avd;
             mReversed = reversed;
+            mHasReversibleFlag = hasReversibleFlag;
         }
 
         @Override
         public boolean canReverse() {
-            return mAvd.canReverse();
+            // When the transition's XML says it is not reversible, then we obey
+            // it, even if the AVD itself is reversible.
+            // This will help the single direction transition.
+            return mAvd.canReverse() && mHasReversibleFlag;
         }
 
         @Override
@@ -322,7 +345,8 @@
             if (canReverse()) {
                 mAvd.reverse();
             } else {
-                Log.w(LOGTAG, "Reverse() is called on a drawable can't reverse");
+                Log.w(LOGTAG, "Can't reverse, either the reversible is set to false,"
+                        + " or the AnimatedVectorDrawable can't reverse");
             }
         }
 
@@ -520,8 +544,12 @@
     }
 
     static class AnimatedStateListState extends StateListState {
-        private static final int REVERSE_SHIFT = 32;
-        private static final int REVERSE_MASK = 0x1;
+        // REVERSED_BIT is indicating the current transition's direction.
+        private static final long REVERSED_BIT = 0x100000000l;
+
+        // REVERSIBLE_FLAG_BIT is indicating whether the whole transition has
+        // reversible flag set to true.
+        private static final long REVERSIBLE_FLAG_BIT = 0x200000000l;
 
         int[] mAnimThemeAttrs;
 
@@ -545,11 +573,15 @@
         int addTransition(int fromId, int toId, @NonNull Drawable anim, boolean reversible) {
             final int pos = super.addChild(anim);
             final long keyFromTo = generateTransitionKey(fromId, toId);
-            mTransitions.append(keyFromTo, pos);
+            long reversibleBit = 0;
+            if (reversible) {
+                reversibleBit = REVERSIBLE_FLAG_BIT;
+            }
+            mTransitions.append(keyFromTo, pos | reversibleBit);
 
             if (reversible) {
                 final long keyToFrom = generateTransitionKey(toId, fromId);
-                mTransitions.append(keyToFrom, pos | (1L << REVERSE_SHIFT));
+                mTransitions.append(keyToFrom, pos | REVERSED_BIT | reversibleBit);
             }
 
             return addChild(anim);
@@ -581,7 +613,12 @@
 
         boolean isTransitionReversed(int fromId, int toId) {
             final long keyFromTo = generateTransitionKey(fromId, toId);
-            return (mTransitions.get(keyFromTo, -1) >> REVERSE_SHIFT & REVERSE_MASK) == 1;
+            return (mTransitions.get(keyFromTo, -1) & REVERSED_BIT) != 0;
+        }
+
+        boolean transitionHasReversibleFlag(int fromId, int toId) {
+            final long keyFromTo = generateTransitionKey(fromId, toId);
+            return (mTransitions.get(keyFromTo, -1) & REVERSIBLE_FLAG_BIT) != 0;
         }
 
         @Override
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index d0edeba..e9c8c2a 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -462,19 +462,22 @@
     /**
      * Reverses ongoing animations or starts pending animations in reverse.
      * <p>
-     * NOTE: Only works of all animations are ValueAnimators.
+     * NOTE: Only works if all animations support reverse. Otherwise, this will
+     * do nothing.
      * @hide
      */
     public void reverse() {
+        // Only reverse when all the animators can be reverse. Otherwise, partially
+        // reverse is confusing.
+        if (!canReverse()) {
+            Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
+            return;
+        }
         final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
         final int size = animators.size();
         for (int i = 0; i < size; i++) {
             final Animator animator = animators.get(i);
-            if (animator.canReverse()) {
-                animator.reverse();
-            } else {
-                Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
-            }
+            animator.reverse();
         }
     }
 
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 58ed4f8..9a0266d 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -128,6 +128,29 @@
 
     /**
      * @hide
+     * Return the input channel mask corresponding to an output channel mask.
+     * This can be used for submix rerouting for the mask of the recorder to map to that of the mix.
+     * @param outMask a combination of the CHANNEL_OUT_* definitions, but not CHANNEL_OUT_DEFAULT
+     * @return a combination of CHANNEL_IN_* definitions matching an output channel mask
+     * @throws IllegalArgumentException
+     */
+    public static int inChannelMaskFromOutChannelMask(int outMask) throws IllegalArgumentException {
+        if (outMask == CHANNEL_OUT_DEFAULT) {
+            throw new IllegalArgumentException(
+                    "Illegal CHANNEL_OUT_DEFAULT channel mask for input.");
+        }
+        switch (channelCountFromOutChannelMask(outMask)) {
+            case 1:
+                return CHANNEL_IN_MONO;
+            case 2:
+                return CHANNEL_IN_STEREO;
+            default:
+                throw new IllegalArgumentException("Unsupported channel configuration for input.");
+        }
+    }
+
+    /**
+     * @hide
      * Return the number of channels from an input channel mask
      * @param mask a combination of the CHANNEL_IN_* definitions, even CHANNEL_IN_DEFAULT
      * @return number of channels for the mask
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 255d828..e9dc3af 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -155,6 +155,7 @@
         {
             throw new IllegalArgumentException("Invalid AudioMix: not defined for loop back");
         }
+        // TODO also check mix is defined for playback or recording, and matches forTrack argument
     }
 
     /**
@@ -175,13 +176,19 @@
             return null;
         }
         checkMixReadyToUse(mix, false/*not for an AudioTrack*/);
+        // create an AudioFormat from the mix format compatible with recording, as the mix
+        // was defined for playback
+        AudioFormat mixFormat = new AudioFormat.Builder(mix.getFormat())
+                .setChannelMask(AudioFormat.inChannelMaskFromOutChannelMask(
+                        mix.getFormat().getChannelMask()))
+                .build();
         // create the AudioRecord, configured for loop back, using the same format as the mix
         AudioRecord ar = new AudioRecord(
                 new AudioAttributes.Builder()
                         .setInternalCapturePreset(MediaRecorder.AudioSource.REMOTE_SUBMIX)
                         .addTag(mix.getRegistration())
                         .build(),
-                mix.getFormat(),
+                mixFormat,
                 AudioRecord.getMinBufferSize(mix.getFormat().getSampleRate(),
                         // using stereo for buffer size to avoid the current poor support for masks
                         AudioFormat.CHANNEL_IN_STEREO, mix.getFormat().getEncoding()),
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 51bd205..de9d54f 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1012,6 +1012,12 @@
     /**
      * Returns the TvStreamConfig list of the given TV input.
      *
+     * If you are using {@link Hardware} object from {@link
+     * #acquireTvInputHardware}, you should get the list of available streams
+     * from {@link HardwareCallback#onStreamConfigChanged} method, not from
+     * here. This method is designed to be used with {@link #captureFrame} in
+     * capture scenarios specifically and not suitable for any other use.
+     *
      * @param inputId the id of the TV input.
      * @return List of {@link TvStreamConfig} which is available for capturing
      *   of the given TV input.
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index f9d84c1..6fc1b82 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -18,7 +18,10 @@
 
 import android.annotation.SystemApi;
 import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
+import android.graphics.Region;
 import android.media.tv.TvInputManager.Session;
 import android.media.tv.TvInputManager.Session.FinishedInputEventCallback;
 import android.media.tv.TvInputManager.SessionCallback;
@@ -593,6 +596,42 @@
     }
 
     @Override
+    public boolean gatherTransparentRegion(Region region) {
+        if (mWindowZOrder != ZORDER_ON_TOP) {
+            if (region != null) {
+                int width = getWidth();
+                int height = getHeight();
+                if (width > 0 && height > 0) {
+                    int location[] = new int[2];
+                    getLocationInWindow(location);
+                    int left = location[0];
+                    int top = location[1];
+                    region.op(left, top, left + width, top + height, Region.Op.UNION);
+                }
+            }
+        }
+        return super.gatherTransparentRegion(region);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        if (mWindowZOrder != ZORDER_ON_TOP) {
+            // Punch a hole so that the underlying overlay view and surface can be shown.
+            canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+        }
+        super.draw(canvas);
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        if (mWindowZOrder != ZORDER_ON_TOP) {
+            // Punch a hole so that the underlying overlay view and surface can be shown.
+            canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+        }
+        super.dispatchDraw(canvas);
+    }
+
+    @Override
     protected void onVisibilityChanged(View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
         mSurfaceView.setVisibility(visibility);
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
index 63694a8..00193ed 100644
--- a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
@@ -44,15 +44,21 @@
             android:paddingTop="8dp"
             android:paddingBottom="8dp"
             android:text="Report unlock attempts" />
+    <CheckBox android:id="@+id/report_device_locked"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dp"
+            android:paddingBottom="8dp"
+            android:text="Report device locked or unlocked" />
 
     <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content">
-        <Button android:id="@+id/check_trusted"
+        <Button android:id="@+id/check_device_locked"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:text="Keyguard in trusted state?" />
-        <TextView android:id="@+id/check_trusted_result"
+                android:text="Device locked?" />
+        <TextView android:id="@+id/check_device_locked_result"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:layout_weight="1" />
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 f28d0e4..e6a0dd7 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
@@ -56,6 +56,7 @@
             = "preference.report_unlock_attempts";
     private static final String PREFERENCE_MANAGING_TRUST
             = "preference.managing_trust";
+    private static final String PREFERENCE_REPORT_DEVICE_LOCKED = "preference.report_device_locked";
 
     private static final String TAG = "SampleTrustAgent";
 
@@ -80,17 +81,37 @@
     @Override
     public void onTrustTimeout() {
         super.onTrustTimeout();
-        Toast.makeText(this, "onTrustTimeout(): timeout expired", Toast.LENGTH_SHORT).show();
+        logAndShowToast("onTrustTimeout(): timeout expired");
+    }
+
+    @Override
+    public void onDeviceLocked() {
+        super.onDeviceLocked();
+        if (getReportDeviceLocked(this)) {
+            logAndShowToast("onDeviceLocked(): device is now locked");
+        }
+    }
+
+    @Override
+    public void onDeviceUnlocked() {
+        super.onDeviceUnlocked();
+        if (getReportDeviceLocked(this)) {
+            logAndShowToast("onDeviceUnlocked(): device is now unlocked");
+        }
     }
 
     @Override
     public void onUnlockAttempt(boolean successful) {
         if (getReportUnlockAttempts(this)) {
-            Toast.makeText(this, "onUnlockAttempt(successful=" + successful + ")",
-                    Toast.LENGTH_SHORT).show();
+            logAndShowToast("onUnlockAttempt(successful=" + successful + ")");
         }
     }
 
+    private void logAndShowToast(String text) {
+        Log.i(TAG, text);
+        Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
+    }
+
     @Override
     public boolean onConfigure(List<PersistableBundle> options) {
         if (options != null) {
@@ -125,8 +146,7 @@
                             intent.getLongExtra(EXTRA_DURATION, 0),
                             intent.getBooleanExtra(EXTRA_INITIATED_BY_USER, false));
                 } catch (IllegalStateException e) {
-                    Toast.makeText(context,
-                            "IllegalStateException: " + e.getMessage(), Toast.LENGTH_SHORT).show();
+                    logAndShowToast("IllegalStateException: " + e.getMessage());
                 }
             } else if (ACTION_REVOKE_TRUST.equals(action)) {
                 revokeTrust();
@@ -160,6 +180,18 @@
         return sharedPreferences.getBoolean(PREFERENCE_REPORT_UNLOCK_ATTEMPTS, false);
     }
 
+    public static void setReportDeviceLocked(Context context, boolean enabled) {
+        SharedPreferences sharedPreferences = PreferenceManager
+                .getDefaultSharedPreferences(context);
+        sharedPreferences.edit().putBoolean(PREFERENCE_REPORT_DEVICE_LOCKED, enabled).apply();
+    }
+
+    public static boolean getReportDeviceLocked(Context context) {
+        SharedPreferences sharedPreferences = PreferenceManager
+                .getDefaultSharedPreferences(context);
+        return sharedPreferences.getBoolean(PREFERENCE_REPORT_DEVICE_LOCKED, false);
+    }
+
     public static void setIsManagingTrust(Context context, boolean enabled) {
         SharedPreferences sharedPreferences = PreferenceManager
                 .getDefaultSharedPreferences(context);
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
index 39a599e..29b15cb 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
@@ -31,8 +31,9 @@
     private static final int TRUST_DURATION_MS = 30 * 1000;
 
     private CheckBox mReportUnlockAttempts;
+    private CheckBox mReportDeviceLocked;
     private CheckBox mManagingTrust;
-    private TextView mCheckTrustedStateResult;
+    private TextView mCheckDeviceLockedResult;
 
     private KeyguardManager mKeyguardManager;
 
@@ -48,15 +49,18 @@
         findViewById(R.id.enable_trust).setOnClickListener(this);
         findViewById(R.id.revoke_trust).setOnClickListener(this);
         findViewById(R.id.crash).setOnClickListener(this);
-        findViewById(R.id.check_trusted).setOnClickListener(this);
+        findViewById(R.id.check_device_locked).setOnClickListener(this);
 
         mReportUnlockAttempts = (CheckBox) findViewById(R.id.report_unlock_attempts);
         mReportUnlockAttempts.setOnCheckedChangeListener(this);
 
+        mReportDeviceLocked = (CheckBox) findViewById(R.id.report_device_locked);
+        mReportDeviceLocked.setOnCheckedChangeListener(this);
+
         mManagingTrust = (CheckBox) findViewById(R.id.managing_trust);
         mManagingTrust.setOnCheckedChangeListener(this);
 
-        mCheckTrustedStateResult = (TextView) findViewById(R.id.check_trusted_result);
+        mCheckDeviceLockedResult = (TextView) findViewById(R.id.check_device_locked_result);
     }
 
     @Override
@@ -77,7 +81,7 @@
             SampleTrustAgent.sendRevokeTrust(this);
         } else if (id == R.id.crash) {
             throw new RuntimeException("crash");
-        } else if (id == R.id.check_trusted) {
+        } else if (id == R.id.check_device_locked) {
             updateTrustedState();
         }
     }
@@ -88,11 +92,13 @@
             SampleTrustAgent.setReportUnlockAttempts(this, isChecked);
         } else if (buttonView == mManagingTrust) {
             SampleTrustAgent.setIsManagingTrust(this, isChecked);
+        } else if (buttonView == mReportDeviceLocked) {
+            SampleTrustAgent.setReportDeviceLocked(this, isChecked);
         }
     }
 
     private void updateTrustedState() {
-        mCheckTrustedStateResult.setText(Boolean.toString(
-                mKeyguardManager.isKeyguardInTrustedState()));
+        mCheckDeviceLockedResult.setText(Boolean.toString(
+                mKeyguardManager.isDeviceLocked()));
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 20e418c..5f92dc6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -23,6 +23,7 @@
 import android.app.PendingIntent;
 import android.app.SearchManager;
 import android.app.StatusBarManager;
+import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -187,8 +188,9 @@
     /** High level access to the window manager for dismissing keyguard animation */
     private IWindowManager mWM;
 
-    /** UserManager for querying number of users */
-    private UserManager mUserManager;
+
+    /** TrustManager for letting it know when we change visibility */
+    private TrustManager mTrustManager;
 
     /** SearchManager for determining whether or not search assistant is available */
     private SearchManager mSearchManager;
@@ -484,7 +486,8 @@
     private void setup() {
         mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWM = WindowManagerGlobal.getWindowManagerService();
-        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
+
         mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
         mShowKeyguardWakeLock.setReferenceCounted(false);
 
@@ -501,6 +504,7 @@
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure...
         mShowing = !shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled();
+        mTrustManager.reportKeyguardShowingChanged();
 
         mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
                 mViewMediatorCallback, mLockPatternUtils);
@@ -931,7 +935,7 @@
         if (mLockPatternUtils.checkVoldPassword()) {
             if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
             // Without this, settings is not enabled until the lock screen first appears
-            mShowing = false;
+            setShowing(false);
             hideLocked();
             return;
         }
@@ -1249,7 +1253,7 @@
 
             mStatusBarKeyguardViewManager.show(options);
             mHiding = false;
-            mShowing = true;
+            setShowing(true);
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false;
             updateActivityLockScreenState();
@@ -1328,7 +1332,7 @@
             }
 
             mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
-            mShowing = false;
+            setShowing(false);
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false;
             updateActivityLockScreenState();
@@ -1389,7 +1393,7 @@
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
             mStatusBarKeyguardViewManager.verifyUnlock();
-            mShowing = true;
+            setShowing(true);
             updateActivityLockScreenState();
         }
     }
@@ -1471,4 +1475,12 @@
             this.fadeoutDuration = fadeoutDuration;
         }
     }
+
+    private void setShowing(boolean showing) {
+        boolean changed = (showing != mShowing);
+        mShowing = showing;
+        if (changed) {
+            mTrustManager.reportKeyguardShowingChanged();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index bb9a105..38ce467 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -32,6 +32,7 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.os.Handler;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Pair;
 import android.view.LayoutInflater;
@@ -361,8 +362,7 @@
         // If the user has toggled it too quickly, then just eat up the event here (it's better than
         // showing a janky screenshot).
         // NOTE: Ideally, the screenshot mechanism would take the window transform into account
-        long currentTime = System.currentTimeMillis();
-        if ((currentTime > mLastToggleTime) && (currentTime - mLastToggleTime) < sMinToggleDelay) {
+        if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) {
             return;
         }
 
@@ -377,7 +377,7 @@
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
                     Intent.FLAG_RECEIVER_FOREGROUND);
             mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
-            mLastToggleTime = System.currentTimeMillis();
+            mLastToggleTime = SystemClock.elapsedRealtime();
             return;
         } else {
             // Otherwise, start the recents activity
@@ -559,7 +559,7 @@
                 startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_HOME, stackVr);
             }
         }
-        mLastToggleTime = System.currentTimeMillis();
+        mLastToggleTime = SystemClock.elapsedRealtime();
     }
 
     /** Starts the recents activity */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 676f1ab..6dc2edb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -28,6 +28,7 @@
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.os.Bundle;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Pair;
 import android.view.KeyEvent;
@@ -564,13 +565,13 @@
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         switch (keyCode) {
             case KeyEvent.KEYCODE_TAB: {
-                boolean hasRepKeyTimeElapsed = (System.currentTimeMillis() -
+                boolean hasRepKeyTimeElapsed = (SystemClock.elapsedRealtime() -
                         mLastTabKeyEventTime) > mConfig.altTabKeyDelay;
                 if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
                     // Focus the next task in the stack
                     final boolean backward = event.isShiftPressed();
                     mRecentsView.focusNextTask(!backward);
-                    mLastTabKeyEventTime = System.currentTimeMillis();
+                    mLastTabKeyEventTime = SystemClock.elapsedRealtime();
                 }
                 return true;
             }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 17889ea..c26df02 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3839,9 +3839,8 @@
             int notificationType) {
         if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE) {
             Intent intent = new Intent();
-            intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST_NETWORK, nri.request);
-            intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST_NETWORK_REQUEST,
-                    networkAgent.network);
+            intent.putExtra(ConnectivityManager.EXTRA_NETWORK, nri.request);
+            intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, networkAgent.network);
             sendIntent(nri.mPendingIntent, intent);
         }
         // else not handled
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 4906bd1..57b204d 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -232,6 +232,12 @@
             mTrustManagerService.mArchive.logAgentConnected(mUserId, name);
             setCallback(mCallback);
             updateDevicePolicyFeatures();
+
+            if (mTrustManagerService.isDeviceLockedInner(mUserId)) {
+                onDeviceLocked();
+            } else {
+                onDeviceUnlocked();
+            }
         }
 
         @Override
@@ -287,6 +293,7 @@
             onError(e);
         }
     }
+
     /**
      * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean)
      */
@@ -298,6 +305,28 @@
         }
     }
 
+    /**
+     * @see android.service.trust.TrustAgentService#onDeviceLocked()
+     */
+    public void onDeviceLocked() {
+        try {
+            if (mTrustAgentService != null) mTrustAgentService.onDeviceLocked();
+        } catch (RemoteException e) {
+            onError(e);
+        }
+    }
+
+    /**
+     * @see android.service.trust.TrustAgentService#onDeviceUnlocked()
+     */
+    public void onDeviceUnlocked() {
+        try {
+            if (mTrustAgentService != null) mTrustAgentService.onDeviceUnlocked();
+        } catch (RemoteException e) {
+            onError(e);
+        }
+    }
+
     private void setCallback(ITrustAgentServiceCallback callback) {
         try {
             if (mTrustAgentService != null) {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 2388c85..a2ea1c8 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -26,7 +26,6 @@
 
 import android.Manifest;
 import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.ITrustListener;
 import android.app.trust.ITrustManager;
@@ -61,6 +60,8 @@
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.Xml;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -96,6 +97,10 @@
     private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
     private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
     private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
+    private static final int MSG_KEYGUARD_SHOWING_CHANGED = 6;
+    private static final int MSG_START_USER = 7;
+    private static final int MSG_CLEANUP_USER = 8;
+    private static final int MSG_SWITCH_USER = 9;
 
     private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
     private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
@@ -110,7 +115,11 @@
     @GuardedBy("mUserIsTrusted")
     private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
 
+    @GuardedBy("mDeviceLockedForUser")
+    private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
+
     private boolean mTrustAgentsCanRun = false;
+    private int mCurrentUser = UserHandle.USER_OWNER;
 
     public TrustManagerService(Context context) {
         super(context);
@@ -177,10 +186,15 @@
     public void updateTrust(int userId, boolean initiatedByUser) {
         dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
         boolean trusted = aggregateIsTrusted(userId);
+        boolean changed;
         synchronized (mUserIsTrusted) {
+            changed = mUserIsTrusted.get(userId) != trusted;
             mUserIsTrusted.put(userId, trusted);
         }
         dispatchOnTrustChanged(trusted, userId, initiatedByUser);
+        if (changed) {
+            refreshDeviceLockedForUser(userId);
+        }
     }
 
     void refreshAgentList(int userId) {
@@ -212,8 +226,7 @@
                     || userInfo.guestToRemove) continue;
             if (!userInfo.supportsSwitchTo()) continue;
             if (!mActivityManager.isUserRunning(userInfo.id)) continue;
-            if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
-                    == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
+            if (!lockPatternUtils.isSecure(userInfo.id)) continue;
             if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
             DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
             int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
@@ -273,6 +286,73 @@
         }
     }
 
+    boolean isDeviceLockedInner(int userId) {
+        synchronized (mDeviceLockedForUser) {
+            return mDeviceLockedForUser.get(userId, true);
+        }
+    }
+
+    private void refreshDeviceLockedForUser(int userId) {
+        if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
+            Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
+                    + " must be USER_ALL or a specific user.", new Throwable("here"));
+            userId = UserHandle.USER_ALL;
+        }
+
+        List<UserInfo> userInfos;
+        if (userId == UserHandle.USER_ALL) {
+            userInfos = mUserManager.getUsers(true /* excludeDying */);
+        } else {
+            userInfos = new ArrayList<>();
+            userInfos.add(mUserManager.getUserInfo(userId));
+        }
+
+        IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+
+        for (int i = 0; i < userInfos.size(); i++) {
+            UserInfo info = userInfos.get(i);
+
+            if (info == null || info.partial || !info.isEnabled() || info.guestToRemove
+                    || !info.supportsSwitchTo()) {
+                continue;
+            }
+
+            int id = info.id;
+            boolean secure = mLockPatternUtils.isSecure(id);
+            boolean trusted = aggregateIsTrusted(id);
+            boolean showingKeyguard = true;
+            if (mCurrentUser == id) {
+                try {
+                    showingKeyguard = wm.isKeyguardLocked();
+                } catch (RemoteException e) {
+                }
+            }
+            boolean deviceLocked = secure && showingKeyguard && !trusted;
+
+            boolean changed;
+            synchronized (mDeviceLockedForUser) {
+                changed = isDeviceLockedInner(id) != deviceLocked;
+                mDeviceLockedForUser.put(id, deviceLocked);
+            }
+            if (changed) {
+                dispatchDeviceLocked(id, deviceLocked);
+            }
+        }
+    }
+
+    private void dispatchDeviceLocked(int userId, boolean isLocked) {
+        for (int i = 0; i < mActiveAgents.size(); i++) {
+            AgentInfo agent = mActiveAgents.valueAt(i);
+            if (agent.userId == userId) {
+                if (isLocked) {
+                    agent.agent.onDeviceLocked();
+                } else{
+                    agent.agent.onDeviceUnlocked();
+                }
+            }
+        }
+    }
+
     void updateDevicePolicyFeatures() {
         for (int i = 0; i < mActiveAgents.size(); i++) {
             AgentInfo info = mActiveAgents.valueAt(i);
@@ -540,12 +620,17 @@
 
     @Override
     public void onStartUser(int userId) {
-        refreshAgentList(userId);
+        mHandler.obtainMessage(MSG_START_USER, userId, 0, null).sendToTarget();
     }
 
     @Override
     public void onCleanupUser(int userId) {
-        refreshAgentList(userId);
+        mHandler.obtainMessage(MSG_CLEANUP_USER, userId, 0, null).sendToTarget();
+    }
+
+    @Override
+    public void onSwitchUser(int userId) {
+        mHandler.obtainMessage(MSG_SWITCH_USER, userId, 0, null).sendToTarget();
     }
 
     // Plumbing
@@ -578,6 +663,14 @@
         }
 
         @Override
+        public void reportKeyguardShowingChanged() throws RemoteException {
+            enforceReportPermission();
+            // coalesce refresh messages.
+            mHandler.removeMessages(MSG_KEYGUARD_SHOWING_CHANGED);
+            mHandler.sendEmptyMessage(MSG_KEYGUARD_SHOWING_CHANGED);
+        }
+
+        @Override
         public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
             enforceListenerPermission();
             mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
@@ -590,13 +683,12 @@
         }
 
         @Override
-        public boolean isTrusted(int userId) throws RemoteException {
+        public boolean isDeviceLocked(int userId) throws RemoteException {
             userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
-                    false /* allowAll */, true /* requireFull */, "isTrusted", null);
+                    false /* allowAll */, true /* requireFull */, "isDeviceLocked", null);
             userId = resolveProfileParent(userId);
-            synchronized (mUserIsTrusted) {
-                return mUserIsTrusted.get(userId);
-            }
+
+            return isDeviceLockedInner(userId);
         }
 
         private void enforceReportPermission() {
@@ -621,19 +713,13 @@
                 fout.println("disabled because the third-party apps can't run yet.");
                 return;
             }
-            final UserInfo currentUser;
             final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
-            try {
-                currentUser = ActivityManagerNative.getDefault().getCurrentUser();
-            } catch (RemoteException e) {
-                throw new RuntimeException(e);
-            }
             mHandler.runWithScissors(new Runnable() {
                 @Override
                 public void run() {
                     fout.println("Trust manager state:");
                     for (UserInfo user : userInfos) {
-                        dumpUser(fout, user, user.id == currentUser.id);
+                        dumpUser(fout, user, user.id == mCurrentUser);
                     }
                 }
             }, 1500);
@@ -642,11 +728,17 @@
         private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
             fout.printf(" User \"%s\" (id=%d, flags=%#x)",
                     user.name, user.id, user.flags);
+            if (!user.supportsSwitchTo()) {
+                fout.println("(managed profile)");
+                fout.println("   disabled because switching to this user is not possible.");
+                return;
+            }
             if (isCurrent) {
                 fout.print(" (current)");
             }
             fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
             fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
+            fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
             fout.println();
             fout.println("   Enabled agents:");
             boolean duplicateSimpleNames = false;
@@ -711,10 +803,23 @@
                     break;
                 case MSG_ENABLED_AGENTS_CHANGED:
                     refreshAgentList(UserHandle.USER_ALL);
+                    // This is also called when the security mode of a user changes.
+                    refreshDeviceLockedForUser(UserHandle.USER_ALL);
                     break;
                 case MSG_REQUIRE_CREDENTIAL_ENTRY:
                     requireCredentialEntry(msg.arg1);
                     break;
+                case MSG_KEYGUARD_SHOWING_CHANGED:
+                    refreshDeviceLockedForUser(UserHandle.USER_CURRENT);
+                    break;
+                case MSG_START_USER:
+                case MSG_CLEANUP_USER:
+                    refreshAgentList(msg.arg1);
+                    break;
+                case MSG_SWITCH_USER:
+                    mCurrentUser = msg.arg1;
+                    refreshDeviceLockedForUser(UserHandle.USER_ALL);
+                    break;
             }
         }
     };
@@ -756,8 +861,14 @@
                 int userId = getUserId(intent);
                 if (userId > 0) {
                     mUserHasAuthenticatedSinceBoot.delete(userId);
-                    mUserIsTrusted.delete(userId);
+                    synchronized (mUserIsTrusted) {
+                        mUserIsTrusted.delete(userId);
+                    }
+                    synchronized (mDeviceLockedForUser) {
+                        mDeviceLockedForUser.delete(userId);
+                    }
                     refreshAgentList(userId);
+                    refreshDeviceLockedForUser(userId);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index c3cbbd3..716487c 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -681,7 +681,7 @@
                     throw new IllegalStateException("Device already released.");
                 }
 
-                int result = TvInputHal.ERROR_UNKNOWN;
+                int result = TvInputHal.SUCCESS;
                 if (surface == null) {
                     // The value of config is ignored when surface == null.
                     if (mActiveConfig != null) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 1086eb2..f859fd2 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -254,15 +254,18 @@
 
     @Override
     void removeAllWindows() {
-        int winNdx;
-        while ((winNdx = allAppWindows.size()) > 0) {
-            WindowState win = allAppWindows.get(winNdx - 1);
+        for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;
+                // removeWindowLocked at bottom of loop may remove multiple entries from
+                // allAppWindows if the window to be removed has child windows. It also may
+                // not remove any windows from allAppWindows at all if win is exiting and
+                // currently animating away. This ensures that winNdx is monotonically decreasing
+                // and never beyond allAppWindows bounds.
+                winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
+            WindowState win = allAppWindows.get(winNdx);
             if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) {
                 Slog.w(WindowManagerService.TAG, "removeAllWindows: removing win=" + win);
             }
 
-            // {@link WindowManagerService.removeWindowLocked} may remove multiple entries from
-            // {@link #allAppWindows} if the window to be removed has child windows.
             win.mService.removeWindowLocked(win.mSession, win);
         }
     }
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index c63eb18..23ba3b6 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -209,8 +209,13 @@
         mUseUsbNotification = !massStorageSupported;
 
         // make sure the ADB_ENABLED setting value matches the current state
-        Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
-
+        try {
+            Settings.Global.putInt(mContentResolver,
+                    Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
+        } catch (SecurityException e) {
+            // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed.
+            Slog.d(TAG, "ADB_ENABLED is restricted.");
+        }
         mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
     }
 
diff --git a/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml b/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml
index 8d82d05..8ab79a5 100644
--- a/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml
+++ b/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml
@@ -15,12 +15,8 @@
      limitations under the License.
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <objectAnimator
-        android:duration="3300"
-        android:propertyName="rotation"
-        android:valueFrom="0"
-        android:valueTo="360"
-        android:repeatCount="-1" />
-</set>
\ No newline at end of file
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:duration="3300"
+    android:propertyName="rotation"
+    android:valueFrom="0"
+    android:valueTo="450" />
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.xml b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.xml
new file mode 100644
index 0000000..a0a801c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.xml
@@ -0,0 +1,26 @@
+<!--
+ 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-selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/on" android:state_checked="true"
+        android:drawable="@drawable/vector_drawable_favorite" />
+    <item android:id="@+id/off"
+        android:drawable="@drawable/vector_drawable_favorite" />
+    <transition android:fromId="@+id/off" android:toId="@+id/on"
+        android:drawable="@drawable/animation_drawable_vector"
+        android:reversible="true">
+    </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml
new file mode 100644
index 0000000..3cf8e48
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml
@@ -0,0 +1,26 @@
+<!--
+ 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-selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/on" android:state_checked="true"
+        android:drawable="@drawable/vector_drawable_favorite" />
+    <item android:id="@+id/off" android:state_checked="false"
+        android:drawable="@drawable/vector_drawable_favorite" />
+    <transition android:fromId="@+id/off" android:toId="@+id/on"
+        android:drawable="@drawable/animation_drawable_vector"
+        android:reversible="false">
+    </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
index 18d7755..768fe39 100644
--- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
@@ -17,7 +17,7 @@
 <animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/on" android:state_checked="true"
         android:drawable="@drawable/vector_drawable12" />
-    <item android:id="@+id/off"
+    <item android:id="@+id/off" android:state_checked="false"
         android:drawable="@drawable/vector_drawable12" />
     <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="true">
         <animated-vector android:drawable="@drawable/vector_drawable12">
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml
new file mode 100644
index 0000000..96d378c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml
@@ -0,0 +1,47 @@
+<!--
+ 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-selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/on" android:state_checked="true"
+        android:drawable="@drawable/vector_drawable12" />
+    <item android:id="@+id/off" android:state_checked="false"
+        android:drawable="@drawable/vector_drawable12" />
+    <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="false">
+        <animated-vector android:drawable="@drawable/vector_drawable12">
+            <target
+                android:name="pie1"
+                android:animation="@anim/trim_path_animation01" />
+            <target
+                android:name="v"
+                android:animation="@anim/trim_path_animation02" />
+            <target
+                android:name="v"
+                android:animation="@anim/trim_path_animation05" />
+            <target
+                android:name="rotationGroup"
+                android:animation="@anim/trim_path_animation03" />
+            <target
+                android:name="rotationGroup3"
+                android:animation="@anim/trim_path_animation03" />
+            <target
+                android:name="rotationGroupBlue"
+                android:animation="@anim/trim_path_animation03" />
+            <target
+                android:name="rotationGroup"
+                android:animation="@anim/trim_path_animation04" />
+        </animated-vector>
+    </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml
new file mode 100644
index 0000000..b722da1
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml
@@ -0,0 +1,26 @@
+<!--
+ 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-selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/on" android:state_checked="true"
+        android:drawable="@drawable/vector_drawable_grouping_1" />
+    <item android:id="@+id/off" android:state_checked="false"
+        android:drawable="@drawable/vector_drawable_grouping_1" />
+    <transition android:fromId="@+id/off" android:toId="@+id/on"
+        android:drawable="@drawable/animation_vector_drawable_grouping_1"
+        android:reversible="false">
+    </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
index 65cf25b..e24dd1f 100644
--- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
@@ -17,7 +17,7 @@
 <animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/on" android:state_checked="true"
         android:drawable="@drawable/vector_drawable_favorite" />
-    <item android:id="@+id/off"
+    <item android:id="@+id/off" android:state_checked="false"
         android:drawable="@drawable/vector_drawable_favorite" />
     <transition android:fromId="@+id/off" android:toId="@+id/on"
         android:drawable="@drawable/animation_vector_drawable_favorite"
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml
new file mode 100644
index 0000000..e788bc2
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml
@@ -0,0 +1,26 @@
+<!--
+ 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-selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/on" android:state_checked="true"
+        android:drawable="@drawable/vector_drawable_favorite" />
+    <item android:id="@+id/off" android:state_checked="false"
+        android:drawable="@drawable/vector_drawable_favorite" />
+    <transition android:fromId="@+id/off" android:toId="@+id/on"
+        android:drawable="@drawable/animation_vector_drawable_favorite"
+        android:reversible="false">
+    </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
index 566cc4b..5386555 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
@@ -27,9 +27,16 @@
     private static final String LOGCAT = "AnimatedStateVectorDrawableTest";
 
     protected int[] icon = {
+            // These shows pairs of ASLD , the left side set the reversible to true.
+            // the right side set to false.
             R.drawable.state_animation_vector_drawable01,
+            R.drawable.state_animation_vector_drawable01_false,
             R.drawable.state_animation_vector_drawable02,
+            R.drawable.state_animation_vector_drawable02_false,
             R.drawable.state_animation_vector_drawable03,
+            R.drawable.state_animation_vector_drawable03_false,
+            R.drawable.state_animation_drawable04,
+            R.drawable.state_animation_drawable04_false,
     };
 
     @Override
@@ -39,7 +46,7 @@
         ScrollView scrollView = new ScrollView(this);
         GridLayout container = new GridLayout(this);
         scrollView.addView(container);
-        container.setColumnCount(5);
+        container.setColumnCount(2);
 
         for (int i = 0; i < icon.length; i++) {
             CheckBox button = new CheckBox(this);