Merge "Work on issue #22303510: Additional permissions aren't properly..." into mnc-dev
diff --git a/Android.mk b/Android.mk
index 121bc8e..a7a2ecb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -285,7 +285,7 @@
 	core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
 	core/java/com/android/internal/backup/IBackupTransport.aidl \
 	core/java/com/android/internal/backup/IObbBackupService.aidl \
-	core/java/com/android/internal/policy/IKeyguardShowCallback.aidl \
+	core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl \
 	core/java/com/android/internal/policy/IKeyguardExitCallback.aidl \
 	core/java/com/android/internal/policy/IKeyguardService.aidl \
 	core/java/com/android/internal/policy/IKeyguardStateCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index c70fbc9..741ff9b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28826,6 +28826,7 @@
     method public void onHandleAssist(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent);
     method public void onHandleScreenshot(android.graphics.Bitmap);
     method public void onHide();
+    method public void onLockscreenShown();
     method public boolean onKeyDown(int, android.view.KeyEvent);
     method public boolean onKeyLongPress(int, android.view.KeyEvent);
     method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
diff --git a/api/system-current.txt b/api/system-current.txt
index 427bdb3..4c2d7b1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -30978,6 +30978,7 @@
     method public void onHandleAssist(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent);
     method public void onHandleScreenshot(android.graphics.Bitmap);
     method public void onHide();
+    method public void onLockscreenShown();
     method public boolean onKeyDown(int, android.view.KeyEvent);
     method public boolean onKeyLongPress(int, android.view.KeyEvent);
     method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 9f4bc52..d952dfc 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -26,6 +26,7 @@
 import android.app.IActivityManager;
 import android.app.IInstrumentationWatcher;
 import android.app.Instrumentation;
+import android.app.IStopUserCallback;
 import android.app.ProfilerInfo;
 import android.app.UiAutomationConnection;
 import android.app.usage.ConfigurationStats;
@@ -133,7 +134,7 @@
                 "       am to-app-uri [INTENT]\n" +
                 "       am switch-user <USER_ID>\n" +
                 "       am start-user <USER_ID>\n" +
-                "       am stop-user <USER_ID>\n" +
+                "       am stop-user [-w] <USER_ID>\n" +
                 "       am stack start <DISPLAY_ID> <INTENT>\n" +
                 "       am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
                 "       am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
@@ -257,6 +258,7 @@
                 "\n" +
                 "am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
                 "  code until a later explicit start or switch to it.\n" +
+                "  -w: wait for stop-user to complete.\n" +
                 "\n" +
                 "am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" +
                 "\n" +
@@ -1303,9 +1305,45 @@
         }
     }
 
+    private static class StopUserCallback extends IStopUserCallback.Stub {
+        private boolean mFinished = false;
+
+        public synchronized void waitForFinish() {
+            try {
+                while (!mFinished) wait();
+            } catch (InterruptedException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        @Override
+        public synchronized void userStopped(int userId) {
+            mFinished = true;
+            notifyAll();
+        }
+
+        @Override
+        public synchronized void userStopAborted(int userId) {
+            mFinished = true;
+            notifyAll();
+        }
+    }
+
     private void runStopUser() throws Exception {
-        String user = nextArgRequired();
-        int res = mAm.stopUser(Integer.parseInt(user), null);
+        boolean wait = false;
+        String opt = null;
+        while ((opt = nextOption()) != null) {
+            if ("-w".equals(opt)) {
+                wait = true;
+            } else {
+                System.err.println("Error: unknown option: " + opt);
+                return;
+            }
+        }
+        int user = Integer.parseInt(nextArgRequired());
+        StopUserCallback callback = wait ? new StopUserCallback() : null;
+
+        int res = mAm.stopUser(user, callback);
         if (res != ActivityManager.USER_OP_SUCCESS) {
             String txt = "";
             switch (res) {
@@ -1317,6 +1355,8 @@
                     break;
             }
             System.err.println("Switch failed: " + res + txt);
+        } else if (callback != null) {
+            callback.waitForFinish();
         }
     }
 
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 2dcd9cb..b39376c 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -16,6 +16,11 @@
 
 package com.android.commands.pm;
 
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
+
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
@@ -212,6 +217,14 @@
             return runSetPermissionEnforced();
         }
 
+        if ("set-app-link".equals(op)) {
+            return runSetAppLink();
+        }
+
+        if ("get-app-link".equals(op)) {
+            return runGetAppLink();
+        }
+
         if ("set-install-location".equals(op)) {
             return runSetInstallLocation();
         }
@@ -827,6 +840,148 @@
         return Integer.toString(result);
     }
 
