Merge "Support to pass <uses-library> option through to dex2oat." into nyc-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index a8afd96..3344b52 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -48971,7 +48971,6 @@
     method public int getPackageId(android.content.res.Resources, java.lang.String);
     method public void invokeDrawGlFunctor(android.view.View, long, boolean);
     method public boolean isTraceTagEnabled();
-    method public java.lang.Runnable setDrawGlFunctionDetachedCallback(android.view.View, java.lang.Runnable);
     method public void setOnTraceEnabledChangeListener(android.webkit.WebViewDelegate.OnTraceEnabledChangeListener);
   }
 
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index f203f46..c14dec9 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -339,13 +339,16 @@
             }
         }
 
-        void cancel() {
+        boolean cancel() {
             if (DEBUG) Log.v(TAG, "  Canceling: " + this);
             if (mStarted && mLoader != null && mListenerRegistered) {
-                if (!mLoader.cancelLoad()) {
+                final boolean cancelLoadResult = mLoader.cancelLoad();
+                if (!cancelLoadResult) {
                     onLoadCanceled(mLoader);
                 }
+                return cancelLoadResult;
             }
+            return false;
         }
 
         void destroy() {
@@ -667,20 +670,21 @@
                     mInactiveLoaders.put(id, info);
                 } else {
                     // We already have an inactive loader for this ID that we are
-                    // waiting for!  What to do, what to do...
-                    if (!info.mStarted) {
-                        // The current Loader has not been started...  we thus
-                        // have no reason to keep it around, so bam, slam,
-                        // thank-you-ma'am.
+                    // waiting for! Try to cancel; if this returns true then the task is still
+                    // running and we have more work to do.
+                    if (!info.cancel()) {
+                        // The current Loader has not been started or was successfully canceled,
+                        // we thus have no reason to keep it around. Remove it and a new
+                        // LoaderInfo will be created below.
                         if (DEBUG) Log.v(TAG, "  Current loader is stopped; replacing");
                         mLoaders.put(id, null);
                         info.destroy();
                     } else {
                         // Now we have three active loaders... we'll queue
                         // up this request to be processed once one of the other loaders
-                        // finishes or is canceled.
-                        if (DEBUG) Log.v(TAG, "  Current loader is running; attempting to cancel");
-                        info.cancel();
+                        // finishes.
+                        if (DEBUG) Log.v(TAG,
+                                "  Current loader is running; configuring pending loader");
                         if (info.mPendingLoader != null) {
                             if (DEBUG) Log.v(TAG, "  Removing pending loader: " + info.mPendingLoader);
                             info.mPendingLoader.destroy();
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 9b1d462..177374c 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -87,7 +87,8 @@
      * resource qualifier.
      *
      * @deprecated Do not set or read this directly. Use {@link #getLocales()} and
-     * {@link #setLocales(LocaleList)}.
+     * {@link #setLocales(LocaleList)}. If only the primary locale is needed,
+     * <code>getLocales().get(0)</code> is now the preferred accessor.
      */
     @Deprecated public Locale locale;
 
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index cc82eb6..0f07419 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -912,9 +912,9 @@
      * its type and name.
      */
     public int getId() {
-        if (mUuid == ALL_0_UUID) {
+        if (mUuid.equals(ALL_0_UUID)) {
             return 0;
-        } else if (mUuid == ALL_F_UUID) {
+        } else if (mUuid.equals(ALL_F_UUID)) {
             return -1;
         } else {
             int id = Math.abs(mUuid.hashCode()) + 1;
@@ -1139,4 +1139,26 @@
                 return false;
         }
     }
+
+    /**
+     * Sets the UUID associated with the sensor.
+     *
+     * NOTE: to be used only by native bindings in SensorManager.
+     *
+     * @see #getUuid
+     * @see UUID
+     */
+    private void setUuid(long msb, long lsb) {
+        // reuse static object if possible
+        if (msb == lsb) {
+            if (msb == 0L) {
+                mUuid = ALL_0_UUID;
+                return;
+            } else if (msb == ~0L) {
+                mUuid = ALL_F_UUID;
+                return;
+            }
+        }
+        mUuid = new UUID(msb, lsb);
+    }
 }
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 49cb8e2..71b53f1 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -505,15 +505,14 @@
         return false;
     }
 
-    /*
-     * @deprecated
-     * Do not use. This function only reverses individual {@code char}s and not their associated
-     * spans. It doesn't support surrogate pairs (that correspond to non-BMP code points),
-     * combining sequences or conjuncts either.
+    /**
+     * This function only reverses individual {@code char}s and not their associated
+     * spans. It doesn't support surrogate pairs (that correspond to non-BMP code points), combining
+     * sequences or conjuncts either.
+     * @deprecated Do not use.
      */
     @Deprecated
-    public static CharSequence getReverse(CharSequence source,
-                                          int start, int end) {
+    public static CharSequence getReverse(CharSequence source, int start, int end) {
         return new Reverser(source, start, end);
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 5b757d3..4e7d1914 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3906,7 +3906,6 @@
      * cleanup.
      */
     final RenderNode mRenderNode;
-    private Runnable mRenderNodeDetachedCallback;
 
     /**
      * Set to true when the view is sending hover accessibility events because it
@@ -16065,20 +16064,6 @@
      * @hide
      */
     public void onRenderNodeDetached(RenderNode renderNode) {
-        if (renderNode == mRenderNode && mRenderNodeDetachedCallback != null) {
-            mRenderNodeDetachedCallback.run();
-        }
-    }
-
-    /**
-     * Set callback for functor detach. Exposed to WebView through WebViewDelegate.
-     * Should not be used otherwise.
-     * @hide
-     */
-    public final Runnable setRenderNodeDetachedCallback(@Nullable Runnable callback) {
-        Runnable oldCallback = mRenderNodeDetachedCallback;
-        mRenderNodeDetachedCallback = callback;
-        return oldCallback;
     }
 
     /**
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 9595db2..49effe4 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -16,9 +16,15 @@
 
 package android.webkit;
 
+import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.content.Context;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
 /**
  * Manages settings state for a WebView. When a WebView is first created, it
  * obtains a set of default settings. These default settings will be returned
@@ -1362,18 +1368,32 @@
     public abstract boolean getOffscreenPreRaster();
 
     /**
+     * @hide
+     */
+    @IntDef(flag = true,
+            value = {
+                    MENU_ITEM_NONE,
+                    MENU_ITEM_SHARE,
+                    MENU_ITEM_WEB_SEARCH,
+                    MENU_ITEM_PROCESS_TEXT
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    @Target({ElementType.PARAMETER, ElementType.METHOD})
+    private @interface MenuItemFlags {}
+
+    /**
      * Disables the action mode menu items according to {@code menuItems} flag.
      * @param menuItems an integer field flag for the menu items to be disabled.
      */
-    public abstract void setDisabledActionModeMenuItems(int menuItems);
+    public abstract void setDisabledActionModeMenuItems(@MenuItemFlags int menuItems);
 
     /**
      * Gets the action mode menu items that are disabled, expressed in an integer field flag.
      * The default value is {@link #MENU_ITEM_NONE}
      *
-     * @return all the disabled menu item flags combined with OR.
+     * @return all the disabled menu item flags combined with bitwise OR.
      */
-    public abstract int getDisabledActionModeMenuItems();
+    public abstract @MenuItemFlags int getDisabledActionModeMenuItems();
 
     /**
      * Used with {@link #setDisabledActionModeMenuItems}.
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 85d7cd0..9e73af2 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -131,24 +131,6 @@
     }
 
     /**
-     * Set the Runnable callback the DrawGlFunction functor is detached and free to be destroyed.
-     * This will replace the previous callback, if any.
-     *
-     * @param view The view to set the callback. Should be the view where onDraw inserted
-     *        DrawGLFunctor.
-     * @param callback The new callback to set on the view.
-     * @throws IllegalArgumentException if view is null.
-     * @return The previous callback on this view.
-     */
-    public Runnable setDrawGlFunctionDetachedCallback(
-        @NonNull View view, @Nullable Runnable callback) {
-        if (view == null) {
-            throw new IllegalArgumentException("View cannot be null");
-        }
-        return view.setRenderNodeDetachedCallback(callback);
-    }
-
-    /**
      * Detaches the draw GL functor.
      *
      * @param nativeDrawGLFunctor the pointer to the native functor that implements
diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp
index 2c840bd..d2d39cd 100644
--- a/core/jni/android/graphics/pdf/PdfEditor.cpp
+++ b/core/jni/android/graphics/pdf/PdfEditor.cpp
@@ -51,22 +51,22 @@
     jfieldID bottom;
 } gRectClassInfo;
 
-static Mutex sLock;
-
-static int sUnmatchedInitRequestCount = 0;
+// Also used in PdfRenderer.cpp
+Mutex sPdfiumLock;
+int sUnmatchedPdfiumInitRequestCount = 0;
 
 static void initializeLibraryIfNeeded() {
-    Mutex::Autolock _l(sLock);
-    if (sUnmatchedInitRequestCount == 0) {
+    Mutex::Autolock _l(sPdfiumLock);
+    if (sUnmatchedPdfiumInitRequestCount == 0) {
         FPDF_InitLibrary();
     }
-    sUnmatchedInitRequestCount++;
+    sUnmatchedPdfiumInitRequestCount++;
 }
 
 static void destroyLibraryIfNeeded() {
-    Mutex::Autolock _l(sLock);
-    sUnmatchedInitRequestCount--;
-    if (sUnmatchedInitRequestCount == 0) {
+    Mutex::Autolock _l(sPdfiumLock);
+    sUnmatchedPdfiumInitRequestCount--;
+    if (sUnmatchedPdfiumInitRequestCount == 0) {
        FPDF_DestroyLibrary();
     }
 }
diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp
index 27f3493..71bec78 100644
--- a/core/jni/android/graphics/pdf/PdfRenderer.cpp
+++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp
@@ -43,22 +43,22 @@
     jfieldID y;
 } gPointClassInfo;
 
-static Mutex sLock;
-
-static int sUnmatchedInitRequestCount = 0;
+// See PdfEditor.cpp
+extern Mutex sPdfiumLock;
+extern int sUnmatchedPdfiumInitRequestCount;
 
 static void initializeLibraryIfNeeded() {
-    Mutex::Autolock _l(sLock);
-    if (sUnmatchedInitRequestCount == 0) {
+    Mutex::Autolock _l(sPdfiumLock);
+    if (sUnmatchedPdfiumInitRequestCount == 0) {
         FPDF_InitLibrary();
     }
-    sUnmatchedInitRequestCount++;
+    sUnmatchedPdfiumInitRequestCount++;
 }
 
 static void destroyLibraryIfNeeded() {
-    Mutex::Autolock _l(sLock);
-    sUnmatchedInitRequestCount--;
-    if (sUnmatchedInitRequestCount == 0) {
+    Mutex::Autolock _l(sPdfiumLock);
+    sUnmatchedPdfiumInitRequestCount--;
+    if (sUnmatchedPdfiumInitRequestCount == 0) {
        FPDF_DestroyLibrary();
     }
 }
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 90f407f..9793cdb 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -50,6 +50,7 @@
 struct SensorOffsets
 {
     jclass      clazz;
+    //fields
     jfieldID    name;
     jfieldID    vendor;
     jfieldID    version;
@@ -64,7 +65,9 @@
     jfieldID    requiredPermission;
     jfieldID    maxDelay;
     jfieldID    flags;
+    //methods
     jmethodID   setType;
+    jmethodID   setUuid;
     jmethodID   init;
 } gSensorOffsets;
 
@@ -102,6 +105,7 @@
     sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags",  "I");
 
     sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
+    sensorOffsets.setUuid = _env->GetMethodID(sensorClass, "setUuid", "(JJ)V");
     sensorOffsets.init = _env->GetMethodID(sensorClass, "<init>", "()V");
 
     // java.util.List;
@@ -192,11 +196,26 @@
                             requiredPermission);
         env->SetIntField(sensor, sensorOffsets.maxDelay, nativeSensor.getMaxDelay());
         env->SetIntField(sensor, sensorOffsets.flags, nativeSensor.getFlags());
+
         if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
                 == JNI_FALSE) {
             jstring stringType = getInternedString(env, &nativeSensor.getStringType());
             env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
         }
+
+        // java.util.UUID constructor UUID(long a, long b) assumes the two long inputs a and b
+        // correspond to first half and second half of the 16-byte stream in big-endian,
+        // respectively, if the byte stream is serialized according to RFC 4122 (Sec. 4.1.2).
+        //
+        // For Java UUID 12345678-90AB-CDEF-1122-334455667788, the byte stream will be
+        // (uint8_t) {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, ....} according RFC 4122.
+        //
+        // According to Java UUID constructor document, the long parameter a should be always
+        // 0x12345678980ABCDEF regardless of host machine endianess. Thus, htobe64 is used to
+        // convert int64_t read directly, which will be in host-endian, to the big-endian required
+        // by Java constructor.
+        const int64_t (&uuid)[2] = nativeSensor.getUuid().i64;
+        env->CallVoidMethod(sensor, sensorOffsets.setUuid, htobe64(uuid[0]), htobe64(uuid[1]));
     }
     return sensor;
 }
@@ -212,32 +231,7 @@
         return false;
     }
 
-    Sensor const* const list = sensorList[index];
-    const SensorOffsets& sensorOffsets(gSensorOffsets);
-    jstring name = getInternedString(env, &list->getName());
-    jstring vendor = getInternedString(env, &list->getVendor());
-    jstring requiredPermission = getInternedString(env, &list->getRequiredPermission());
-    env->SetObjectField(sensor, sensorOffsets.name,      name);
-    env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);
-    env->SetIntField(sensor, sensorOffsets.version,      list->getVersion());
-    env->SetIntField(sensor, sensorOffsets.handle,       list->getHandle());
-    env->SetFloatField(sensor, sensorOffsets.range,      list->getMaxValue());
-    env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());
-    env->SetFloatField(sensor, sensorOffsets.power,      list->getPowerUsage());
-    env->SetIntField(sensor, sensorOffsets.minDelay,     list->getMinDelay());
-    env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
-                     list->getFifoReservedEventCount());
-    env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
-                     list->getFifoMaxEventCount());
-    env->SetObjectField(sensor, sensorOffsets.requiredPermission,
-                        requiredPermission);
-    env->SetIntField(sensor, sensorOffsets.maxDelay, list->getMaxDelay());
-    env->SetIntField(sensor, sensorOffsets.flags, list->getFlags());
-    if (env->CallBooleanMethod(sensor, sensorOffsets.setType, list->getType()) == JNI_FALSE) {
-        jstring stringType = getInternedString(env, &list->getStringType());
-        env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
-    }
-    return true;
+    return translateNativeSensorToJavaSensor(env, sensor, *sensorList[index]) != NULL;
 }
 
 static void
diff --git a/packages/SettingsLib/res/values-be-rBY/strings.xml b/packages/SettingsLib/res/values-be-rBY/strings.xml
index 75297d5..1c15082 100644
--- a/packages/SettingsLib/res/values-be-rBY/strings.xml
+++ b/packages/SettingsLib/res/values-be-rBY/strings.xml
@@ -91,7 +91,7 @@
     <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-мадэм"</string>
     <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Мадэм"</string>
     <string name="tether_settings_title_all" msgid="8356136101061143841">"Мадэм і партатыўны хотспот"</string>
-    <string name="managed_user_title" msgid="8109605045406748842">"Усе рабочыя праграмы"</string>
+    <string name="managed_user_title" msgid="8109605045406748842">"Усе працоўныя праграмы"</string>
     <string name="user_guest" msgid="8475274842845401871">"Госць"</string>
     <string name="unknown" msgid="1592123443519355854">"Невядома"</string>
     <string name="running_process_item_user_label" msgid="3129887865552025943">"Карыстальнiк: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
@@ -123,7 +123,7 @@
     <string name="tts_engine_settings_button" msgid="1030512042040722285">"Запуск налад модулю"</string>
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Выбраны модуль"</string>
     <string name="tts_general_section_title" msgid="4402572014604490502">"Агульныя"</string>
-    <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Скід вышыні голасу падчас гаворкі"</string>
+    <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Скід вышыні голасу падчас маўлення"</string>
     <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Скінуць вышыню голасу, з якой прагаворваецца тэкст, да стандартнай."</string>
   <string-array name="tts_rate_entries">
     <item msgid="6695494874362656215">"Вельмі павольна"</item>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index 4ac1d83..6340d50 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -124,7 +124,7 @@
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motor hobetsia"</string>
     <string name="tts_general_section_title" msgid="4402572014604490502">"Orokorra"</string>
     <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Berrezarri ahots-tonua"</string>
-    <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Berrezarri testua esateko ahots-tonua lehenetsira."</string>
+    <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Berrezarri testua esateko ahots-tonu lehenetsia."</string>
   <string-array name="tts_rate_entries">
     <item msgid="6695494874362656215">"Oso motela"</item>
     <item msgid="4795095314303559268">"Motela"</item>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index 48718f1..f6a7592 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -124,7 +124,7 @@
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Тандалган жарак"</string>
     <string name="tts_general_section_title" msgid="4402572014604490502">"Жалпы"</string>
     <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Сүйлөө тонун баштапкы абалга келтирүү"</string>
-    <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Текст айтылчу тонду демейки тоного коюңуз."</string>
+    <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Текст айтылчу тонду демейки тонго коюңуз."</string>
   <string-array name="tts_rate_entries">
     <item msgid="6695494874362656215">"Өтө жай"</item>
     <item msgid="4795095314303559268">"Жай"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 25aa283..64dd02b 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -124,7 +124,7 @@
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Preferovaný nástroj"</string>
     <string name="tts_general_section_title" msgid="4402572014604490502">"Všeobecné"</string>
     <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Obnoviť výšku hlasu"</string>
-    <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Obnovte predvolenú výšku hlasu vyslovujúceho text"</string>
+    <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Obnovte predvolenú výšku hlasu vyslovujúceho text."</string>
   <string-array name="tts_rate_entries">
     <item msgid="6695494874362656215">"Veľmi pomaly"</item>
     <item msgid="4795095314303559268">"Pomaly"</item>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index 35aff21..dded595 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -15,6 +15,8 @@
 package com.android.systemui.qs.tiles;
 
 import android.content.Intent;
+
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
@@ -52,6 +54,7 @@
     @Override
     protected void handleClick() {
         mState.value = !mDataSaverController.isDataSaverEnabled();
+        MetricsLogger.action(mContext, getMetricsCategory(), mState.value);
         mDataSaverController.setDataSaverEnabled(mState.value);
         refreshState(mState.value);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index 9842634..74f0cd3 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -267,6 +267,9 @@
     void movePipToFullscreen() {
         mState = STATE_NO_PIP;
         mPipTaskId = TASK_ID_NO_PIP;
+        for (int i = mListeners.size() - 1; i >= 0; --i) {
+            mListeners.get(i).onMoveToFullscreen();
+        }
         resizePinnedStack(mState);
     }
 
@@ -627,11 +630,6 @@
         public void onPinnedStackAnimationEnded() {
             if (DEBUG) Log.d(TAG, "onPinnedStackAnimationEnded()");
             switch (mState) {
-                case STATE_NO_PIP:
-                    for (int i = mListeners.size() - 1; i >= 0; --i) {
-                        mListeners.get(i).onMoveToFullscreen();
-                    }
-                    break;
                 case STATE_PIP_OVERLAY:
                     if (!mPipRecentsOverlayManager.isRecentsShown()) {
                         showPipOverlay();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 66bc51c..f192a9d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2997,7 +2997,11 @@
     }
 
     boolean switchUserLocked(int userId, UserState uss) {
-        mUserStackInFront.put(mCurrentUser, mFocusedStack.getStackId());
+        final int focusStackId = mFocusedStack.getStackId();
+        // We dismiss the docked stack whenever we switch users.
+        moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, focusStackId == DOCKED_STACK_ID);
+
+        mUserStackInFront.put(mCurrentUser, focusStackId);
         final int restoreStackId = mUserStackInFront.get(userId, HOME_STACK_ID);
         mCurrentUser = userId;
 
@@ -3510,7 +3514,7 @@
 
             // Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
             // we need to move it to top of fullscreen stack, otherwise it will be covered.
-            mService.moveTasksToFullscreenStack(DOCKED_STACK_ID, actualStackId == DOCKED_STACK_ID);
+            moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, actualStackId == DOCKED_STACK_ID);
         } else if (task.mResizeMode == RESIZE_MODE_FORCE_RESIZEABLE) {
             String packageName = task.getTopActivity() != null
                     ? task.getTopActivity().appInfo.packageName : null;
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 1f44b29..debb382 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -149,15 +149,11 @@
         public void onAnimationEnd(Animator animation) {
             if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
                     + " mMoveToFullScreen=" + mMoveToFullScreen + " mWillReplace=" + mWillReplace);
+
+            finishAnimation();
             if (mMoveToFullScreen && !mWillReplace) {
                 mTarget.moveToFullscreen();
             }
-
-            // If we finish the animation before we move the target to fullscreen,
-            // recents may close itself and we may try and resume the previous
-            // fullscreen app leading to churn and flicker after we then move
-            // our target to fullscreen.
-            finishAnimation();
         }
 
         @Override