Merge "Fixed mutate() for RippleDrawable, ASLD, AVD, fix applyTheme in VD" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 299a33c..eb7891a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27271,8 +27271,8 @@
     method public boolean isSpeaking();
     method public int playEarcon(java.lang.String, int, android.os.Bundle, java.lang.String);
     method public deprecated int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
-    method public int playSilence(long, int, java.lang.String);
     method public deprecated int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>);
+    method public int playSilentUtterance(long, int, java.lang.String);
     method public int setAudioAttributes(android.media.AudioAttributes);
     method public deprecated int setEngineByPackageName(java.lang.String);
     method public int setLanguage(java.util.Locale);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 005baed..3d14c58 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -635,14 +635,7 @@
             if (mIcon != null) {
                 return mIcon;
             }
-            if (mIconFilename != null) {
-                try {
-                    return ActivityManagerNative.getDefault().
-                            getTaskDescriptionIcon(mIconFilename);
-                } catch (RemoteException e) {
-                }
-            }
-            return null;
+            return loadTaskDescriptionIcon(mIconFilename);
         }
 
         /** @hide */
@@ -650,6 +643,23 @@
             return mIconFilename;
         }
 
+        /** @hide */
+        public Bitmap getInMemoryIcon() {
+            return mIcon;
+        }
+
+        /** @hide */
+        public static Bitmap loadTaskDescriptionIcon(String iconFilename) {
+            if (iconFilename != null) {
+                try {
+                    return ActivityManagerNative.getDefault().
+                            getTaskDescriptionIcon(iconFilename);
+                } catch (RemoteException e) {
+                }
+            }
+            return null;
+        }
+
         /**
          * @return The color override on the theme's primary color.
          */
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 300301b..b492deb 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -702,6 +702,20 @@
     }
 
     /**
+     * Disable NFC hardware.
+     * @hide
+    */
+    @SystemApi
+    public boolean disable(boolean persist) {
+        try {
+            return sService.disable(persist);
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+            return false;
+        }
+    }
+
+    /**
      * Pauses polling for a {@code timeoutInMs} millis. If polling must be resumed before timeout,
      * use {@link #resumePolling()}.
      * @hide
diff --git a/core/java/android/speech/tts/SynthesisRequest.java b/core/java/android/speech/tts/SynthesisRequest.java
index d41aa67..6262fcb 100644
--- a/core/java/android/speech/tts/SynthesisRequest.java
+++ b/core/java/android/speech/tts/SynthesisRequest.java
@@ -61,7 +61,7 @@
 
     /**
      * Gets the text which should be synthesized.
-     * @deprecated As of API level 20, replaced by {@link #getCharSequenceText}.
+     * @deprecated As of API level 21, replaced by {@link #getCharSequenceText}.
      */
     @Deprecated
     public String getText() {
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 120c9e3..c59ca8a 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -575,7 +575,7 @@
          * @see TextToSpeech#synthesizeToFile(String, java.util.HashMap, String)
          * @see TextToSpeech#getFeatures(java.util.Locale)
          *
-         * @deprecated Starting from API level 20, to select network synthesis, call
+         * @deprecated Starting from API level 21, to select network synthesis, call
          * ({@link TextToSpeech#getVoices()}, find a suitable network voice
          * ({@link Voice#isNetworkConnectionRequired()}) and pass it
          * to {@link TextToSpeech#setVoice(Voice)}).
@@ -593,7 +593,7 @@
          * @see TextToSpeech#synthesizeToFile(String, java.util.HashMap, String)
          * @see TextToSpeech#getFeatures(java.util.Locale)
 
-         * @deprecated Starting from API level 20, to select embedded synthesis, call
+         * @deprecated Starting from API level 21, to select embedded synthesis, call
          * ({@link TextToSpeech#getVoices()}, find a suitable embedded voice
          * ({@link Voice#isNetworkConnectionRequired()}) and pass it
          * to {@link TextToSpeech#setVoice(Voice)}).
@@ -1015,7 +1015,7 @@
      *
      * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
      *
-     * @deprecated As of API level 20, replaced by
+     * @deprecated As of API level 21, replaced by
      *         {@link #addEarcon(String, File)}.
      */
     @Deprecated
@@ -1124,7 +1124,7 @@
      *            engine named "com.svox.pico" if it is being used.
      *
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the speak operation.
-     * @deprecated As of API level 20, replaced by
+     * @deprecated As of API level 21, replaced by
      *         {@link #speak(CharSequence, int, Bundle, String)}.
      */
     @Deprecated
@@ -1194,7 +1194,7 @@
      *            engine named "com.svox.pico" if it is being used.
      *
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation.
-     * @deprecated As of API level 20, replaced by
+     * @deprecated As of API level 21, replaced by
      *         {@link #playEarcon(String, int, Bundle, String)}.
      */
     @Deprecated
@@ -1218,9 +1218,9 @@
      * @param queueMode {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
      * @param utteranceId An unique identifier for this request.
      *
-     * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilence operation.
+     * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilentUtterance operation.
      */
-    public int playSilence(final long durationInMs, final int queueMode,
+    public int playSilentUtterance(final long durationInMs, final int queueMode,
             final String utteranceId) {
         return runAction(new Action<Integer>() {
             @Override
@@ -1228,7 +1228,7 @@
                 return service.playSilence(getCallerIdentity(), durationInMs,
                                            queueMode, utteranceId);
             }
-        }, ERROR, "playSilence");
+        }, ERROR, "playSilentUtterance");
     }
 
     /**
@@ -1252,13 +1252,13 @@
      *            engine named "com.svox.pico" if it is being used.
      *
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilence operation.
-     * @deprecated As of API level 20, replaced by
-     *         {@link #playSilence(long, int, String)}.
+     * @deprecated As of API level 21, replaced by
+     *         {@link #playSilentUtterance(long, int, String)}.
      */
     @Deprecated
     public int playSilence(final long durationInMs, final int queueMode,
             final HashMap<String, String> params) {
-        return playSilence(durationInMs, queueMode,
+        return playSilentUtterance(durationInMs, queueMode,
                            params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID));
     }
 
@@ -1276,7 +1276,7 @@
      *
      * @param locale The locale to query features for.
      * @return Set instance. May return {@code null} on error.
-     * @deprecated As of API level 20, please use voices. In order to query features of the voice,
+     * @deprecated As of API level 21, please use voices. In order to query features of the voice,
      * call {@link #getVoices()} to retrieve the list of available voices and
      * {@link Voice#getFeatures()} to retrieve the set of features.
      */
@@ -1421,7 +1421,7 @@
      *
      * @return language, country (if any) and variant (if any) used by the client stored in a
      *     Locale instance, or {@code null} on error.
-     * @deprecated As of API Level 20, use <code>getDefaultVoice().getLocale()</code> ({@link
+     * @deprecated As of API level 21, use <code>getDefaultVoice().getLocale()</code> ({@link
      *   #getDefaultVoice()})
      */
     @Deprecated
@@ -1476,7 +1476,7 @@
 
                 String variant = loc.getVariant();
 
-                // As of API level 20, setLanguage is implemented using setVoice.
+                // As of API level 21, setLanguage is implemented using setVoice.
                 // (which, in the default implementation, will call loadLanguage on the service
                 // interface).
 
@@ -1535,7 +1535,7 @@
      * @return language, country (if any) and variant (if any) used by the client stored in a
      *     Locale instance, or {@code null} on error.
      *
-     * @deprecated As of API level 20, please use <code>getVoice().getLocale()</code>
+     * @deprecated As of API level 21, please use <code>getVoice().getLocale()</code>
      * ({@link #getVoice()}).
      */
     @Deprecated
@@ -1831,7 +1831,7 @@
      *            something like "/sdcard/myappsounds/mysound.wav".
      *
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation.
-     * @deprecated As of API level 20, replaced by
+     * @deprecated As of API level 21, replaced by
      *         {@link #synthesizeToFile(CharSequence, Bundle, File, String)}.
      */
     @Deprecated
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 079467a..9bb7f02 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -91,7 +91,7 @@
  * The first three methods are siblings of the {@link #onGetLanguage},
  * {@link #onIsLanguageAvailable} and {@link #onLoadLanguage} methods. The last one,
  * {@link #onGetDefaultVoiceNameFor(String, String, String)} is a link between locale and voice
- * based methods. Since API level 20 {@link TextToSpeech#setLanguage} is implemented by
+ * based methods. Since API level 21 {@link TextToSpeech#setLanguage} is implemented by
  * calling {@link TextToSpeech#setVoice} with the voice returned by
  * {@link #onGetDefaultVoiceNameFor(String, String, String)}.
  *
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 946a3f7..c855e57 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -81,7 +81,7 @@
 
     /**
      * Intermediate density for screens that sit somewhere between
-     * {@link #DENSITY_XXHIGH} (480 dpi) and {@link #DENSITY_XXXHIGH} (560 dpi).
+     * {@link #DENSITY_XXHIGH} (480 dpi) and {@link #DENSITY_XXXHIGH} (640 dpi).
      * This is not a density that applications should target, instead relying
      * on the system to scale their {@link #DENSITY_XXXHIGH} assets for them.
      */
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index f64177d..3592687 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -276,13 +276,19 @@
 
             // Do not check this word if the user is currently editing it
             final boolean isEditing;
+
+            // Defer spell check when typing a word with an interior apostrophe.
+            // TODO: a better solution to this would be to make the word
+            // iterator locale-sensitive and include the apostrophe in
+            // languages that use it (such as English).
+            final boolean apostrophe = (selectionStart == end + 1 && editable.charAt(end) == '\'');
             if (mIsSentenceSpellCheckSupported) {
                 // Allow the overlap of the cursor and the first boundary of the spell check span
                 // no to skip the spell check of the following word because the
                 // following word will never be spell-checked even if the user finishes composing
-                isEditing = selectionEnd <= start || selectionStart > end;
+                isEditing = !apostrophe && (selectionEnd <= start || selectionStart > end);
             } else {
-                isEditing = selectionEnd < start || selectionStart > end;
+                isEditing = !apostrophe && (selectionEnd < start || selectionStart > end);
             }
             if (start >= 0 && end > start && isEditing) {
                 spellCheckSpan.setSpellCheckInProgress(true);
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 71a05ab..5c2abc53 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -4174,6 +4174,14 @@
                 AudioSystem.DEVICE_STATE_UNAVAILABLE,
                 address);
         mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
+        synchronized (mCurAudioRoutes) {
+            // Remove A2DP routes as well
+            if (mCurAudioRoutes.mBluetoothName != null) {
+                mCurAudioRoutes.mBluetoothName = null;
+                sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
+                        SENDMSG_NOOP, 0, 0, null, 0);
+            }
+        }
     }
 
     // must be called synchronized on mConnectedDevices
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 1de8a8b..3e5919f 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -141,26 +141,31 @@
 
         final ServiceConnection thisConnection = mServiceConnection = new MediaServiceConnection();
 
+        boolean bound = false;
         try {
-            mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
+            if (mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE)) {
+                bound = true;
+            }
         } catch (Exception ex) {
             Log.e(TAG, "Failed binding to service " + mServiceComponent);
+        }
 
+        if (!bound) {
             // Tell them that it didn't work.  We are already on the main thread,
             // but we don't want to do callbacks inside of connect().  So post it,
             // and then check that we are on the same ServiceConnection.  We know
             // we won't also get an onServiceConnected or onServiceDisconnected,
             // so we won't be doing double callbacks.
             mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        // Ensure that nobody else came in or tried to connect again.
-                        if (thisConnection == mServiceConnection) {
-                            forceCloseConnection();
-                            mCallback.onConnectionFailed();
-                        }
+                @Override
+                public void run() {
+                    // Ensure that nobody else came in or tried to connect again.
+                    if (thisConnection == mServiceConnection) {
+                        forceCloseConnection();
+                        mCallback.onConnectionFailed();
                     }
-                });
+                }
+            });
         }
 
         if (DBG) {
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index 06e40c5..5ce7f9f 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -49,7 +49,7 @@
  */
 public class MediaSessionLegacyHelper {
     private static final String TAG = "MediaSessionHelper";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final Object sLock = new Object();
     private static MediaSessionLegacyHelper sInstance;
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 8e603ba..0d393bf 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -412,7 +412,7 @@
                 if (mCurrView != null) {
                     float delta = getPos(ev) - mInitialTouchPos;
                     float absDelta = Math.abs(delta);
-                    if (absDelta >= mFalsingThreshold) {
+                    if (absDelta >= getFalsingThreshold()) {
                         mTouchAboveFalsingThreshold = true;
                     }
                     // don't let items that can't be dismissed be dragged more than
@@ -466,6 +466,11 @@
         return true;
     }
 
+    private int getFalsingThreshold() {
+        float factor = mCallback.getFalsingThresholdFactor();
+        return (int) (mFalsingThreshold * factor);
+    }
+
     public interface Callback {
         View getChildAtPosition(MotionEvent ev);
 
@@ -489,6 +494,11 @@
          * @return if true, prevents the default alpha fading.
          */
         boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress);
+
+        /**
+         * @return The factor the falsing threshold should be multiplied with
+         */
+        float getFalsingThresholdFactor();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index bdb0ad3..330333a 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -196,6 +196,11 @@
         return false;
     }
 
+    @Override
+    public float getFalsingThresholdFactor() {
+        return 1.0f;
+    }
+
     public void dismissChild(View v) {
         mSwipeHelper.dismissChild(v, 0);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 47c096f..1e247be 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -204,6 +204,11 @@
         return false;
     }
 
+    @Override
+    public float getFalsingThresholdFactor() {
+        return 1.0f;
+    }
+
     public void dismissChild(View v) {
         mSwipeHelper.dismissChild(v, 0);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index d4b403d..9d4fe66 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -177,16 +177,24 @@
                 if (t != null) {
                     Drawable cachedIcon = mApplicationIconCache.get(t.key);
                     Bitmap cachedThumbnail = mThumbnailCache.get(t.key);
+
                     // Load the application icon if it is stale or we haven't cached one yet
                     if (cachedIcon == null) {
-                        ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
-                                t.key.userId);
-                        if (info != null) {
-                            cachedIcon = ssp.getActivityIcon(info, t.key.userId);
+                        cachedIcon = getTaskDescriptionIcon(t.key, t.icon, t.iconFilename, ssp,
+                                mContext.getResources());
+
+                        if (cachedIcon == null) {
+                            ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
+                                    t.key.userId);
+                            if (info != null) {
+                                cachedIcon = ssp.getActivityIcon(info, t.key.userId);
+                            }
                         }
+
                         if (cachedIcon == null) {
                             cachedIcon = mDefaultApplicationIcon;
                         }
+
                         // At this point, even if we can't load the icon, we will set the default
                         // icon.
                         mApplicationIconCache.put(t.key, cachedIcon);
@@ -230,6 +238,17 @@
             }
         }
     }
+
+    Drawable getTaskDescriptionIcon(Task.TaskKey taskKey, Bitmap iconBitmap, String iconFilename,
+            SystemServicesProxy ssp, Resources res) {
+        Bitmap tdIcon = iconBitmap != null
+                ? iconBitmap
+                : ActivityManager.TaskDescription.loadTaskDescriptionIcon(iconFilename);
+        if (tdIcon != null) {
+            return ssp.getBadgedIcon(new BitmapDrawable(res, tdIcon), taskKey.userId);
+        }
+        return null;
+    }
 }
 
 /* Recents task loader
@@ -321,15 +340,20 @@
         if (icon != null) {
             return icon;
         }
-        // Return the task description icon if it exists
-        if (td != null && td.getIcon() != null) {
-            icon = ssp.getBadgedIcon(new BitmapDrawable(res, td.getIcon()), taskKey.userId);
-            mApplicationIconCache.put(taskKey, icon);
-            return icon;
-        }
-        // If we are preloading this task, continue to load the activity icon
+
+        // If we are preloading this task, continue to load the task description icon or the
+        // activity icon
         if (preloadTask) {
-            // All short paths failed, load the icon from the activity info and cache it
+
+            // Return and cache the task description icon if it exists
+            Drawable tdDrawable = mLoader.getTaskDescriptionIcon(taskKey, td.getInMemoryIcon(),
+                    td.getIconFilename(), ssp, res);
+            if (tdDrawable != null) {
+                mApplicationIconCache.put(taskKey, tdDrawable);
+                return tdDrawable;
+            }
+
+            // Load the icon from the activity info and cache it
             if (infoHandle.info == null) {
                 infoHandle.info = ssp.getActivityInfo(taskKey.baseIntent.getComponent(),
                         taskKey.userId);
@@ -453,10 +477,17 @@
                 activityInfoCache.put(cnKey, infoHandle);
             }
 
+            Bitmap icon = t.taskDescription != null
+                    ? t.taskDescription.getInMemoryIcon()
+                    : null;
+            String iconFilename = t.taskDescription != null
+                    ? t.taskDescription.getIconFilename()
+                    : null;
+
             // Add the task to the stack
             Task task = new Task(taskKey, (t.id > -1), t.affiliatedTaskId, t.affiliatedTaskColor,
                     activityLabel, activityIcon, activityColor, (i == (taskCount - 1)),
-                    config.lockToAppEnabled);
+                    config.lockToAppEnabled, icon, iconFilename);
 
             if (preloadTask && loadTaskThumbnails) {
                 // Load the thumbnail from the cache if possible
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 406e03f..a7e2b0b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -124,7 +124,8 @@
     public boolean isActive;
     public boolean lockToThisTask;
     public boolean lockToTaskEnabled;
-
+    public Bitmap icon;
+    public String iconFilename;
     TaskCallbacks mCb;
 
     public Task() {
@@ -133,7 +134,8 @@
 
     public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor,
                 String activityTitle, Drawable activityIcon, int colorPrimary,
-                boolean lockToThisTask, boolean lockToTaskEnabled) {
+                boolean lockToThisTask, boolean lockToTaskEnabled, Bitmap icon,
+                String iconFilename) {
         boolean isInAffiliationGroup = (taskAffiliation != key.id);
         boolean hasAffiliationGroupColor = isInAffiliationGroup && (taskAffiliationColor != 0);
         this.key = key;
@@ -147,6 +149,8 @@
         this.isActive = isActive;
         this.lockToThisTask = lockToTaskEnabled && lockToThisTask;
         this.lockToTaskEnabled = lockToTaskEnabled;
+        this.icon = icon;
+        this.iconFilename = iconFilename;
     }
 
     /** Copies the other task. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index c869ba4..0d5ebe7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -256,6 +256,9 @@
     }
 
     private void startActivateAnimation(boolean reverse) {
+        if (!isAttachedToWindow()) {
+            return;
+        }
         int widthHalf = mBackgroundNormal.getWidth()/2;
         int heightHalf = mBackgroundNormal.getActualHeight()/2;
         float radius = (float) Math.sqrt(widthHalf*widthHalf + heightHalf*heightHalf);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index a9c701a..6653254 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -303,8 +303,12 @@
     }
 
     private boolean isBelowFalsingThreshold() {
-        return Math.abs(mTranslation) < Math.abs(mTranslationOnDown)
-                + mMinTranslationAmount;
+        return Math.abs(mTranslation) < Math.abs(mTranslationOnDown) + getMinTranslationAmount();
+    }
+
+    private int getMinTranslationAmount() {
+        float factor = mCallback.getAffordanceFalsingFactor();
+        return (int) (mMinTranslationAmount * factor);
     }
 
     private void fling(float vel, final boolean snapBack) {
@@ -339,14 +343,14 @@
         translation = rightSwipePossible() ? translation : Math.max(0, translation);
         translation = leftSwipePossible() ? translation : Math.min(0, translation);
         float absTranslation = Math.abs(translation);
-        if (absTranslation > Math.abs(mTranslationOnDown) + mMinTranslationAmount ||
+        if (absTranslation > Math.abs(mTranslationOnDown) + getMinTranslationAmount() ||
                 mMotionPerformedByUser) {
             mMotionPerformedByUser = true;
         }
         if (translation != mTranslation || isReset) {
             KeyguardAffordanceView targetView = translation > 0 ? mLeftIcon : mRightIcon;
             KeyguardAffordanceView otherView = translation > 0 ? mRightIcon : mLeftIcon;
-            float alpha = absTranslation / mMinTranslationAmount;
+            float alpha = absTranslation / getMinTranslationAmount();
 
             // We interpolate the alpha of the other icons to 0
             float fadeOutAlpha = SWIPE_RESTING_ALPHA_AMOUNT * (1.0f - alpha);
@@ -482,5 +486,10 @@
         View getLeftPreview();
 
         View getRightPreview();
+
+        /**
+         * @return The factor the minimum swipe amount should be multiplied with.
+         */
+        float getAffordanceFalsingFactor();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 80e9663..b9efb22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -706,7 +706,7 @@
             case MotionEvent.ACTION_MOVE:
                 final float h = y - mInitialTouchY;
                 setQsExpansion(h + mInitialHeightOnTouch);
-                if (h >= mQsFalsingThreshold) {
+                if (h >= getFalsingThreshold()) {
                     mQsTouchAboveFalsingThreshold = true;
                 }
                 trackMovement(event);
@@ -732,6 +732,11 @@
         }
     }
 
+    private int getFalsingThreshold() {
+        float factor = mStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f;
+        return (int) (mQsFalsingThreshold * factor);
+    }
+
     @Override
     public void onOverscrolled(float lastTouchX, float lastTouchY, int amount) {
         if (mIntercepting && shouldQuickSettingsIntercept(lastTouchX, lastTouchY,
@@ -1453,8 +1458,7 @@
         if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
                 || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
             mAfforanceHelper.animateHideLeftRightIcon();
-        }
-        if (mQsExpanded) {
+        } else if (mQsExpanded) {
             mTwoFingerQsExpand = true;
         }
     }
@@ -1633,6 +1637,11 @@
     }
 
     @Override
+    public float getAffordanceFalsingFactor() {
+        return mStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f;
+    }
+
+    @Override
     protected float getPeekHeight() {
         if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
             return mNotificationStackScroller.getPeekHeight();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index 7f155a1d..84216a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -316,6 +316,11 @@
     }
 
     @Override
+    public float getFalsingThresholdFactor() {
+        return 1.0f;
+    }
+
+    @Override
     public void onChildDismissed(View v) {
         Log.v(TAG, "User swiped heads up to dismiss");
         mBar.onHeadsUpDismissed();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 67ba8d20..4a20406 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -547,6 +547,11 @@
         return false;
     }
 
+    @Override
+    public float getFalsingThresholdFactor() {
+        return mPhoneStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f;
+    }
+
     public void onBeginDrag(View v) {
         setSwipingInProgress(true);
         mAmbientState.onBeginDrag(v);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 006f5db..73ff066 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -4093,6 +4093,7 @@
             } else {
                 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
             }
+            mPowerManager.wakeUp(whenNanos / 1000000);
             mContext.startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
         }
         mCameraLensCoverState = lensCoverState;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4d2fd4c..f535791 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6316,7 +6316,12 @@
                 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
                 // Tell anyone interested that we are done booting!
                 SystemProperties.set("sys.boot_completed", "1");
-                SystemProperties.set("dev.bootcomplete", "1");
+
+                // And trigger dev.bootcomplete if we are not showing encryption progress
+                if (!"trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt"))
+                    || "".equals(SystemProperties.get("vold.encrypt_progress"))) {
+                    SystemProperties.set("dev.bootcomplete", "1");
+                }
                 for (int i=0; i<mStartedUsers.size(); i++) {
                     UserStartedState uss = mStartedUsers.valueAt(i);
                     if (uss.mState == UserStartedState.STATE_BOOTING) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a61d621..27184390 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10444,9 +10444,21 @@
         IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
                 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
         try {
-            if (dpm != null && (dpm.packageHasActiveAdmins(packageName, userId)
-                    || dpm.isDeviceOwner(packageName))) {
-                return true;
+            if (dpm != null) {
+                if (dpm.isDeviceOwner(packageName)) {
+                    return true;
+                }
+                int[] users;
+                if (userId == UserHandle.USER_ALL) {
+                    users = sUserManager.getUserIds();
+                } else {
+                    users = new int[]{userId};
+                }
+                for (int i = 0; i < users.length; ++i) {
+                    if (dpm.packageHasActiveAdmins(packageName, users[i])) {
+                        return true;
+                    }
+                }
             }
         } catch (RemoteException e) {
         }
@@ -10471,7 +10483,10 @@
         final PackageRemovedInfo info = new PackageRemovedInfo();
         final boolean res;
 
-        if (isPackageDeviceAdmin(packageName, userId)) {
+        final UserHandle removeForUser = (flags & PackageManager.DELETE_ALL_USERS) != 0
+                ? UserHandle.ALL : new UserHandle(userId);
+
+        if (isPackageDeviceAdmin(packageName, removeForUser.getIdentifier())) {
             Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
             return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
         }
@@ -10494,9 +10509,7 @@
 
         synchronized (mInstallLock) {
             if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
-            res = deletePackageLI(packageName,
-                    (flags & PackageManager.DELETE_ALL_USERS) != 0
-                            ? UserHandle.ALL : new UserHandle(userId),
+            res = deletePackageLI(packageName, removeForUser,
                     true, allUsers, perUserInstalled,
                     flags | REMOVE_CHATTY, info, true);
             systemUpdate = info.isRemovedPackageSystemUpdate;