+    // pm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}
+    private int runSetAppLink() {
+        int userId = UserHandle.USER_OWNER;
+
+        String opt;
+        while ((opt = nextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = Integer.parseInt(nextOptionData());
+                if (userId < 0) {
+                    System.err.println("Error: user must be >= 0");
+                    return 1;
+                }
+            } else {
+                System.err.println("Error: unknown option: " + opt);
+                showUsage();
+                return 1;
+            }
+        }
+
+        // Package name to act on; required
+        final String pkg = nextArg();
+        if (pkg == null) {
+            System.err.println("Error: no package specified.");
+            showUsage();
+            return 1;
+        }
+
+        // State to apply; {always|ask|never|undefined}, required
+        final String modeString = nextArg();
+        if (modeString == null) {
+            System.err.println("Error: no app link state specified.");
+            showUsage();
+            return 1;
+        }
+
+        final int newMode;
+        switch (modeString.toLowerCase()) {
+            case "undefined":
+                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+                break;
+
+            case "always":
+                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+                break;
+
+            case "ask":
+                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
+                break;
+
+            case "never":
+                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
+                break;
+
+            default:
+                System.err.println("Error: unknown app link state '" + modeString + "'");
+                return 1;
+        }
+
+        try {
+            final PackageInfo info = mPm.getPackageInfo(pkg, 0, userId);
+            if (info == null) {
+                System.err.println("Error: package " + pkg + " not found.");
+                return 1;
+            }
+
+            if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
+                System.err.println("Error: package " + pkg + " does not handle web links.");
+                return 1;
+            }
+
+            if (!mPm.updateIntentVerificationStatus(pkg, newMode, userId)) {
+                System.err.println("Error: unable to update app link status for " + pkg);
+                return 1;
+            }
+        } catch (Exception e) {
+            System.err.println(e.toString());
+            System.err.println(PM_NOT_RUNNING_ERR);
+            return 1;
+        }
+
+        return 0;
+    }
+
+    // pm get-app-link [--user USER_ID] PACKAGE
+    private int runGetAppLink() {
+        int userId = UserHandle.USER_OWNER;
+
+        String opt;
+        while ((opt = nextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = Integer.parseInt(nextOptionData());
+                if (userId < 0) {
+                    System.err.println("Error: user must be >= 0");
+                    return 1;
+                }
+            } else {
+                System.err.println("Error: unknown option: " + opt);
+                showUsage();
+                return 1;
+            }
+        }
+
+        // Package name to act on; required
+        final String pkg = nextArg();
+        if (pkg == null) {
+            System.err.println("Error: no package specified.");
+            showUsage();
+            return 1;
+        }
+
+        try {
+            final PackageInfo info = mPm.getPackageInfo(pkg, 0, userId);
+            if (info == null) {
+                System.err.println("Error: package " + pkg + " not found.");
+                return 1;
+            }
+
+            if ((info.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) == 0) {
+                System.err.println("Error: package " + pkg + " does not handle web links.");
+                return 1;
+            }
+
+            System.out.println(linkStateToString(mPm.getIntentVerificationStatus(pkg, userId)));
+        } catch (Exception e) {
+            System.err.println(e.toString());
+            System.err.println(PM_NOT_RUNNING_ERR);
+            return 1;
+        }
+
+        return 0;
+    }
+
+    private String linkStateToString(int state) {
+        switch (state) {
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: return "undefined";
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
+        }
+        return "Unknown link state: " + state;
+    }
+
     private int runSetInstallLocation() {
         int loc;
 
@@ -1936,6 +2091,8 @@
         System.err.println("       pm grant [--user USER_ID] PACKAGE PERMISSION");
         System.err.println("       pm revoke [--user USER_ID] PACKAGE PERMISSION");
         System.err.println("       pm reset-permissions");
+        System.err.println("       pm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}");
+        System.err.println("       pm get-app-link [--user USER_ID] PACKAGE");
         System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
         System.err.println("       pm get-install-location");
         System.err.println("       pm set-permission-enforced PERMISSION [true|false]");
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 13030ca..84cbea9 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -1094,8 +1094,10 @@
                         container.getViewTreeObserver().removeOnPreDrawListener(this);
 
                         // Don't include any newly-hidden fragments in the transition.
-                        excludeHiddenFragments(hiddenFragmentViews, inFragment.mContainerId,
-                                overallTransition);
+                        if (inFragment != null) {
+                            excludeHiddenFragments(hiddenFragmentViews, inFragment.mContainerId,
+                                    overallTransition);
+                        }
 
                         ArrayMap<String, View> namedViews = null;
                         if (sharedElementTransition != null) {
@@ -1692,7 +1694,7 @@
 
     private static void setNameOverrides(TransitionState state, ArrayList<String> sourceNames,
             ArrayList<String> targetNames) {
-        if (sourceNames != null) {
+        if (sourceNames != null && targetNames != null) {
             for (int i = 0; i < sourceNames.size(); i++) {
                 String source = sourceNames.get(i);
                 String target = targetNames.get(i);
@@ -1703,7 +1705,9 @@
 
     private void setBackNameOverrides(TransitionState state, ArrayMap<String, View> namedViews,
             boolean isEnd) {
-        int count = mSharedElementTargetNames == null ? 0 : mSharedElementTargetNames.size();
+        int targetCount = mSharedElementTargetNames == null ? 0 : mSharedElementTargetNames.size();
+        int sourceCount = mSharedElementSourceNames == null ? 0 : mSharedElementSourceNames.size();
+        final int count = Math.min(targetCount, sourceCount);
         for (int i = 0; i < count; i++) {
             String source = mSharedElementSourceNames.get(i);
             String originalTarget = mSharedElementTargetNames.get(i);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index c5f142a..ee37047 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -321,6 +321,14 @@
          * Called when a fingerprint is valid but not recognized.
          */
         public void onAuthenticationFailed() { }
+
+        /**
+         * Called when a fingerprint image has been acquired, but wasn't processed yet.
+         *
+         * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants
+         * @hide
+         */
+        public void onAuthenticationAcquired(int acquireInfo) {}
     };
 
     /**
@@ -737,9 +745,13 @@
         }
 
         private void sendAcquiredResult(long deviceId, int acquireInfo) {
+            if (mAuthenticationCallback != null) {
+                mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
+            }
             final String msg = getAcquiredString(acquireInfo);
-            if (msg == null) return;
-
+            if (msg == null) {
+                return;
+            }
             if (mEnrollmentCallback != null) {
                 mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg);
             } else if (mAuthenticationCallback != null) {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index b104135..79fb805 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -45,7 +45,9 @@
     private final Context mContext;
 
     /**
-     * Specifies if a user is disallowed from adding and removing accounts.
+     * Specifies if a user is disallowed from adding and removing accounts, unless they are
+     * {@link android.accounts.AccountManager#addAccountExplicitly programmatically} added by
+     * Authenticator.
      * The default value is <code>false</code>.
      *
      * <p/>Key for user restrictions.
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index bae5455..04d5952 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -51,6 +51,7 @@
     public static final int KM_TAG_DIGEST = KM_ENUM_REP | 5;
     public static final int KM_TAG_PADDING = KM_ENUM_REP | 6;
     public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 7;
+    public static final int KM_TAG_MIN_MAC_LENGTH = KM_UINT | 8;
 
     public static final int KM_TAG_RESCOPING_ADD = KM_ENUM_REP | 101;
     public static final int KM_TAG_RESCOPING_DEL = KM_ENUM_REP | 102;
@@ -194,6 +195,9 @@
     public static final int KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54;
     public static final int KM_ERROR_CALLER_NONCE_PROHIBITED = -55;
     public static final int KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56;
+    public static final int KM_ERROR_INVALID_MAC_LENGTH = -57;
+    public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
+    public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
     public static final int KM_ERROR_UNIMPLEMENTED = -100;
     public static final int KM_ERROR_VERSION_MISMATCH = -101;
     public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
@@ -237,6 +241,8 @@
         sErrorCodeToString.put(KM_ERROR_INVALID_NONCE, "Invalid IV");
         sErrorCodeToString.put(KM_ERROR_CALLER_NONCE_PROHIBITED,
                 "Caller-provided IV not permitted");
+        sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH,
+                "Invalid MAC or authentication tag length");
         sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
         sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
     }
diff --git a/core/java/android/service/voice/IVoiceInteractionSession.aidl b/core/java/android/service/voice/IVoiceInteractionSession.aidl
index 8fe84e1..dbc28f7 100644
--- a/core/java/android/service/voice/IVoiceInteractionSession.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionSession.aidl
@@ -35,5 +35,6 @@
     void taskStarted(in Intent intent, int taskId);
     void taskFinished(in Intent intent, int taskId);
     void closeSystemDialogs();
+    void onLockscreenShown();
     void destroy();
 }
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index f08e93c..f647aa6 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -265,6 +265,11 @@
         }
 
         @Override
+        public void onLockscreenShown() {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_ON_LOCKSCREEN_SHOWN));
+        }
+
+        @Override
         public void destroy() {
             mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_DESTROY));
         }
@@ -674,6 +679,7 @@
     static final int MSG_HANDLE_SCREENSHOT = 105;
     static final int MSG_SHOW = 106;
     static final int MSG_HIDE = 107;
+    static final int MSG_ON_LOCKSCREEN_SHOWN = 108;
 
     class MyCallbacks implements HandlerCaller.Callback, SoftInputWindow.Callback {
         @Override
@@ -752,6 +758,10 @@
                     if (DEBUG) Log.d(TAG, "doHide");
                     doHide();
                     break;
+                case MSG_ON_LOCKSCREEN_SHOWN:
+                    if (DEBUG) Log.d(TAG, "onLockscreenShown");
+                    onLockscreenShown();
+                    break;
             }
             if (args != null) {
                 args.recycle();
@@ -1296,6 +1306,13 @@
         hide();
     }
 
+    /**
+     * Called when the lockscreen was shown.
+     */
+    public void onLockscreenShown() {
+        hide();
+    }
+
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
     }
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index b2b98db..ed858e7 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1556,13 +1556,6 @@
         if (accessibilityId == getAccessibilityViewId()) {
             return this;
         }
-        // If the data changed the children are invalid since the data model changed.
-        // Hence, we pretend they do not exist. After a layout the children will sync
-        // with the model at which point we notify that the accessibility state changed,
-        // so a service will be able to re-fetch the views.
-        if (mDataChanged) {
-            return null;
-        }
         return super.findViewByAccessibilityIdTraversal(accessibilityId);
     }
 
@@ -2409,18 +2402,6 @@
 
     class ListItemAccessibilityDelegate extends AccessibilityDelegate {
         @Override
-        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
-            // If the data changed the children are invalid since the data model changed.
-            // Hence, we pretend they do not exist. After a layout the children will sync
-            // with the model at which point we notify that the accessibility state changed,
-            // so a service will be able to re-fetch the views.
-            if (mDataChanged) {
-                return null;
-            }
-            return super.createAccessibilityNodeInfo(host);
-        }
-
-        @Override
         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
             super.onInitializeAccessibilityNodeInfo(host, info);
 
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index 0910daf..d552e54 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -122,6 +122,16 @@
         }
     }
 
+    public void onLockscreenShown() {
+        try {
+            if (mVoiceInteractionManagerService != null) {
+                mVoiceInteractionManagerService.onLockscreenShown();
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call onLockscreenShown", e);
+        }
+    }
+
     public ComponentName getAssistComponentForUser(int userId) {
         final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
                 Settings.Secure.ASSISTANT, userId);
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index dc946ab..1a963f3 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -131,4 +131,9 @@
      * from the lockscreen.
      */
     boolean activeServiceSupportsLaunchFromKeyguard();
+
+    /**
+     * Called when the lockscreen got shown.
+     */
+    void onLockscreenShown();
 }
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
index 768d586..0369c3f 100644
--- a/core/java/com/android/internal/os/KernelWakelockReader.java
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -68,12 +68,12 @@
         try {
             FileInputStream is;
             try {
-                is = new FileInputStream(sWakeupSourceFile);
-                wakeup_sources = true;
+                is = new FileInputStream(sWakelockFile);
+                wakeup_sources = false;
             } catch (java.io.FileNotFoundException e) {
                 try {
-                    is = new FileInputStream(sWakelockFile);
-                    wakeup_sources = false;
+                    is = new FileInputStream(sWakeupSourceFile);
+                    wakeup_sources = true;
                 } catch (java.io.FileNotFoundException e2) {
                     return null;
                 }
diff --git a/core/java/com/android/internal/policy/IKeyguardShowCallback.aidl b/core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl
similarity index 89%
rename from core/java/com/android/internal/policy/IKeyguardShowCallback.aidl
rename to core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl
index a2784d9..ef8478c 100644
--- a/core/java/com/android/internal/policy/IKeyguardShowCallback.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl
@@ -15,6 +15,6 @@
  */
 package com.android.internal.policy;
 
-oneway interface IKeyguardShowCallback {
-    void onShown(IBinder windowToken);
+oneway interface IKeyguardDrawnCallback {
+    void onDrawn();
 }
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 7ab4651..79af452 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -15,7 +15,7 @@
  */
 package com.android.internal.policy;
 
-import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.policy.IKeyguardStateCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
 
@@ -57,7 +57,13 @@
     /**
      * Called when the device has started waking up.
      */
-    void onStartedWakingUp(IKeyguardShowCallback callback);
+    void onStartedWakingUp();
+
+    /**
+     * Called when the device screen is turning on.
+     */
+    void onScreenTurningOn(IKeyguardDrawnCallback callback);
+
     void setKeyguardEnabled(boolean enabled);
     void onSystemReady();
     void doKeyguardTimeout(in Bundle options);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0c0ba7f..92862f5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -331,7 +331,7 @@
 
     <!-- Used for runtime permissions related to user's contacts and profile. -->
     <permission-group android:name="android.permission-group.CONTACTS"
-        android:icon="@drawable/perm_group_social_info"
+        android:icon="@drawable/perm_group_contacts"
         android:label="@string/permgrouplab_contacts"
         android:description="@string/permgroupdesc_contacts"
         android:priority="100" />
@@ -391,7 +391,7 @@
 
     <!-- Used for runtime permissions related to user's SMS messages. -->
     <permission-group android:name="android.permission-group.SMS"
-        android:icon="@drawable/perm_group_messages"
+        android:icon="@drawable/perm_group_sms"
         android:label="@string/permgrouplab_sms"
         android:description="@string/permgroupdesc_sms"
         android:priority="300" />
@@ -729,6 +729,7 @@
     <!-- Used for permissions that are associated with accessing
          camera or capturing images/video from the device. -->
     <permission-group android:name="android.permission-group.SENSORS"
+        android:icon="@drawable/perm_group_sensors"
         android:label="@string/permgrouplab_sensors"
         android:description="@string/permgroupdesc_sensors"
         android:priority="800" />
@@ -1535,7 +1536,9 @@
     <permission android:name="android.permission.CHANGE_CONFIGURATION"
         android:protectionLevel="signature|privileged|development" />
 
-    <!-- Allows an application to read or write the system settings. -->
+    <!-- Allows an application to read or write the system settings.
+         <p>Protection level: signature
+    -->
     <permission android:name="android.permission.WRITE_SETTINGS"
         android:label="@string/permlab_writeSettings"
         android:description="@string/permdesc_writeSettings"
diff --git a/core/res/res/drawable/ic_more_items.xml b/core/res/res/drawable/ic_more_items.xml
new file mode 100644
index 0000000..5fdcdce
--- /dev/null
+++ b/core/res/res/drawable/ic_more_items.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7
+7v2h14V7H7z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/perm_group_calendar.xml b/core/res/res/drawable/perm_group_calendar.xml
index a0f9dd2..4dc7b37 100644
--- a/core/res/res/drawable/perm_group_calendar.xml
+++ b/core/res/res/drawable/perm_group_calendar.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
     Copyright (C) 2015 The Android Open Source Project
 
@@ -14,11 +15,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
     <path
-        android:fillColor="#FF000000"
-        android:pathData="M34.0,24.0L24.0,24.0l0.0,10.0l10.0,0.0L34.0,24.0zM32.0,2.0l0.0,4.0L16.0,6.0L16.0,2.0l-4.0,0.0l0.0,4.0l-2.0,0.0c-2.21,0.0 -3.98,1.79 -3.98,4.0L6.0,38.0c0.0,2.21 1.79,4.0 4.0,4.0l28.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L42.0,10.0c0.0,-2.21 -1.79,-4.0 -4.0,-4.0l-2.0,0.0L36.0,2.0l-4.0,0.0zm6.0,36.0L10.0,38.0L10.0,16.0l28.0,0.0l0.0,22.0z"/>
-</vector>
+        android:fillColor="#000000"
+        android:pathData="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99 .9 -1.99 2L3 19c0 1.1 .89 2 2
+2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/perm_group_camera.xml b/core/res/res/drawable/perm_group_camera.xml
index 30d31ce..741a40e 100644
--- a/core/res/res/drawable/perm_group_camera.xml
+++ b/core/res/res/drawable/perm_group_camera.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
     Copyright (C) 2015 The Android Open Source Project
 
@@ -14,11 +15,19 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
     <path
-        android:fillColor="#FF000000"
-        android:pathData="M18.8,21.0l9.53,-16.51C26.94,4.18 25.49,4.0 24.0,4.0c-4.8,0.0 -9.19,1.69 -12.64,4.51l7.33,12.6 0.11,-0.2zm24.28,-3.0c-1.84,-5.85 -6.3,-10.52 -11.99,-12.68L23.77,18.0l19.31,0.0zm0.52,2.0L28.62,20.0l0.58,1.0 9.53,16.5C41.99,33.94 44.0,29.21 44.0,24.0c0.0,-1.37 -0.14,-2.71 -0.4,-4.0zm-26.53,4.0l-7.8,-13.5C6.01,14.06 4.0,18.79 4.0,24.0c0.0,1.3 0.14,2.7 0.4,4.0l14.98,0.0l-2.31,-4.0zM4.92,30.0c1.84,5.85 6.3,10.52 11.99,12.68L24.23,30.0L4.92,30.0zm22.54,0.0l-7.8,13.51c1.0,0.31 2.8,0.49 4.3,0.49 4.8,0.0 9.19,-1.69 12.64,-4.51L29.31,26.8 27.46,30.0z"/>
-</vector>
+        android:fillColor="#000000"
+        android:pathData="M 12 8.8 C 13.7673111995 8.8 15.2 10.2326888005 15.2 12 C 15.2 13.7673111995 13.7673111995 15.2 12 15.2 C 10.2326888005 15.2 8.8 13.7673111995 8.8 12 C 8.8 10.2326888005 10.2326888005 8.8 12 8.8 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1 .9 2 2 2h16c1.1 0 2-.9
+2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5
+5-2.24 5-5 5z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/perm_group_contacts.xml b/core/res/res/drawable/perm_group_contacts.xml
new file mode 100644
index 0000000..d698fd1
--- /dev/null
+++ b/core/res/res/drawable/perm_group_contacts.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:pathData="M0 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20 0H4v2h16V0zM4 24h16v-2H4v2zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1 .9 2 2 2h16c1.1
+0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 2.75c1.24 0 2.25 1.01 2.25 2.25s-1.01 2.25-2.25
+2.25S9.75 10.24 9.75 9 10.76 6.75 12 6.75zM17 17H7v-1.5c0-1.67 3.33-2.5 5-2.5s5
+.83 5 2.5V17z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/perm_group_location.xml b/core/res/res/drawable/perm_group_location.xml
index 4184cf9..fbc6066 100644
--- a/core/res/res/drawable/perm_group_location.xml
+++ b/core/res/res/drawable/perm_group_location.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
     Copyright (C) 2015 The Android Open Source Project
 
@@ -14,11 +15,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
     <path
-        android:fillColor="#FF000000"
-        android:pathData="M24.0,16.0c-4.42,0.0 -8.0,3.58 -8.0,8.0s3.58,8.0 8.0,8.0 8.0,-3.58 8.0,-8.0 -3.58,-8.0 -8.0,-8.0zm17.88,6.0C40.96,13.66 34.34,7.04 26.0,6.12L26.0,2.0l-4.0,0.0l0.0,4.12C13.66,7.04 7.04,13.66 6.12,22.0L2.0,22.0l0.0,4.0l4.12,0.0c0.92,8.34 7.54,14.96 15.88,15.88L22.0,46.0l4.0,0.0l0.0,-4.12c8.34,-0.92 14.96,-7.54 15.88,-15.88L46.0,26.0l0.0,-4.0l-4.12,0.0zM24.0,38.0c-7.73,0.0 -14.0,-6.27 -14.0,-14.0s6.27,-14.0 14.0,-14.0 14.0,6.27 14.0,14.0 -6.27,14.0 -14.0,14.0z"/>
-</vector>
+        android:fillColor="#000000"
+        android:pathData="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0
+9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/perm_group_messages.xml b/core/res/res/drawable/perm_group_messages.xml
deleted file mode 100644
index 4140e6c..0000000
--- a/core/res/res/drawable/perm_group_messages.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-    Copyright (C) 2015 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M40.0,4.0L8.0,4.0C5.79,4.0 4.02,5.79 4.02,8.0L4.0,44.0l8.0,-8.0l28.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L44.0,8.0c0.0,-2.21 -1.79,-4.0 -4.0,-4.0zm-4.0,24.0L12.0,28.0l0.0,-4.0l16.0,0.0l0.0,4.0zm0.0,-6.0L12.0,22.0l0.0,-4.0l24.0,0.0l0.0,4.0zm0.0,-6.0L12.0,16.0l0.0,-4.0l24.0,0.0l0.0,4.0z"/>
-</vector>
diff --git a/core/res/res/drawable/perm_group_microphone.xml b/core/res/res/drawable/perm_group_microphone.xml
index 670ef98..c565d20 100644
--- a/core/res/res/drawable/perm_group_microphone.xml
+++ b/core/res/res/drawable/perm_group_microphone.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
     Copyright (C) 2015 The Android Open Source Project
 
@@ -14,11 +15,16 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
     <path
-        android:fillColor="#FF000000"
-        android:pathData="M24.0,28.0c3.31,0.0 5.98,-2.69 5.98,-6.0L30.0,10.0c0.0,-3.32 -2.68,-6.0 -6.0,-6.0 -3.31,0.0 -6.0,2.68 -6.0,6.0l0.0,12.0c0.0,3.31 2.69,6.0 6.0,6.0zm10.6,-6.0c0.0,6.0 -5.07,10.2 -10.6,10.2 -5.52,0.0 -10.6,-4.2 -10.6,-10.2L10.0,22c0.0,6.83 5.44,12.47 12.0,13.44L22.0,42.0l4.0,0.0l0.0,-6.56c6.56,-0.97 12.0,-6.61 12.0,-13.44l-3.4,0.0z"/>
-</vector>
+        android:fillColor="#000000"
+        android:pathData="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3
+3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6
+6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/perm_group_phone_calls.xml b/core/res/res/drawable/perm_group_phone_calls.xml
index 04ac6b9..a647894 100644
--- a/core/res/res/drawable/perm_group_phone_calls.xml
+++ b/core/res/res/drawable/perm_group_phone_calls.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
     Copyright (C) 2015 The Android Open Source Project
 
@@ -14,11 +15,17 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
     <path
-        android:fillColor="#FF000000"
-        android:pathData="M13.25,21.59c2.88,5.66 7.51,10.29 13.18,13.17l4.4,-4.41c0.55,-0.55 1.34,-0.71 2.03,-0.49C35.1,30.6 37.51,31.0 40.0,31.0c1.11,0.0 2.0,0.89 2.0,2.0l0.0,7.0c0.0,1.11 -0.89,2.0 -2.0,2.0C21.22,42.0 6.0,26.78 6.0,8.0c0.0,-1.1 0.9,-2.0 2.0,-2.0l7.0,0.0c1.11,0.0 2.0,0.89 2.0,2.0 0.0,2.4 0.4,4.9 1.14,7.1 0.2,0.6 0.06,1.48 -0.49,2.03l-4.4,4.42z"/>
-</vector>
+        android:pathData="M0 0h24v24H0z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27 .67 -.36 1.02-.24 1.12
+.37 2.33 .57 3.57 .57 .55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17
+0-.55 .45 -1 1-1h3.5c.55 0 1 .45 1 1 0 1.25 .2 2.45 .57 3.57 .11 .35 .03 .74-.25
+1.02l-2.2 2.2z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/perm_group_sensors.xml b/core/res/res/drawable/perm_group_sensors.xml
new file mode 100644
index 0000000..ce36c13
--- /dev/null
+++ b/core/res/res/drawable/perm_group_sensors.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1
+2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9
+0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5 .1 -.8 .1 l-5.2
+2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/perm_group_sms.xml b/core/res/res/drawable/perm_group_sms.xml
new file mode 100644
index 0000000..9b32c601
--- /dev/null
+++ b/core/res/res/drawable/perm_group_sms.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20 2H4c-1.1 0-1.99 .9 -1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM9
+11H7V9h2v2zm4 0h-2V9h2v2zm4 0h-2V9h2v2z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/perm_group_social_info.xml b/core/res/res/drawable/perm_group_social_info.xml
deleted file mode 100644
index f0f7a90..0000000
--- a/core/res/res/drawable/perm_group_social_info.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-    Copyright (C) 2015 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M32.0,22.0c3.31,0.0 5.98,-2.69 5.98,-6.0s-2.67,-6.0 -5.98,-6.0c-3.31,0.0 -6.0,2.69 -6.0,6.0s2.69,6.0 6.0,6.0zm-16.0,0.0c3.31,0.0 5.98,-2.69 5.98,-6.0s-2.67,-6.0 -5.98,-6.0c-3.31,0.0 -6.0,2.69 -6.0,6.0s2.69,6.0 6.0,6.0zm0.0,4.0c-4.67,0.0 -14.0,2.34 -14.0,7.0l0.0,5.0l28.0,0.0l0.0,-5.0c0.0,-4.66 -9.33,-7.0 -14.0,-7.0zm16.0,0.0c-0.58,0.0 -1.2,0.04 -1.9,0.11C32.39,27.78 34.0,30.03 34.0,33.0l0.0,5.0l12.0,0.0l0.0,-5.0c0.0,-4.66 -9.33,-7.0 -14.0,-7.0z"/>
-</vector>
diff --git a/core/res/res/drawable/perm_group_storage.xml b/core/res/res/drawable/perm_group_storage.xml
index 74f16d8..477270d 100644
--- a/core/res/res/drawable/perm_group_storage.xml
+++ b/core/res/res/drawable/perm_group_storage.xml
@@ -1,7 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
-Copyright (C) 2015 The Android Open Source Project
+    Copyright (C) 2015 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -14,11 +15,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
     <path
-        android:pathData="M20,8H8c-2.2,0 -4,1.8 -4,4l0,24c0,2.2 1.8,4 4,4h32c2.2,0 4,-1.8 4,-4V16c0,-2.2 -1.8,-4 -4,-4H24L20,8z"
-        android:fillColor="#FFFFFF"/>
-</vector>
+        android:fillColor="#000000"
+        android:pathData="M10 4H4c-1.1 0-1.99 .9 -1.99 2L2 18c0 1.1 .9 2 2 2h16c1.1 0 2-.9
+2-2V8c0-1.1-.9-2-2-2h-8l-2-2z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f590ebe..fe82b8c 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2313,4 +2313,6 @@
   <java-symbol type="bool" name="config_eap_sim_based_auth_supported" />
 
   <java-symbol type="array" name="config_cell_retries_per_error_code" />
+  <java-symbol type="drawable" name="ic_more_items" />
+
 </resources>
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
index 5459bea..441ee66 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
@@ -51,7 +51,7 @@
 abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
 
     abstract static class GCM extends AndroidKeyStoreAuthenticatedAESCipherSpi {
-        private static final int MIN_SUPPORTED_TAG_LENGTH_BITS = 96;
+        static final int MIN_SUPPORTED_TAG_LENGTH_BITS = 96;
         private static final int MAX_SUPPORTED_TAG_LENGTH_BITS = 128;
         private static final int DEFAULT_TAG_LENGTH_BITS = 128;
         private static final int IV_LENGTH_BYTES = 12;
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index fd014eb..4c174f1 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -171,7 +171,7 @@
                         "Key size must be positive: " + mKeySizeBits);
             } else if ((mKeySizeBits % 8) != 0) {
                 throw new InvalidAlgorithmParameterException(
-                        "Key size in must be a multiple of 8: " + mKeySizeBits);
+                        "Key size must be a multiple of 8: " + mKeySizeBits);
             }
 
             try {
@@ -272,6 +272,11 @@
         KeymasterUtils.addUserAuthArgs(args,
                 spec.isUserAuthenticationRequired(),
                 spec.getUserAuthenticationValidityDurationSeconds());
+        KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
+                args,
+                mKeymasterAlgorithm,
+                mKeymasterBlockModes,
+                mKeymasterDigests);
         args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart());
         args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
                 spec.getKeyValidityForOriginationEnd());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 88858de..915d86f 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -672,6 +672,11 @@
             KeymasterUtils.addUserAuthArgs(args,
                     params.isUserAuthenticationRequired(),
                     params.getUserAuthenticationValidityDurationSeconds());
+            KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
+                    args,
+                    keymasterAlgorithm,
+                    keymasterBlockModes,
+                    keymasterDigests);
             args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
                     params.getKeyValidityStart());
             args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
index ea0f4b9..dbb79bc 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
@@ -19,12 +19,14 @@
 import android.os.IBinder;
 import android.security.KeyStore;
 import android.security.KeyStoreException;
+import android.security.keymaster.KeymasterDefs;
 import android.security.keymaster.OperationResult;
 
 import libcore.util.EmptyArray;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.security.ProviderException;
 
 /**
  * Helper for streaming a crypto operation's input and output via {@link KeyStore} service's
@@ -135,14 +137,15 @@
                 mBuffered = EmptyArray.BYTE;
                 mBufferedOffset = 0;
                 mBufferedLength = 0;
-            } else if (opResult.inputConsumed == 0) {
+            } else if (opResult.inputConsumed <= 0) {
                 // Nothing was consumed. More input needed.
                 if (inputLength > 0) {
                     // More input is available, but it wasn't included into the previous chunk
                     // because the chunk reached its maximum permitted size.
                     // Shouldn't have happened.
-                    throw new IllegalStateException("Nothing consumed from max-sized chunk: "
-                            + chunk.length + " bytes");
+                    throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
+                            "Keystore consumed nothing from max-sized chunk: " + chunk.length
+                                    + " bytes");
                 }
                 mBuffered = chunk;
                 mBufferedOffset = 0;
@@ -153,8 +156,9 @@
                 mBufferedOffset = opResult.inputConsumed;
                 mBufferedLength = chunk.length - opResult.inputConsumed;
             } else {
-                throw new IllegalStateException("Consumed more than provided: "
-                        + opResult.inputConsumed + ", provided: " + chunk.length);
+                throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
+                        "Keystore consumed more input than provided. Provided: " + chunk.length
+                                + ", consumed: " + opResult.inputConsumed);
             }
 
             if ((opResult.output != null) && (opResult.output.length > 0)) {
@@ -165,7 +169,7 @@
                         try {
                             bufferedOutput.write(opResult.output);
                         } catch (IOException e) {
-                            throw new IllegalStateException("Failed to buffer output", e);
+                            throw new ProviderException("Failed to buffer output", e);
                         }
                     }
                 } else {
@@ -179,7 +183,7 @@
                         try {
                             bufferedOutput.write(opResult.output);
                         } catch (IOException e) {
-                            throw new IllegalStateException("Failed to buffer output", e);
+                            throw new ProviderException("Failed to buffer output", e);
                         }
                         result = bufferedOutput.toByteArray();
                     }
@@ -229,27 +233,71 @@
             return EmptyArray.BYTE;
         }
 
-        byte[] chunk = ArrayUtils.subarray(mBuffered, mBufferedOffset, mBufferedLength);
-        mBuffered = EmptyArray.BYTE;
-        mBufferedLength = 0;
-        mBufferedOffset = 0;
+        // Keep invoking the update operation with remaining buffered data until either all of the
+        // buffered data is consumed or until update fails to consume anything.
+        ByteArrayOutputStream bufferedOutput = null;
+        while (mBufferedLength > 0) {
+            byte[] chunk = ArrayUtils.subarray(mBuffered, mBufferedOffset, mBufferedLength);
+            OperationResult opResult = mKeyStoreStream.update(chunk);
+            if (opResult == null) {
+                throw new KeyStoreConnectException();
+            } else if (opResult.resultCode != KeyStore.NO_ERROR) {
+                throw KeyStore.getKeyStoreException(opResult.resultCode);
+            }
 
-        OperationResult opResult = mKeyStoreStream.update(chunk);
-        if (opResult == null) {
-            throw new KeyStoreConnectException();
-        } else if (opResult.resultCode != KeyStore.NO_ERROR) {
-            throw KeyStore.getKeyStoreException(opResult.resultCode);
+            if (opResult.inputConsumed <= 0) {
+                // Nothing was consumed. Break out of the loop to avoid an infinite loop.
+                break;
+            }
+
+            if (opResult.inputConsumed >= chunk.length) {
+                // All of the input was consumed
+                mBuffered = EmptyArray.BYTE;
+                mBufferedOffset = 0;
+                mBufferedLength = 0;
+            } else {
+                // Some of the input was not consumed
+                mBuffered = chunk;
+                mBufferedOffset = opResult.inputConsumed;
+                mBufferedLength = chunk.length - opResult.inputConsumed;
+            }
+
+            if (opResult.inputConsumed > chunk.length) {
+                throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
+                        "Keystore consumed more input than provided. Provided: "
+                                + chunk.length + ", consumed: " + opResult.inputConsumed);
+            }
+
+            if ((opResult.output != null) && (opResult.output.length > 0)) {
+                // Some output was produced by this update operation
+                if (bufferedOutput == null) {
+                    // No output buffered yet.
+                    if (mBufferedLength == 0) {
+                        // No more output will be produced by this flush operation
+                        mProducedOutputSizeBytes += opResult.output.length;
+                        return opResult.output;
+                    } else {
+                        // More output might be produced by this flush operation -- buffer output.
+                        bufferedOutput = new ByteArrayOutputStream();
+                    }
+                }
+                // Buffer the output from this update operation
+                try {
+                    bufferedOutput.write(opResult.output);
+                } catch (IOException e) {
+                    throw new ProviderException("Failed to buffer output", e);
+                }
+            }
         }
 
-        if (opResult.inputConsumed < chunk.length) {
-            throw new IllegalStateException("Keystore failed to consume all input. Provided: "
-                    + chunk.length + ", consumed: " + opResult.inputConsumed);
-        } else if (opResult.inputConsumed > chunk.length) {
-            throw new IllegalStateException("Keystore consumed more input than provided"
-                    + " . Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed);
+        if (mBufferedLength > 0) {
+            throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
+                    "Keystore failed to consume last "
+                            + ((mBufferedLength != 1) ? (mBufferedLength + " bytes") : "byte")
+                            + " of input");
         }
 
-        byte[] result = (opResult.output != null) ? opResult.output : EmptyArray.BYTE;
+        byte[] result = (bufferedOutput != null) ? bufferedOutput.toByteArray() : EmptyArray.BYTE;
         mProducedOutputSizeBytes += result.length;
         return result;
     }
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index 92d636c..feafbfa 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -22,6 +22,8 @@
 import android.security.keymaster.KeymasterArguments;
 import android.security.keymaster.KeymasterDefs;
 
+import java.security.ProviderException;
+
 /**
  * @hide
  */
@@ -133,4 +135,45 @@
                     userAuthenticationValidityDurationSeconds);
         }
     }
+
+    /**
+     * Adds {@code KM_TAG_MIN_MAC_LENGTH} tag, if necessary, to the keymaster arguments for
+     * generating or importing a key. This tag may only be needed for symmetric keys (e.g., HMAC,
+     * AES-GCM).
+     */
+    public static void addMinMacLengthAuthorizationIfNecessary(KeymasterArguments args,
+            int keymasterAlgorithm,
+            int[] keymasterBlockModes,
+            int[] keymasterDigests) {
+        switch (keymasterAlgorithm) {
+            case KeymasterDefs.KM_ALGORITHM_AES:
+                if (com.android.internal.util.ArrayUtils.contains(
+                        keymasterBlockModes, KeymasterDefs.KM_MODE_GCM)) {
+                    // AES GCM key needs the minimum length of AEAD tag specified.
+                    args.addUnsignedInt(KeymasterDefs.KM_TAG_MIN_MAC_LENGTH,
+                            AndroidKeyStoreAuthenticatedAESCipherSpi.GCM
+                                    .MIN_SUPPORTED_TAG_LENGTH_BITS);
+                }
+                break;
+            case KeymasterDefs.KM_ALGORITHM_HMAC:
+                // HMAC key needs the minimum length of MAC set to the output size of the associated
+                // digest. This is because we do not offer a way to generate shorter MACs and
+                // don't offer a way to verify MACs (other than by generating them).
+                if (keymasterDigests.length != 1) {
+                    throw new ProviderException(
+                            "Unsupported number of authorized digests for HMAC key: "
+                                    + keymasterDigests.length
+                                    + ". Exactly one digest must be authorized");
+                }
+                int keymasterDigest = keymasterDigests[0];
+                int digestOutputSizeBits = getDigestOutputSizeBits(keymasterDigest);
+                if (digestOutputSizeBits == -1) {
+                    throw new ProviderException(
+                            "HMAC key authorized for unsupported digest: "
+                                    + KeyProperties.Digest.fromKeymaster(keymasterDigest));
+                }
+                args.addUnsignedInt(KeymasterDefs.KM_TAG_MIN_MAC_LENGTH, digestOutputSizeBits);
+                break;
+        }
+    }
 }
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 80f349a..0951fc1 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -214,10 +214,10 @@
         info.renderer->pushLayerUpdate(mLayer);
     }
 
-    if (CC_UNLIKELY(info.canvasContext)) {
-        // If canvasContext is not null that means there are prefetched layers
-        // that need to be accounted for. That might be us, so tell CanvasContext
-        // that this layer is in the tree and should not be destroyed.
+    if (info.canvasContext) {
+        // There might be prefetched layers that need to be accounted for.
+        // That might be us, so tell CanvasContext that this layer is in the
+        // tree and should not be destroyed.
         info.canvasContext->markLayerInUse(this);
     }
 }
@@ -339,7 +339,8 @@
         TextureCache& cache = Caches::getInstance().textureCache;
         info.out.hasFunctors |= subtree->functors.size();
         for (size_t i = 0; info.prepareTextures && i < subtree->bitmapResources.size(); i++) {
-            info.prepareTextures = cache.prefetchAndMarkInUse(subtree->bitmapResources[i]);
+            info.prepareTextures = cache.prefetchAndMarkInUse(
+                    info.canvasContext, subtree->bitmapResources[i]);
         }
         for (size_t i = 0; i < subtree->children().size(); i++) {
             DrawRenderNodeOp* op = subtree->children()[i];
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index 7227ce0..4bcd96d 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -97,7 +97,7 @@
      * Whether or not the Texture is marked in use and thus not evictable for
      * the current frame. This is reset at the start of a new frame.
      */
-    bool isInUse = false;
+    void* isInUse = nullptr;
 
 private:
     /**
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 2a90087..fda0091 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -122,10 +122,12 @@
     mAssetAtlas = assetAtlas;
 }
 
-void TextureCache::resetMarkInUse() {
+void TextureCache::resetMarkInUse(void* ownerToken) {
     LruCache<uint32_t, Texture*>::Iterator iter(mCache);
     while (iter.next()) {
-        iter.value()->isInUse = false;
+        if (iter.value()->isInUse == ownerToken) {
+            iter.value()->isInUse = nullptr;
+        }
     }
 }
 
@@ -189,10 +191,10 @@
     return texture;
 }
 
-bool TextureCache::prefetchAndMarkInUse(const SkBitmap* bitmap) {
+bool TextureCache::prefetchAndMarkInUse(void* ownerToken, const SkBitmap* bitmap) {
     Texture* texture = getCachedTexture(bitmap, AtlasUsageType::Use);
     if (texture) {
-        texture->isInUse = true;
+        texture->isInUse = ownerToken;
     }
     return texture;
 }
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 83c6e91..7a7ee5a 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -66,14 +66,14 @@
     /**
      * Resets all Textures to not be marked as in use
      */
-    void resetMarkInUse();
+    void resetMarkInUse(void* ownerToken);
 
     /**
      * Attempts to precache the SkBitmap. Returns true if a Texture was successfully
      * acquired for the bitmap, false otherwise. If a Texture was acquired it is
      * marked as in use.
      */
-    bool prefetchAndMarkInUse(const SkBitmap* bitmap);
+    bool prefetchAndMarkInUse(void* ownerToken, const SkBitmap* bitmap);
 
     /**
      * Returns the texture associated with the specified bitmap from either within the cache, or
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 0799c6c..ed853f7 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -95,7 +95,7 @@
     // layer updates or similar. May be NULL.
     OpenGLRenderer* renderer;
     ErrorHandler* errorHandler;
-    // TODO: Remove this? May be NULL
+    // May be NULL (TODO: can it really?)
     renderthread::CanvasContext* canvasContext;
 
     struct Out {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 09f93b8..e472e93 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -178,16 +178,13 @@
 
     info.damageAccumulator = &mDamageAccumulator;
     info.renderer = mCanvas;
-    if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) {
-        info.canvasContext = this;
-    }
+    info.canvasContext = this;
+
     mAnimationContext->startFrame(info.mode);
     mRootRenderNode->prepareTree(info);
     mAnimationContext->runRemainingAnimations(info);
 
-    if (info.canvasContext) {
-        freePrefetechedLayers();
-    }
+    freePrefetechedLayers();
 
     if (CC_UNLIKELY(!mNativeWindow.get())) {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
@@ -369,7 +366,11 @@
     if (mEglManager.hasEglContext()) {
         freePrefetechedLayers();
         mRootRenderNode->destroyHardwareResources();
-        Caches::getInstance().flush(Caches::kFlushMode_Layers);
+        Caches& caches = Caches::getInstance();
+        // Make sure to release all the textures we were owning as there won't
+        // be another draw
+        caches.textureCache.resetMarkInUse(this);
+        caches.flush(Caches::kFlushMode_Layers);
     }
 }
 
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 6507ce8..a4ac13b 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -114,7 +114,7 @@
     int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
     mRenderThread->timeLord().vsyncReceived(vsync);
     mContext->makeCurrent();
-    Caches::getInstance().textureCache.resetMarkInUse();
+    Caches::getInstance().textureCache.resetMarkInUse(mContext);
 
     for (size_t i = 0; i < mLayers.size(); i++) {
         mContext->processLayerUpdate(mLayers[i].get());
diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl
index aa5fde3..8091421 100644
--- a/media/java/android/media/IRingtonePlayer.aidl
+++ b/media/java/android/media/IRingtonePlayer.aidl
@@ -33,4 +33,7 @@
     /** Used for Notification sound playback. */
     void playAsync(in Uri uri, in UserHandle user, boolean looping, in AudioAttributes aa);
     void stopAsync();
+
+    /** Return the title of the media. */
+    String getTitle(in Uri uri);
 }
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index faeebe6..9e9d602 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -27,6 +27,7 @@
 import android.os.RemoteException;
 import android.provider.MediaStore;
 import android.provider.Settings;
+import android.provider.MediaStore.MediaColumns;
 import android.util.Log;
 
 import java.io.IOException;
@@ -50,6 +51,8 @@
         MediaStore.Audio.Media.DATA,
         MediaStore.Audio.Media.TITLE
     };
+    /** Selection that limits query results to just audio files */
+    private static final String MEDIA_SELECTION = MediaColumns.MIME_TYPE + " LIKE 'audio/%'";
 
     // keep references on active Ringtones until stopped or completion listener called.
     private static final ArrayList<Ringtone> sActiveRingtones = new ArrayList<Ringtone>();
@@ -193,11 +196,14 @@
      */
     public String getTitle(Context context) {
         if (mTitle != null) return mTitle;
-        return mTitle = getTitle(context, mUri, true);
+        return mTitle = getTitle(context, mUri, true /*followSettingsUri*/, mAllowRemote);
     }
 
-    private static String getTitle(Context context, Uri uri, boolean followSettingsUri) {
-        Cursor cursor = null;
+    /**
+     * @hide
+     */
+    public static String getTitle(
+            Context context, Uri uri, boolean followSettingsUri, boolean allowRemote) {
         ContentResolver res = context.getContentResolver();
         
         String title = null;
@@ -209,31 +215,45 @@
                 if (followSettingsUri) {
                     Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context,
                             RingtoneManager.getDefaultType(uri));
-                    String actualTitle = getTitle(context, actualUri, false);
+                    String actualTitle = getTitle(
+                            context, actualUri, false /*followSettingsUri*/, allowRemote);
                     title = context
                             .getString(com.android.internal.R.string.ringtone_default_with_actual,
                                     actualTitle);
                 }
             } else {
+                Cursor cursor = null;
                 try {
                     if (MediaStore.AUTHORITY.equals(authority)) {
-                        cursor = res.query(uri, MEDIA_COLUMNS, null, null, null);
+                        final String mediaSelection = allowRemote ? null : MEDIA_SELECTION;
+                        cursor = res.query(uri, MEDIA_COLUMNS, mediaSelection, null, null);
+                        if (cursor != null && cursor.getCount() == 1) {
+                            cursor.moveToFirst();
+                            return cursor.getString(2);
+                        }
+                        // missing cursor is handled below
                     }
                 } catch (SecurityException e) {
-                    // missing cursor is handled below
-                }
-
-                try {
-                    if (cursor != null && cursor.getCount() == 1) {
-                        cursor.moveToFirst();
-                        return cursor.getString(2);
-                    } else {
-                        title = uri.getLastPathSegment();
+                    IRingtonePlayer mRemotePlayer = null;
+                    if (allowRemote) {
+                        AudioManager audioManager =
+                                (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+                        mRemotePlayer = audioManager.getRingtonePlayer();
+                    }
+                    if (mRemotePlayer != null) {
+                        try {
+                            title = mRemotePlayer.getTitle(uri);
+                        } catch (RemoteException re) {
+                        }
                     }
                 } finally {
                     if (cursor != null) {
                         cursor.close();
                     }
+                    cursor = null;
+                }
+                if (title == null) {
+                    title = uri.getLastPathSegment();
                 }
             }
         }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java b/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java
index e5f3dc9..3927122 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java
@@ -27,4 +27,5 @@
      */
     public static final boolean DEBUG = false;
     public static final boolean DEBUG_SIM_STATES = false;
+    public static final boolean DEBUG_FP_WAKELOCK = true;
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 9e5644e..b098258 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -44,7 +44,9 @@
 import android.os.Handler;
 import android.os.IRemoteCallback;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
 
@@ -90,12 +92,15 @@
     private static final String TAG = "KeyguardUpdateMonitor";
     private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
+    private static final boolean DEBUG_FP_WAKELOCK = KeyguardConstants.DEBUG_FP_WAKELOCK;
     private static final int LOW_BATTERY_THRESHOLD = 20;
+    private static final long FINGERPRINT_WAKELOCK_TIMEOUT_MS = 15 * 1000;
 
     private static final String ACTION_FACE_UNLOCK_STARTED
             = "com.android.facelock.FACE_UNLOCK_STARTED";
     private static final String ACTION_FACE_UNLOCK_STOPPED
             = "com.android.facelock.FACE_UNLOCK_STOPPED";
+    private static final String FINGERPRINT_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
 
     // Callback messages
     private static final int MSG_TIME_UPDATE = 301;
@@ -114,10 +119,6 @@
     private static final int MSG_SCREEN_TURNED_ON = 319;
     private static final int MSG_SCREEN_TURNED_OFF = 320;
     private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322;
-    private static final int MSG_FINGERPRINT_AUTHENTICATED = 323;
-    private static final int MSG_FINGERPRINT_ERROR = 324;
-    private static final int MSG_FINGERPRINT_HELP = 325;
-    private static final int MSG_FINGERPRINT_AUTH_FAILED = 326;
     private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 327;
     private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 328;
     private static final int MSG_AIRPLANE_MODE_CHANGED = 329;
@@ -157,6 +158,7 @@
     private List<SubscriptionInfo> mSubscriptionInfo;
     private boolean mFingerprintDetectionRunning;
     private TrustManager mTrustManager;
+    private PowerManager mPowerManager;
 
     private final Handler mHandler = new Handler() {
         @Override
@@ -210,18 +212,6 @@
                 case MSG_SCREEN_TURNED_ON:
                     handleScreenTurnedOn();
                     break;
-                case MSG_FINGERPRINT_AUTHENTICATED:
-                    handleFingerprintAuthenticated();
-                    break;
-                case MSG_FINGERPRINT_HELP:
-                    handleFingerprintHelp(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
-                    break;
-                case MSG_FINGERPRINT_ERROR:
-                    handleFingerprintError(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
-                    break;
-                case MSG_FINGERPRINT_AUTH_FAILED:
-                    handleFingerprintAuthFailed();
-                    break;
                 case MSG_FACE_UNLOCK_STATE_CHANGED:
                     handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
                     break;
@@ -253,6 +243,8 @@
 
     private static int sCurrentUser;
 
+    private boolean mWakeAndUnlocking;
+
     public synchronized static void setCurrentUser(int currentUser) {
         sCurrentUser = currentUser;
     }
@@ -353,23 +345,72 @@
         }
     }
 
-    private void onFingerprintAuthenticated(int userId) {
+    private void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) {
         mUserFingerprintAuthenticated.put(userId, true);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
-                cb.onFingerprintAuthenticated(userId);
+                cb.onFingerprintAuthenticated(userId, wakeAndUnlocking);
             }
         }
     }
 
     private void handleFingerprintAuthFailed() {
+        releaseFingerprintWakeLock();
         stopListeningForFingerprint();
         handleFingerprintHelp(-1, mContext.getString(R.string.fingerprint_not_recognized));
         updateFingerprintListeningState();
     }
 
+    private void handleFingerprintAcquired(int acquireInfo) {
+        if (acquireInfo != FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) {
+            return;
+        }
+        if (!mScreenOn) {
+            releaseFingerprintWakeLock();
+            mWakeLock = mPowerManager.newWakeLock(
+                    PowerManager.PARTIAL_WAKE_LOCK, FINGERPRINT_WAKE_LOCK_NAME);
+            mWakeLock.acquire();
+            mWakeAndUnlocking = true;
+            if (DEBUG_FP_WAKELOCK) {
+                Log.i(TAG, "fingerprint acquired, grabbing fp wakelock");
+            }
+            mHandler.postDelayed(mReleaseFingerprintWakeLockRunnable,
+                    FINGERPRINT_WAKELOCK_TIMEOUT_MS);
+        } else {
+            mWakeAndUnlocking = false;
+        }
+    }
+
+    private final Runnable mReleaseFingerprintWakeLockRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (DEBUG_FP_WAKELOCK) {
+                Log.i(TAG, "fp wakelock: TIMEOUT!!");
+            }
+            releaseFingerprintWakeLock();
+        }
+    };
+
+    private void releaseFingerprintWakeLock() {
+        if (mWakeLock != null) {
+            mHandler.removeCallbacks(mReleaseFingerprintWakeLockRunnable);
+            if (DEBUG_FP_WAKELOCK) {
+                Log.i(TAG, "releasing fp wakelock");
+            }
+            mWakeLock.release();
+            mWakeLock = null;
+        }
+    }
+
     private void handleFingerprintAuthenticated() {
+        if (mWakeAndUnlocking) {
+            if (DEBUG_FP_WAKELOCK) {
+                Log.i(TAG, "fp wakelock: Authenticated, waking up...");
+            }
+            mPowerManager.wakeUp(SystemClock.uptimeMillis());
+        }
+        releaseFingerprintWakeLock();
         try {
             final int userId;
             try {
@@ -382,7 +423,7 @@
                 Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
                 return;
             }
-            onFingerprintAuthenticated(userId);
+            onFingerprintAuthenticated(userId, mWakeAndUnlocking);
         } finally {
             setFingerprintRunningDetectionRunning(false);
         }
@@ -555,26 +596,32 @@
 
         @Override
         public void onAuthenticationFailed() {
-            mHandler.obtainMessage(MSG_FINGERPRINT_AUTH_FAILED).sendToTarget();
+            handleFingerprintAuthFailed();
         };
 
         @Override
         public void onAuthenticationSucceeded(AuthenticationResult result) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
+            handleFingerprintAuthenticated();
         }
 
         @Override
         public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_HELP, helpMsgId, 0, helpString).sendToTarget();
+            handleFingerprintHelp(helpMsgId, helpString.toString());
         }
 
         @Override
         public void onAuthenticationError(int errMsgId, CharSequence errString) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, errMsgId, 0, errString).sendToTarget();
+            handleFingerprintError(errMsgId, errString.toString());
+        }
+
+        @Override
+        public void onAuthenticationAcquired(int acquireInfo) {
+            handleFingerprintAcquired(acquireInfo);
         }
     };
     private CancellationSignal mFingerprintCancelSignal;
     private FingerprintManager mFpm;
+    private PowerManager.WakeLock mWakeLock;
 
     /**
      * When we receive a
@@ -741,6 +788,7 @@
     private KeyguardUpdateMonitor(Context context) {
         mContext = context;
         mSubscriptionManager = SubscriptionManager.from(context);
+        mPowerManager = context.getSystemService(PowerManager.class);
         mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
         // Since device can't be un-provisioned, we only need to register a content observer
         // to update mDeviceProvisioned when we are...
@@ -819,7 +867,7 @@
     }
 
     private boolean shouldListenForFingerprint() {
-        return mScreenOn && mKeyguardIsVisible && !mSwitchingUser
+        return mKeyguardIsVisible && !mSwitchingUser
                 && mTrustManager.hasUserAuthenticatedSinceBoot(ActivityManager.getCurrentUser());
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 26e6973..9fd8d30 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -178,8 +178,10 @@
     /**
      * Called when a fingerprint is recognized.
      * @param userId the user id for which the fingerprint was authenticated
+     * @param wakeAndUnlocking whether the authentication woke the device up and thus we'd like to
+     *                         dismiss the lockscreen before turning on the screen
      */
-    public void onFingerprintAuthenticated(int userId) { }
+    public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) { }
 
     /**
      * Called when fingerprint provides help string (e.g. "Try again")
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index f66a7dd..9265b63 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -304,4 +304,8 @@
     public void onUserSwitched(int newUserId) {
         updateAssistInfo();
     }
+
+    public void onLockscreenShown() {
+        mAssistUtils.onLockscreenShown();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 98558b4..9f21dbe 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -25,9 +25,9 @@
 import android.os.Process;
 import android.util.Log;
 
+import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
-import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.policy.IKeyguardStateCallback;
 import com.android.systemui.SystemUIApplication;
 
@@ -120,9 +120,15 @@
         }
 
         @Override // Binder interface
-        public void onStartedWakingUp(IKeyguardShowCallback callback) {
+        public void onStartedWakingUp() {
             checkPermission();
-            mKeyguardViewMediator.onStartedWakingUp(callback);
+            mKeyguardViewMediator.onStartedWakingUp();
+        }
+
+        @Override // Binder interface
+        public void onScreenTurningOn(IKeyguardDrawnCallback callback) {
+            checkPermission();
+            mKeyguardViewMediator.onScreenTurningOn(callback);
         }
 
         @Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 009a0d6..c01a485 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -41,6 +41,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -55,8 +56,9 @@
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
+
+import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
-import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.policy.IKeyguardStateCallback;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.widget.LockPatternUtils;
@@ -77,7 +79,6 @@
 
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
 
-
 /**
  * Mediates requests related to the keyguard.  This includes queries about the
  * state of the keyguard, power management events that effect whether the keyguard
@@ -138,7 +139,7 @@
     private static final int RESET = 4;
     private static final int VERIFY_UNLOCK = 5;
     private static final int NOTIFY_SCREEN_OFF = 6;
-    private static final int NOTIFY_SCREEN_ON = 7;
+    private static final int NOTIFY_SCREEN_TURNING_ON = 7;
     private static final int KEYGUARD_DONE = 9;
     private static final int KEYGUARD_DONE_DRAWING = 10;
     private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
@@ -148,6 +149,7 @@
     private static final int START_KEYGUARD_EXIT_ANIM = 18;
     private static final int ON_ACTIVITY_DRAWN = 19;
     private static final int KEYGUARD_DONE_PENDING_TIMEOUT = 20;
+    private static final int NOTIFY_STARTED_WAKING_UP = 21;
 
     /**
      * The default amount of time we stay awake (used for all key input)
@@ -311,11 +313,14 @@
     private boolean mPendingReset;
 
     /**
-     * When starting goign to sleep, we figured out that we need to lock Keyguard and this should be
+     * When starting going to sleep, we figured out that we need to lock Keyguard and this should be
      * committed when finished going to sleep.
      */
     private boolean mPendingLock;
 
+    private boolean mWakeAndUnlocking;
+    private IKeyguardDrawnCallback mDrawnCallback;
+
     KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
@@ -454,12 +459,17 @@
         }
 
         @Override
-        public void onFingerprintAuthenticated(int userId) {
+        public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) {
             if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                 mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated();
             } else {
-                mStatusBarKeyguardViewManager.animateCollapsePanels(
-                        FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
+                if (wakeAndUnlocking) {
+                    mWakeAndUnlocking = true;
+                    keyguardDone(true, true);
+                } else {
+                    mStatusBarKeyguardViewManager.animateCollapsePanels(
+                            FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
+                }
             }
         };
 
@@ -752,21 +762,23 @@
     /**
      * Let's us know when the device is waking up.
      */
-    public void onStartedWakingUp(IKeyguardShowCallback callback) {
+    public void onStartedWakingUp() {
 
         // TODO: Rename all screen off/on references to interactive/sleeping
         synchronized (this) {
             mDeviceInteractive = true;
             cancelDoKeyguardLaterLocked();
             if (DEBUG) Log.d(TAG, "onStartedWakingUp, seq = " + mDelayedShowingSequence);
-            if (callback != null) {
-                notifyScreenOnLocked(callback);
-            }
+            notifyStartedWakingUp();
         }
         KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurnedOn();
         maybeSendUserPresentBroadcast();
     }
 
+    public void onScreenTurningOn(IKeyguardDrawnCallback callback) {
+        notifyScreenOnLocked(callback);
+    }
+
     private void maybeSendUserPresentBroadcast() {
         if (mSystemReady && mLockPatternUtils.isLockScreenDisabled(
                 KeyguardUpdateMonitor.getCurrentUser())) {
@@ -1093,14 +1105,14 @@
         mHandler.sendEmptyMessage(NOTIFY_SCREEN_OFF);
     }
 
-    /**
-     * Send a message to keyguard telling it the screen just turned on.
-     * @see #onScreenTurnedOn
-     * @see #handleNotifyScreenOn
-     */
-    private void notifyScreenOnLocked(IKeyguardShowCallback result) {
+    private void notifyStartedWakingUp() {
+        if (DEBUG) Log.d(TAG, "notifyStartedWakingUp");
+        mHandler.sendEmptyMessage(NOTIFY_STARTED_WAKING_UP);
+    }
+
+    private void notifyScreenOnLocked(IKeyguardDrawnCallback callback) {
         if (DEBUG) Log.d(TAG, "notifyScreenOnLocked");
-        Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_ON, result);
+        Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_TURNING_ON, callback);
         mHandler.sendMessage(msg);
     }
 
@@ -1190,8 +1202,11 @@
                 case NOTIFY_SCREEN_OFF:
                     handleNotifyScreenOff();
                     break;
-                case NOTIFY_SCREEN_ON:
-                    handleNotifyScreenOn((IKeyguardShowCallback) msg.obj);
+                case NOTIFY_SCREEN_TURNING_ON:
+                    handleNotifyScreenTurningOn((IKeyguardDrawnCallback) msg.obj);
+                    break;
+                case NOTIFY_STARTED_WAKING_UP:
+                    handleNotifyStartedWakingUp();
                     break;
                 case KEYGUARD_DONE:
                     handleKeyguardDone(msg.arg1 != 0, msg.arg2 != 0);
@@ -1354,6 +1369,7 @@
             setShowingLocked(true);
             mStatusBarKeyguardViewManager.show(options);
             mHiding = false;
+            mWakeAndUnlocking = false;
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false;
             updateActivityLockScreenState();
@@ -1375,7 +1391,8 @@
                 // manager until it tells us it's safe to do so with
                 // startKeyguardExitAnimation.
                 ActivityManagerNative.getDefault().keyguardGoingAway(
-                        mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock(),
+                        mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
+                                || mWakeAndUnlocking,
                         mStatusBarKeyguardViewManager.isGoingToNotificationShade());
             } catch (RemoteException e) {
                 Log.e(TAG, "Error while calling WindowManager", e);
@@ -1437,6 +1454,9 @@
             updateActivityLockScreenState();
             adjustStatusBarLocked();
             sendUserPresentBroadcast();
+            if (mWakeAndUnlocking && mDrawnCallback != null) {
+                notifyDrawn(mDrawnCallback);
+            }
         }
     }
 
@@ -1508,14 +1528,31 @@
         }
     }
 
-    /**
-     * Handle message sent by {@link #notifyScreenOnLocked}
-     * @see #NOTIFY_SCREEN_ON
-     */
-    private void handleNotifyScreenOn(IKeyguardShowCallback callback) {
+    private void handleNotifyStartedWakingUp() {
         synchronized (KeyguardViewMediator.this) {
-            if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
-            mStatusBarKeyguardViewManager.onScreenTurnedOn(callback);
+            if (DEBUG) Log.d(TAG, "handleNotifyWakingUp");
+            mStatusBarKeyguardViewManager.onScreenTurnedOn();
+        }
+    }
+
+    private void handleNotifyScreenTurningOn(IKeyguardDrawnCallback callback) {
+        synchronized (KeyguardViewMediator.this) {
+            if (DEBUG) Log.d(TAG, "handleNotifyScreenTurningOn");
+            if (callback != null) {
+                if (mWakeAndUnlocking) {
+                    mDrawnCallback = callback;
+                } else {
+                    notifyDrawn(callback);
+                }
+            }
+        }
+    }
+
+    private void notifyDrawn(final IKeyguardDrawnCallback callback) {
+        try {
+            callback.onDrawn();
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Exception calling onDrawn():", e);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index e9a256c..fe876d7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -171,6 +171,13 @@
             }
             mAsyncPlayer.stop();
         }
+
+        @Override
+        public String getTitle(Uri uri) {
+            final UserHandle user = Binder.getCallingUserHandle();
+            return Ringtone.getTitle(getContextForUser(user), uri,
+                    false /*followSettingsUri*/, false /*allowRemote*/);
+        }
     };
 
     private Context getContextForUser(UserHandle user) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 07406b9..f3ad9d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -45,6 +45,8 @@
     private final MobileDataController mDataController;
     private final CellularDetailAdapter mDetailAdapter;
 
+    private final CellSignalCallback mSignalCallback = new CellSignalCallback();
+
     public CellularTile(Host host) {
         super(host);
         mController = host.getNetworkController();
@@ -90,8 +92,10 @@
     protected void handleUpdateState(SignalState state, Object arg) {
         state.visible = mController.hasMobileDataFeature();
         if (!state.visible) return;
-        final CallbackInfo cb = (CallbackInfo) arg;
-        if (cb == null) return;
+        CallbackInfo cb = (CallbackInfo) arg;
+        if (cb == null) {
+            cb = mSignalCallback.mInfo;
+        }
 
         final Resources r = mContext.getResources();
         final int iconId = cb.noSim ? R.drawable.ic_qs_no_sim
@@ -152,7 +156,7 @@
         boolean isDataTypeIconWide;
     }
 
-    private final SignalCallback mSignalCallback = new SignalCallbackAdapter() {
+    private final class CellSignalCallback extends SignalCallbackAdapter {
         private final CallbackInfo mInfo = new CallbackInfo();
         @Override
         public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index f7f7acb..3d0dc7b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -45,6 +45,8 @@
     private int mCurrentUserId;
     private String mIntentPackage;
 
+    private Intent mLastIntent;
+
     private IntentTile(Host host, String action) {
         super(host);
         mContext.registerReceiver(mReceiver, new IntentFilter(action));
@@ -112,8 +114,16 @@
 
     @Override
     protected void handleUpdateState(State state, Object arg) {
-        if (!(arg instanceof Intent)) return;
-        final Intent intent = (Intent) arg;
+        Intent intent = (Intent) arg;
+        if (intent == null) {
+            if (mLastIntent == null) {
+                return;
+            }
+            // No intent but need to refresh state, just use the last one.
+            intent = mLastIntent;
+        }
+        // Save the last one in case we need it later.
+        mLastIntent = intent;
         state.visible = intent.getBooleanExtra("visible", true);
         state.contentDescription = intent.getStringExtra("contentDescription");
         state.label = intent.getStringExtra("label");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 3bfff2f..e654efd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -35,7 +35,6 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
-import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
 
 import java.util.List;
@@ -49,6 +48,8 @@
     private final WifiDetailAdapter mDetailAdapter;
     private final QSTile.SignalState mStateBeforeClick = newTileState();
 
+    private final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
+
     public WifiTile(Host host) {
         super(host);
         mController = host.getNetworkController();
@@ -118,8 +119,10 @@
     protected void handleUpdateState(SignalState state, Object arg) {
         state.visible = true;
         if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg);
-        if (arg == null) return;
         CallbackInfo cb = (CallbackInfo) arg;
+        if (cb == null) {
+            cb = mSignalCallback.mInfo;
+        }
 
         boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
         boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null);
@@ -213,20 +216,21 @@
         }
     }
 
-    private final SignalCallback mSignalCallback = new SignalCallbackAdapter() {
+    private final class WifiSignalCallback extends SignalCallbackAdapter {
+        final CallbackInfo mInfo = new CallbackInfo();
+
         @Override
         public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
                 boolean activityIn, boolean activityOut, String description) {
             if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
-            final CallbackInfo info = new CallbackInfo();
-            info.enabled = enabled;
-            info.connected = qsIcon.visible;
-            info.wifiSignalIconId = qsIcon.icon;
-            info.enabledDesc = description;
-            info.activityIn = activityIn;
-            info.activityOut = activityOut;
-            info.wifiSignalContentDescription = qsIcon.contentDescription;
-            refreshState(info);
+            mInfo.enabled = enabled;
+            mInfo.connected = qsIcon.visible;
+            mInfo.wifiSignalIconId = qsIcon.icon;
+            mInfo.enabledDesc = description;
+            mInfo.activityIn = activityIn;
+            mInfo.activityOut = activityOut;
+            mInfo.wifiSignalContentDescription = qsIcon.contentDescription;
+            refreshState(mInfo);
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 91adc460..a5310a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -641,7 +641,7 @@
         }
 
         @Override
-        public void onFingerprintAuthenticated(int userId) {
+        public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) {
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 2248905..d829299 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1730,7 +1730,7 @@
     }
 
     private int adjustDisableFlags(int state) {
-        if (!mLaunchTransitionFadingAway
+        if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway
                 && (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit)) {
             state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
             state |= StatusBarManager.DISABLE_SYSTEM_INFO;
@@ -2913,7 +2913,7 @@
         updateRowStates();
         mIconController.updateResources();
         mScreenPinningRequest.onConfigurationChanged();
-        mNetworkController.handleConfigurationChanged();
+        mNetworkController.onConfigurationChanged();
     }
 
     @Override
@@ -3311,6 +3311,7 @@
             mDraggedDownRow.notifyHeightChanged(false  /* needsAnimation */);
             mDraggedDownRow = null;
         }
+        mAssistManager.onLockscreenShown();
     }
 
     private void onLaunchTransitionFadingEnded() {
@@ -3460,7 +3461,7 @@
                 startTime + fadeoutDuration
                         - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION,
                 StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
-        disable(mDisabledUnmodified1, mDisabledUnmodified2, true /* animate */);
+        disable(mDisabledUnmodified1, mDisabledUnmodified2, fadeoutDuration > 0 /* animate */);
     }
 
     public boolean isKeyguardFadingAway() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index a69416a..e622144 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -19,15 +19,12 @@
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.SystemClock;
-import android.util.Slog;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManagerGlobal;
 
-import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.ViewMediatorCallback;
@@ -163,26 +160,10 @@
         mBouncer.onScreenTurnedOff();
     }
 
-    public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
+    public void onScreenTurnedOn() {
         mScreenOn = true;
         mScreenWillWakeUp = false;
         mPhoneStatusBar.onScreenTurnedOn();
-        if (callback != null) {
-            callbackAfterDraw(callback);
-        }
-    }
-
-    private void callbackAfterDraw(final IKeyguardShowCallback callback) {
-        mContainer.post(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    callback.onShown(mContainer.getWindowToken());
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Exception calling onShown():", e);
-                }
-            }
-        });
     }
 
     public void notifyScreenWakeUpRequested() {
@@ -270,16 +251,22 @@
             mPhoneStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
             boolean staying = mPhoneStatusBar.hideKeyguard();
             if (!staying) {
-                mStatusBarWindowManager.setKeyguardFadingAway(true);
-                mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() {
-                    @Override
-                    public void run() {
-                        mStatusBarWindowManager.setKeyguardFadingAway(false);
-                        mPhoneStatusBar.finishKeyguardFadingAway();
-                        WindowManagerGlobal.getInstance().trimMemory(
-                                ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
-                    }
-                });
+                if (fadeoutDuration == 0) {
+                    mPhoneStatusBar.finishKeyguardFadingAway();
+                    WindowManagerGlobal.getInstance().trimMemory(
+                            ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+                } else {
+                    mStatusBarWindowManager.setKeyguardFadingAway(true);
+                    mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() {
+                        @Override
+                        public void run() {
+                            mStatusBarWindowManager.setKeyguardFadingAway(false);
+                            mPhoneStatusBar.finishKeyguardFadingAway();
+                            WindowManagerGlobal.getInstance().trimMemory(
+                                    ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+                        }
+                    });
+                }
             } else {
                 mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
                 mPhoneStatusBar.finishKeyguardFadingAway();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 6fc15a8..f31311d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -132,7 +132,7 @@
         }
 
         @Override
-        public void onFingerprintAuthenticated(int userId) {
+        public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) {
             update(false /* updateAlways */);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 81f2d53..7cd94d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -197,7 +197,6 @@
         filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
-        filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
         filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
         mContext.registerReceiver(this, filter, null, mReceiverHandler);
         mListening = true;
@@ -339,8 +338,6 @@
         if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
                 action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
             updateConnectivity();
-        } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
-            handleConfigurationChanged();
         } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
             refreshLocale();
             updateAirplaneMode(false);
@@ -373,8 +370,18 @@
         }
     }
 
-    public void handleConfigurationChanged() {
+    public void onConfigurationChanged() {
         mConfig = Config.readConfig(mContext);
+        mReceiverHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                handleConfigurationChanged();
+            }
+        });
+    }
+
+    @VisibleForTesting
+    void handleConfigurationChanged() {
         for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
             mobileSignalController.setConfiguration(mConfig);
         }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index e57e3ff..a75cc48 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -617,12 +617,9 @@
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                 ActivityRecord r = activities.get(activityNdx);
                 if (notCurrentUserTask && (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) == 0) {
-                    return null;
+                    continue;
                 }
                 if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId == userId) {
-                    //Slog.i(TAG, "Found matching class!");
-                    //dump();
-                    //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
                     return r;
                 }
             }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index eef3d63..1223a00 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -5126,6 +5126,11 @@
             if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
                 continue;
             }
+            // Skip packages that have permission to interact across users
+            if (pm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS, pkg.packageName)
+                    == PackageManager.PERMISSION_GRANTED) {
+                continue;
+            }
             if (homeActivityName != null
                     && pkg.packageName.equals(homeActivityName.getPackageName())
                     && pkg.applicationInfo.isSystemApp()) {
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 8871e64..c705fbf 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -74,7 +74,6 @@
     private static final int MSG_USER_SWITCHING = 10;
     private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute
 
-    private boolean mIsKeyguard; // true if the authentication client is keyguard
     private ClientMonitor mAuthClient = null;
     private ClientMonitor mEnrollClient = null;
     private ClientMonitor mRemoveClient = null;
@@ -124,20 +123,29 @@
     public void binderDied() {
         Slog.v(TAG, "fingerprintd died");
         mDaemon = null;
+        dispatchError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
     }
 
     public IFingerprintDaemon getFingerprintDaemon() {
         if (mDaemon == null) {
             mDaemon = IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(FINGERPRINTD));
-            if (mDaemon == null) {
-                Slog.w(TAG, "fingerprind service not available");
-            } else {
+            if (mDaemon != null) {
                 try {
                     mDaemon.asBinder().linkToDeath(this, 0);
-                }   catch (RemoteException e) {
-                    Slog.w(TAG, "caught remote exception in linkToDeath: ", e);
-                    mDaemon = null; // try again!
+                    mDaemon.init(mDaemonCallback);
+                    mHalDeviceId = mDaemon.openHal();
+                    if (mHalDeviceId != 0) {
+                        updateActiveGroup(ActivityManager.getCurrentUser());
+                    } else {
+                        Slog.w(TAG, "Failed to open Fingerprint HAL!");
+                        mDaemon = null;
+                    }
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to open fingeprintd HAL", e);
+                    mDaemon = null; // try again later!
                 }
+            } else {
+                Slog.w(TAG, "fingerprint service not available");
             }
         }
         return mDaemon;
@@ -156,7 +164,6 @@
     protected void dispatchRemoved(long deviceId, int fingerId, int groupId) {
         final ClientMonitor client = mRemoveClient;
         if (fingerId != 0) {
-            ContentResolver res = mContext.getContentResolver();
             removeTemplateForUser(mRemoveClient, fingerId);
         }
         if (client != null && client.sendRemoved(fingerId, groupId)) {
@@ -577,12 +584,6 @@
                 result |= true; // we have a valid fingerprint
                 mLockoutReset.run();
             }
-            // For fingerprint devices that support touch-to-wake, this will ensure the device
-            // wakes up and turns the screen on when fingerprint is authenticated.
-            if (mIsKeyguard && authenticated) {
-                mPowerManager.wakeUp(SystemClock.uptimeMillis(),
-                        "android.server.fingerprint:AUTH");
-            }
             return result;
         }
 
@@ -727,7 +728,6 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    mIsKeyguard = KEYGUARD_PACKAGE.equals(opPackageName);
                     startAuthentication(token, opId, groupId, receiver, flags, restricted);
                 }
             });
@@ -821,15 +821,6 @@
     public void onStart() {
         publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
         IFingerprintDaemon daemon = getFingerprintDaemon();
-        if (daemon != null) {
-            try {
-                daemon.init(mDaemonCallback);
-                mHalDeviceId = daemon.openHal();
-            	updateActiveGroup(ActivityManager.getCurrentUser());
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to open fingeprintd HAL", e);
-            }
-        }
         if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
         listenForUserSwitches();
     }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 07de6f5..0366fff 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -91,7 +91,6 @@
 import com.android.internal.util.ImageUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.IoThread;
-import com.google.android.collect.Sets;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -106,6 +105,7 @@
 import java.nio.charset.StandardCharsets;
 import java.security.SecureRandom;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.Random;
@@ -221,7 +221,7 @@
 
             reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL);
 
-            final ArraySet<File> unclaimedIcons = Sets.newArraySet(
+            final ArraySet<File> unclaimedIcons = newArraySet(
                     mSessionsDir.listFiles());
 
             // Ignore stages and icons claimed by active sessions
@@ -245,7 +245,7 @@
 
     private void reconcileStagesLocked(String volumeUuid) {
         final File stagingDir = buildStagingDir(volumeUuid);
-        final ArraySet<File> unclaimedStages = Sets.newArraySet(
+        final ArraySet<File> unclaimedStages = newArraySet(
                 stagingDir.listFiles(sStageFilter));
 
         // Ignore stages claimed by active sessions
@@ -1091,6 +1091,15 @@
                 .build();
     }
 
+    public static <E> ArraySet<E> newArraySet(E... elements) {
+        final ArraySet<E> set = new ArraySet<E>();
+        if (elements != null) {
+            set.ensureCapacity(elements.length);
+            Collections.addAll(set, elements);
+        }
+        return set;
+    }
+
     private static class Callbacks extends Handler {
         private static final int MSG_SESSION_CREATED = 1;
         private static final int MSG_SESSION_BADGING_CHANGED = 2;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 28cbaab..dc3e2d6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -119,7 +119,7 @@
 import com.android.internal.widget.PointerLocationView;
 import com.android.server.LocalServices;
 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
-import com.android.server.policy.keyguard.KeyguardServiceDelegate.ShowListener;
+import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
 
 import java.io.File;
 import java.io.FileReader;
@@ -323,10 +323,10 @@
             mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
         }
     };
-    final ShowListener mKeyguardDelegateCallback = new ShowListener() {
+    final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
         @Override
-        public void onShown(IBinder windowToken) {
-            if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onShown.");
+        public void onDrawn() {
+            if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
             mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
         }
     };
@@ -5496,11 +5496,7 @@
         }
 
         if (mKeyguardDelegate != null) {
-            mKeyguardDelegate.onStartedWakingUp(mKeyguardDelegateCallback);
-            // ... eventually calls finishKeyguardDrawn
-        } else {
-            if (DEBUG_WAKEUP) Slog.d(TAG, "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
-            finishKeyguardDrawn();
+            mKeyguardDelegate.onStartedWakingUp();
         }
     }
 
@@ -5539,9 +5535,13 @@
             if (mKeyguardDelegate != null) {
                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
             }
+            mWindowManagerDrawComplete = false;
         }
 
-        finishScreenTurningOn();
+        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
+        // as well as enabling the orientation change logic/sensor.
+        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
+                WAITING_FOR_DRAWN_TIMEOUT);
     }
 
     // Called on the DisplayManager's DisplayPowerController thread.
@@ -5570,12 +5570,15 @@
             mScreenOnFully = false;
             mWindowManagerDrawComplete = false;
             mScreenOnListener = screenOnListener;
-        }
 
-        mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
-                WAITING_FOR_DRAWN_TIMEOUT);
-        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
-        // as well as enabling the orientation change logic/sensor.
+            if (mKeyguardDelegate != null) {
+                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
+            } else {
+                if (DEBUG_WAKEUP) Slog.d(TAG,
+                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
+                finishKeyguardDrawn();
+            }
+        }
     }
 
     private void finishWindowsDrawn() {
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 1406789..0f3a199 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -18,9 +18,9 @@
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy.OnKeyguardExitResult;
 
+import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
-import com.android.internal.policy.IKeyguardShowCallback;
 
 /**
  * A local class that keeps a cache of keyguard state that can be restored in the event
@@ -35,7 +35,7 @@
     private final Context mContext;
     private final View mScrim; // shown if keyguard crashes
     private final KeyguardState mKeyguardState = new KeyguardState();
-    private ShowListener mShowListenerWhenConnect;
+    private DrawnListener mDrawnListenerWhenConnect;
 
     private static final class KeyguardState {
         KeyguardState() {
@@ -61,23 +61,23 @@
         public boolean bootCompleted;
     };
 
-    public interface ShowListener {
-        public void onShown(IBinder windowToken);
+    public interface DrawnListener {
+        void onDrawn();
     }
 
     // A delegate class to map a particular invocation with a ShowListener object.
-    private final class KeyguardShowDelegate extends IKeyguardShowCallback.Stub {
-        private ShowListener mShowListener;
+    private final class KeyguardShowDelegate extends IKeyguardDrawnCallback.Stub {
+        private DrawnListener mDrawnListener;
 
-        KeyguardShowDelegate(ShowListener showListener) {
-            mShowListener = showListener;
+        KeyguardShowDelegate(DrawnListener drawnListener) {
+            mDrawnListener = drawnListener;
         }
 
         @Override
-        public void onShown(IBinder windowToken) throws RemoteException {
+        public void onDrawn() throws RemoteException {
             if (DEBUG) Log.v(TAG, "**** SHOWN CALLED ****");
-            if (mShowListener != null) {
-                mShowListener.onShown(windowToken);
+            if (mDrawnListener != null) {
+                mDrawnListener.onDrawn();
             }
             hideScrim();
         }
@@ -141,9 +141,10 @@
                 // If the system is ready, it means keyguard crashed and restarted.
                 mKeyguardService.onSystemReady();
                 // This is used to hide the scrim once keyguard displays.
-                mKeyguardService.onStartedWakingUp(new KeyguardShowDelegate(
-                        mShowListenerWhenConnect));
-                mShowListenerWhenConnect = null;
+                mKeyguardService.onStartedWakingUp();
+                mKeyguardService.onScreenTurningOn(
+                        new KeyguardShowDelegate(mDrawnListenerWhenConnect));
+                mDrawnListenerWhenConnect = null;
             }
             if (mKeyguardState.bootCompleted) {
                 mKeyguardService.onBootCompleted();
@@ -221,16 +222,23 @@
         mKeyguardState.dreaming = false;
     }
 
-    public void onStartedWakingUp(final ShowListener showListener) {
+    public void onStartedWakingUp() {
         if (mKeyguardService != null) {
-            if (DEBUG) Log.v(TAG, "onScreenTurnedOn(showListener = " + showListener + ")");
-            mKeyguardService.onStartedWakingUp(new KeyguardShowDelegate(showListener));
+            if (DEBUG) Log.v(TAG, "onStartedWakingUp()");
+            mKeyguardService.onStartedWakingUp();
+        }
+    }
+
+    public void onScreenTurningOn(final DrawnListener drawnListener) {
+        if (mKeyguardService != null) {
+            if (DEBUG) Log.v(TAG, "onScreenTurnedOn(showListener = " + drawnListener + ")");
+            mKeyguardService.onScreenTurningOn(new KeyguardShowDelegate(drawnListener));
         } else {
             // try again when we establish a connection
-            Slog.w(TAG, "onScreenTurnedOn(): no keyguard service!");
+            Slog.w(TAG, "onScreenTurningOn(): no keyguard service!");
             // This shouldn't happen, but if it does, show the scrim immediately and
             // invoke the listener's callback after the service actually connects.
-            mShowListenerWhenConnect = showListener;
+            mDrawnListenerWhenConnect = drawnListener;
             showScrim();
         }
     }
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index 51d59fa..5810a45 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -22,9 +22,9 @@
 import android.os.RemoteException;
 import android.util.Slog;
 
+import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
-import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.policy.IKeyguardStateCallback;
 
 /**
@@ -124,9 +124,18 @@
     }
 
     @Override
-    public void onStartedWakingUp(IKeyguardShowCallback callback) {
+    public void onStartedWakingUp() {
         try {
-            mService.onStartedWakingUp(callback);
+            mService.onStartedWakingUp();
+        } catch (RemoteException e) {
+            Slog.w(TAG , "Remote Exception", e);
+        }
+    }
+
+    @Override
+    public void onScreenTurningOn(IKeyguardDrawnCallback callback) {
+        try {
+            mService.onScreenTurningOn(callback);
         } catch (RemoteException e) {
             Slog.w(TAG , "Remote Exception", e);
         }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index b57c413..a8874d0 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -894,6 +894,28 @@
         }
 
         @Override
+        public void onLockscreenShown() {
+            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
+            synchronized (this) {
+                if (mImpl == null) {
+                    return;
+                }
+                final long caller = Binder.clearCallingIdentity();
+                try {
+                    if (mImpl.mActiveSession != null && mImpl.mActiveSession.mSession != null) {
+                        try {
+                            mImpl.mActiveSession.mSession.onLockscreenShown();
+                        } catch (RemoteException e) {
+                            Log.w(TAG, "Failed to call onLockscreenShown", e);
+                        }
+                    }
+                } finally {
+                    Binder.restoreCallingIdentity(caller);
+                }
+            }
+        }
+
+        @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
diff --git a/tests/Assist/src/com/android/test/assist/AssistInteractionSession.java b/tests/Assist/src/com/android/test/assist/AssistInteractionSession.java
index 43f1e32..851bda9 100644
--- a/tests/Assist/src/com/android/test/assist/AssistInteractionSession.java
+++ b/tests/Assist/src/com/android/test/assist/AssistInteractionSession.java
@@ -24,6 +24,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.service.voice.VoiceInteractionSession;
+import android.util.Log;
 import android.view.View;
 import android.view.ViewAnimationUtils;
 import android.view.ViewTreeObserver;
@@ -69,6 +70,7 @@
 
     @Override
     public void onCreate() {
+        super.onCreate();
         // Simulate slowness of Assist app
         try {
             Thread.sleep(1000);
@@ -105,6 +107,12 @@
         }
     }
 
+    @Override
+    public void onLockscreenShown() {
+        super.onLockscreenShown();
+        Log.i("Assistant", "Lockscreen was shown");
+    }
+
     private void playAssistAnimation() {
         Interpolator linearOutSlowIn = AnimationUtils.loadInterpolator(mBackground.getContext(),
                 android.R.interpolator.linear_out_slow_in);