Merge "Turn off HWUI_ENABLE_OPENGL_VALIDATION" into nyc-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 915ceb2..39b1c2c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -25315,6 +25315,41 @@
     method public void onTetheringStarted();
   }
 
+  public final class ConnectivityMetricsEvent implements android.os.Parcelable {
+    ctor public ConnectivityMetricsEvent(long, int, int, android.os.Parcelable);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.ConnectivityMetricsEvent> CREATOR;
+    field public final int componentTag;
+    field public final android.os.Parcelable data;
+    field public final int eventTag;
+    field public final long timestamp;
+  }
+
+  public static final class ConnectivityMetricsEvent.Reference implements android.os.Parcelable {
+    ctor public ConnectivityMetricsEvent.Reference(long);
+    method public int describeContents();
+    method public long getValue();
+    method public void readFromParcel(android.os.Parcel);
+    method public void setValue(long);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.ConnectivityMetricsEvent.Reference> CREATOR;
+  }
+
+  public class ConnectivityMetricsLogger {
+    ctor public ConnectivityMetricsLogger();
+    method public void logEvent(long, int, int, android.os.Parcelable);
+    field public static final int COMPONENT_TAG_BLUETOOTH = 1; // 0x1
+    field public static final int COMPONENT_TAG_CONNECTIVITY = 0; // 0x0
+    field public static final int COMPONENT_TAG_TELECOM = 3; // 0x3
+    field public static final int COMPONENT_TAG_TELEPHONY = 4; // 0x4
+    field public static final int COMPONENT_TAG_WIFI = 2; // 0x2
+    field public static final java.lang.String CONNECTIVITY_METRICS_LOGGER_SERVICE = "connectivity_metrics_logger";
+    field public static final java.lang.String DATA_KEY_EVENTS_COUNT = "count";
+    field public static final int NUMBER_OF_COMPONENTS = 5; // 0x5
+    field public static final int TAG_SKIPPED_EVENTS = -1; // 0xffffffff
+  }
+
   public class Credentials {
     ctor public Credentials(int, int, int);
     method public int getGid();
@@ -26387,9 +26422,11 @@
     field public int bwSupported;
     field public boolean lciSupported;
     field public boolean lcrSupported;
+    field public int mcVersion;
     field public boolean oneSidedRttSupported;
     field public int preambleSupported;
     field public boolean responderSupported;
+    field public boolean secureRttSupported;
     field public deprecated boolean supportedPeerType;
     field public deprecated boolean supportedType;
     field public boolean twoSided11McRttSupported;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index aa1e372..4108f6d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1210,7 +1210,7 @@
             // For those APKs we only care about extracting signer certificates, and don't care
             // about verifying integrity.
             boolean signatureSchemeRollbackProtectionsEnforced =
-                    (parseFlags & PARSE_IS_SYSTEM) == 0;
+                    (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
             jarFile = new StrictJarFile(
                     apkPath,
                     !verified, // whether to verify JAR signature
@@ -1239,7 +1239,7 @@
             toVerify.add(manifestEntry);
 
             // If we're parsing an untrusted package, verify all contents
-            if ((parseFlags & PARSE_IS_SYSTEM) == 0) {
+            if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
                 final Iterator<ZipEntry> i = jarFile.iterator();
                 while (i.hasNext()) {
                     final ZipEntry entry = i.next();
@@ -1679,7 +1679,6 @@
     private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
             XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
             IOException {
-        final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0;
         mParseInstrumentationArgs = null;
         mParseActivityArgs = null;
         mParseServiceArgs = null;
@@ -1769,8 +1768,6 @@
                     return null;
                 }
             } else if (tagName.equals(TAG_OVERLAY)) {
-                pkg.mTrustedOverlay = trustedOverlay;
-
                 sa = res.obtainAttributes(parser,
                         com.android.internal.R.styleable.AndroidManifestResourceOverlay);
                 pkg.mOverlayTarget = sa.getString(
@@ -2924,12 +2921,14 @@
             ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
         }
 
-        if (sa.getBoolean(R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
-                false) && (flags & PARSE_IS_SYSTEM) != 0) {
+        if (sa.getBoolean(
+                R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
+                false)) {
             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
         }
-        if (sa.getBoolean(R.styleable.AndroidManifestApplication_directBootAware, false)
-                && (flags & PARSE_IS_SYSTEM) != 0) {
+        if (sa.getBoolean(
+                R.styleable.AndroidManifestApplication_directBootAware,
+                false)) {
             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
         }
 
@@ -3554,7 +3553,7 @@
 
             a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
                     R.styleable.AndroidManifestActivity_directBootAware,
-                    owner.applicationInfo.isDirectBootAware());
+                    false);
         } else {
             a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
             a.info.configChanges = 0;
@@ -3572,7 +3571,7 @@
 
             a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
                     R.styleable.AndroidManifestActivity_directBootAware,
-                    owner.applicationInfo.isDirectBootAware());
+                    false);
         }
 
         if (a.info.directBootAware) {
@@ -3985,7 +3984,7 @@
 
         p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
                 R.styleable.AndroidManifestProvider_directBootAware,
-                owner.applicationInfo.isDirectBootAware());
+                false);
         if (p.info.directBootAware) {
             owner.applicationInfo.privateFlags |=
                     ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
@@ -4277,7 +4276,7 @@
 
         s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
                 R.styleable.AndroidManifestService_directBootAware,
-                owner.applicationInfo.isDirectBootAware());
+                false);
         if (s.info.directBootAware) {
             owner.applicationInfo.privateFlags |=
                     ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index b5d67d3..5153ba9 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -16,10 +16,12 @@
 
 package android.net;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 /** {@hide} */
+@SystemApi
 public final class ConnectivityMetricsEvent implements Parcelable {
 
     /**  The time when this event was collected, as returned by System.currentTimeMillis(). */
@@ -80,12 +82,13 @@
     }
 
     /** {@hide} */
-    public static class Reference implements Parcelable {
+    @SystemApi
+    public final static class Reference implements Parcelable {
 
-        public long value;
+        private long mValue;
 
         public Reference(long ref) {
-            this.value = ref;
+            this.mValue = ref;
         }
 
         /** Implement the Parcelable interface */
@@ -109,11 +112,19 @@
         /** Implement the Parcelable interface */
         @Override
         public void writeToParcel(Parcel dest, int flags) {
-            dest.writeLong(value);
+            dest.writeLong(mValue);
         }
 
         public void readFromParcel(Parcel in) {
-            value = in.readLong();
+            mValue = in.readLong();
+        }
+
+        public long getValue() {
+            return mValue;
+        }
+
+        public void setValue(long val) {
+            mValue = val;
         }
     }
 }
diff --git a/core/java/android/net/ConnectivityMetricsLogger.java b/core/java/android/net/ConnectivityMetricsLogger.java
index eafb8ac..b49cc2b 100644
--- a/core/java/android/net/ConnectivityMetricsLogger.java
+++ b/core/java/android/net/ConnectivityMetricsLogger.java
@@ -15,6 +15,7 @@
  */
 package android.net;
 
+import android.annotation.SystemApi;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.RemoteException;
@@ -22,6 +23,7 @@
 import android.util.Log;
 
 /** {@hide} */
+@SystemApi
 public class ConnectivityMetricsLogger {
     private static String TAG = "ConnectivityMetricsLogger";
     private static final boolean DBG = true;
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 080ed9a..2481e04 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -163,17 +163,33 @@
     ///////////////////////////////////////////////////////////////////////////
 
     /**
-     * Calls the function specified with the drawGLFunction function pointer. This is
-     * functionality used by webkit for calling into their renderer from our display lists.
-     * This function may return true if an invalidation is needed after the call.
+     * Records the functor specified with the drawGLFunction function pointer. This is
+     * functionality used by webview for calling into their renderer from our display lists.
      *
      * @param drawGLFunction A native function pointer
      */
     public void callDrawGLFunction2(long drawGLFunction) {
-        nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction);
+        nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction, null);
     }
 
-    private static native void nCallDrawGLFunction(long renderer, long drawGLFunction);
+    /**
+     * Records the functor specified with the drawGLFunction function pointer. This is
+     * functionality used by webview for calling into their renderer from our display lists.
+     *
+     * @param drawGLFunction A native function pointer
+     * @param releasedCallback Called when the display list is destroyed, and thus
+     * the functor is no longer referenced by this canvas's display list.
+     *
+     * NOTE: The callback does *not* necessarily mean that there are no longer
+     * any references to the functor, just that the reference from this specific
+     * canvas's display list has been released.
+     */
+    public void drawGLFunctor2(long drawGLFunctor, Runnable releasedCallback) {
+        nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunctor, releasedCallback);
+    }
+
+    private static native void nCallDrawGLFunction(long renderer,
+            long drawGLFunction, Runnable releasedCallback);
 
     ///////////////////////////////////////////////////////////////////////////
     // Display list
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index 6aac0e4..cadfd3d 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -22,12 +22,12 @@
 
 #include <android_runtime/AndroidRuntime.h>
 
+#include <utils/Looper.h>
 #include <cutils/properties.h>
 
 #include <SkBitmap.h>
 #include <SkRegion.h>
 
-
 #include <Rect.h>
 #include <RenderNode.h>
 #include <CanvasProperty.h>
@@ -41,6 +41,52 @@
 
 using namespace uirenderer;
 
+jmethodID gRunnableMethodId;
+
+static JNIEnv* jnienv(JavaVM* vm) {
+    JNIEnv* env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
+    }
+    return env;
+}
+
+class InvokeRunnableMessage : public MessageHandler {
+public:
+    InvokeRunnableMessage(JNIEnv* env, jobject runnable) {
+        mRunnable = env->NewGlobalRef(runnable);
+        env->GetJavaVM(&mVm);
+    }
+
+    virtual ~InvokeRunnableMessage() {
+        jnienv(mVm)->DeleteGlobalRef(mRunnable);
+    }
+
+    virtual void handleMessage(const Message&) {
+        jnienv(mVm)->CallVoidMethod(mRunnable, gRunnableMethodId);
+    }
+
+private:
+    JavaVM* mVm;
+    jobject mRunnable;
+};
+
+class GlFunctorReleasedCallbackBridge : public GlFunctorLifecycleListener {
+public:
+    GlFunctorReleasedCallbackBridge(JNIEnv* env, jobject javaCallback) {
+        mLooper = Looper::getForThread();
+        mMessage = new InvokeRunnableMessage(env, javaCallback);
+    }
+
+    virtual void onGlFunctorReleased(Functor* functor) override {
+        mLooper->sendMessage(mMessage, 0);
+    }
+
+private:
+    sp<Looper> mLooper;
+    sp<InvokeRunnableMessage> mMessage;
+};
+
 // ----------------------------------------------------------------------------
 // Setup
 // ----------------------------------------------------------------------------
@@ -56,10 +102,12 @@
 // ----------------------------------------------------------------------------
 
 static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
-        jlong canvasPtr, jlong functorPtr) {
+        jlong canvasPtr, jlong functorPtr, jobject releasedCallback) {
     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
-    canvas->callDrawGLFunction(functor);
+    sp<GlFunctorReleasedCallbackBridge> bridge(new GlFunctorReleasedCallbackBridge(
+            env, releasedCallback));
+    canvas->callDrawGLFunction(functor, bridge.get());
 }
 
 // ----------------------------------------------------------------------------
@@ -184,7 +232,8 @@
     { "nIsAvailable",       "!()Z",             (void*) android_view_DisplayListCanvas_isAvailable },
     { "nInsertReorderBarrier","!(JZ)V",         (void*) android_view_DisplayListCanvas_insertReorderBarrier },
 
-    { "nCallDrawGLFunction", "!(JJ)V",          (void*) android_view_DisplayListCanvas_callDrawGLFunction },
+    { "nCallDrawGLFunction", "!(JJLjava/lang/Runnable;)V",
+            (void*) android_view_DisplayListCanvas_callDrawGLFunction },
 
     { "nDrawRoundRect",     "!(JJJJJJJJ)V",     (void*) android_view_DisplayListCanvas_drawRoundRectProps },
     { "nDrawCircle",        "!(JJJJJ)V",        (void*) android_view_DisplayListCanvas_drawCircleProps },
@@ -207,6 +256,9 @@
 };
 
 int register_android_view_DisplayListCanvas(JNIEnv* env) {
+    jclass runnableClass = FindClassOrDie(env, "java/lang/Runnable");
+    gRunnableMethodId = GetMethodIDOrDie(env, runnableClass, "run", "()V");
+
     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
 }
 
diff --git a/core/res/res/layout/floating_popup_overflow_button.xml b/core/res/res/layout/floating_popup_overflow_button.xml
index 7053f3e..12e2000 100644
--- a/core/res/res/layout/floating_popup_overflow_button.xml
+++ b/core/res/res/layout/floating_popup_overflow_button.xml
@@ -24,5 +24,5 @@
     android:paddingEnd="@dimen/floating_toolbar_menu_button_side_padding"
     android:paddingBottom="@dimen/floating_toolbar_menu_image_button_vertical_padding"
     android:scaleType="centerInside"
-    android:background="?attr/selectableItemBackgroundBorderless"
+    android:background="?attr/actionBarItemBackground"
     android:tint="?attr/floatingToolbarForegroundColor" />
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 181b343..b572bda 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -73,6 +73,12 @@
         delete path;
     }
 
+    for (auto& iter : functors) {
+        if (iter.listener) {
+            iter.listener->onGlFunctorReleased(iter.functor);
+        }
+    }
+
     patchResources.clear();
     pathResources.clear();
     paints.clear();
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index aba5d4b..5b3227b 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -35,6 +35,7 @@
 #include "Debug.h"
 #include "CanvasProperty.h"
 #include "DeferredDisplayList.h"
+#include "GlFunctorLifecycleListener.h"
 #include "Matrix.h"
 #include "RenderProperties.h"
 
@@ -119,6 +120,11 @@
     virtual void operator ()() {}
 };
 
+struct FunctorContainer {
+    Functor* functor;
+    GlFunctorLifecycleListener* listener;
+};
+
 /**
  * Data structure that holds the list of commands used in display list stream
  */
@@ -154,7 +160,7 @@
     const LsaVector<NodeOpType*>& getChildren() const { return children; }
 
     const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; }
-    const LsaVector<Functor*>& getFunctors() const { return functors; }
+    const LsaVector<FunctorContainer>& getFunctors() const { return functors; }
     const LsaVector<PushStagingFunctor*>& getPushStagingFunctors() { return pushStagingFunctors; }
 
     size_t addChild(NodeOpType* childOp);
@@ -195,7 +201,7 @@
     LsaVector< sp<VirtualLightRefBase> > referenceHolders;
 
     // List of functors
-    LsaVector<Functor*> functors;
+    LsaVector<FunctorContainer> functors;
 
     // List of functors that need to be notified of pushStaging. Note that this list gets nothing
     // but a callback during sync DisplayList, unlike the list of functors defined above, which
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index c6e92ab..ca968ce 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -81,9 +81,11 @@
     return displayList;
 }
 
-void DisplayListCanvas::callDrawGLFunction(Functor *functor) {
+void DisplayListCanvas::callDrawGLFunction(Functor* functor,
+        GlFunctorLifecycleListener* listener) {
     addDrawOp(new (alloc()) DrawFunctorOp(functor));
-    mDisplayList->functors.push_back(functor);
+    mDisplayList->functors.push_back({functor, listener});
+    mDisplayList->ref(listener);
 }
 
 SkCanvas* DisplayListCanvas::asSkCanvas() {
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index d6a5794..664f79e 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -93,7 +93,8 @@
 // ----------------------------------------------------------------------------
     virtual void drawLayer(DeferredLayerUpdater* layerHandle) override;
     virtual void drawRenderNode(RenderNode* renderNode) override;
-    virtual void callDrawGLFunction(Functor* functor) override;
+    virtual void callDrawGLFunction(Functor* functor,
+            GlFunctorLifecycleListener* listener) override;
 
 // ----------------------------------------------------------------------------
 // CanvasStateClient interface
diff --git a/libs/hwui/GlFunctorLifecycleListener.h b/libs/hwui/GlFunctorLifecycleListener.h
new file mode 100644
index 0000000..357090e
--- /dev/null
+++ b/libs/hwui/GlFunctorLifecycleListener.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#include <utils/Functor.h>
+#include <utils/RefBase.h>
+
+namespace android {
+namespace uirenderer {
+
+class GlFunctorLifecycleListener : public VirtualLightRefBase {
+public:
+    virtual ~GlFunctorLifecycleListener() {}
+    virtual void onGlFunctorReleased(Functor* functor) = 0;
+};
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index ab733f1..b49f9b5 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -594,8 +594,10 @@
             layerHandle->backingLayer()));
 }
 
-void RecordingCanvas::callDrawGLFunction(Functor* functor) {
-    mDisplayList->functors.push_back(functor);
+void RecordingCanvas::callDrawGLFunction(Functor* functor,
+        GlFunctorLifecycleListener* listener) {
+    mDisplayList->functors.push_back({functor, listener});
+    mDisplayList->ref(listener);
     addOp(alloc().create_trivial<FunctorOp>(
             *(mState.currentSnapshot()->transform),
             getRecordedClip(),
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 219296c..372be24 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -59,7 +59,8 @@
 
     virtual void drawLayer(DeferredLayerUpdater* layerHandle) override;
     virtual void drawRenderNode(RenderNode* renderNode) override;
-    virtual void callDrawGLFunction(Functor* functor) override;
+    virtual void callDrawGLFunction(Functor* functor,
+            GlFunctorLifecycleListener* listener) override;
 
 // ----------------------------------------------------------------------------
 // CanvasStateClient interface
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index ea06fcd..6e848fd 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -474,8 +474,8 @@
     mDisplayList = mStagingDisplayList;
     mStagingDisplayList = nullptr;
     if (mDisplayList) {
-        for (size_t i = 0; i < mDisplayList->getFunctors().size(); i++) {
-            (*mDisplayList->getFunctors()[i])(DrawGlInfo::kModeSync, nullptr);
+        for (auto& iter : mDisplayList->getFunctors()) {
+            (*iter.functor)(DrawGlInfo::kModeSync, nullptr);
         }
         for (size_t i = 0; i < mDisplayList->getPushStagingFunctors().size(); i++) {
             (*mDisplayList->getPushStagingFunctors()[i])();
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 1b459c1..ce67554 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -160,7 +160,8 @@
 
     virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
     virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
-    virtual void callDrawGLFunction(Functor* functor) override;
+    virtual void callDrawGLFunction(Functor* functor,
+            uirenderer::GlFunctorLifecycleListener* listener) override;
 
 protected:
     virtual void drawGlyphs(const uint16_t* text, const float* positions, int count,
@@ -846,6 +847,7 @@
 
 void SkiaCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) { }
 
-void SkiaCanvas::callDrawGLFunction(Functor* functor) { }
+void SkiaCanvas::callDrawGLFunction(Functor* functor,
+        uirenderer::GlFunctorLifecycleListener* listener) { }
 
 } // namespace android
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 691cfa0..1c6f48e 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -219,22 +219,24 @@
             int fillType = 0; /* non-zero or kWinding_FillType in Skia */
         };
         FullPathProperties(Node* mNode) : Properties(mNode), mTrimDirty(false) {}
+        ~FullPathProperties() {
+            SkSafeUnref(fillGradient);
+            SkSafeUnref(strokeGradient);
+        }
         void syncProperties(const FullPathProperties& prop) {
             mPrimitiveFields = prop.mPrimitiveFields;
             mTrimDirty = true;
-            fillGradient.reset(prop.fillGradient);
-            strokeGradient.reset(prop.strokeGradient);
+            UPDATE_SKPROP(fillGradient, prop.fillGradient);
+            UPDATE_SKPROP(strokeGradient, prop.strokeGradient);
             onPropertyChanged();
         }
         void setFillGradient(SkShader* gradient) {
-            if(fillGradient != gradient){
-                fillGradient.reset(gradient);
+            if(UPDATE_SKPROP(fillGradient, gradient)) {
                 onPropertyChanged();
             }
         }
         void setStrokeGradient(SkShader* gradient) {
-            if(strokeGradient != gradient){
-                strokeGradient.reset(gradient);
+            if(UPDATE_SKPROP(strokeGradient, gradient)) {
                 onPropertyChanged();
             }
         }
@@ -346,8 +348,8 @@
             count,
         };
         PrimitiveFields mPrimitiveFields;
-        SkAutoTUnref<SkShader> fillGradient;
-        SkAutoTUnref<SkShader> strokeGradient;
+        SkShader* fillGradient = nullptr;
+        SkShader* strokeGradient = nullptr;
     };
 
     // Called from UI thread
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 5dbda43..55af33e 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -20,6 +20,7 @@
 #include <cutils/compiler.h>
 #include <utils/Functor.h>
 
+#include "GlFunctorLifecycleListener.h"
 #include "utils/NinePatch.h"
 
 #include <SkBitmap.h>
@@ -124,7 +125,8 @@
 
     virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) = 0;
     virtual void drawRenderNode(uirenderer::RenderNode* renderNode) = 0;
-    virtual void callDrawGLFunction(Functor* functor) = 0;
+    virtual void callDrawGLFunction(Functor* functor,
+            uirenderer::GlFunctorLifecycleListener* listener) = 0;
 
 // ----------------------------------------------------------------------------
 // Canvas state operations
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 209a104..ebc1c80 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -581,7 +581,7 @@
     auto scrolledFunctorView = TestUtils::createNode(0, 0, 400, 1000000,
             [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) {
         canvas.translate(0, -800000);
-        canvas.callDrawGLFunction(&noopFunctor);
+        canvas.callDrawGLFunction(&noopFunctor, nullptr);
     });
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index 7c57a50..b2997df 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -51,3 +51,41 @@
     EXPECT_FALSE(child->hasParents()) << "Child should be removed";
     EXPECT_FALSE(parent->hasParents()) << "Root node shouldn't have any parents";
 }
+
+TEST(RenderNode, releasedCallback) {
+    class DecRefOnReleased : public GlFunctorLifecycleListener {
+    public:
+        DecRefOnReleased(int* refcnt) : mRefCnt(refcnt) {}
+        void onGlFunctorReleased(Functor* functor) override {
+            *mRefCnt -= 1;
+        }
+    private:
+        int* mRefCnt;
+    };
+
+    int refcnt = 0;
+    sp<DecRefOnReleased> listener(new DecRefOnReleased(&refcnt));
+    Functor noopFunctor;
+
+    auto node = TestUtils::createNode(0, 0, 200, 400,
+            [&](RenderProperties& props, TestCanvas& canvas) {
+        refcnt++;
+        canvas.callDrawGLFunction(&noopFunctor, listener.get());
+    });
+    TestUtils::syncHierarchyPropertiesAndDisplayList(node);
+    EXPECT_EQ(1, refcnt);
+
+    TestUtils::recordNode(*node, [&](TestCanvas& canvas) {
+        refcnt++;
+        canvas.callDrawGLFunction(&noopFunctor, listener.get());
+    });
+    EXPECT_EQ(2, refcnt);
+
+    TestUtils::syncHierarchyPropertiesAndDisplayList(node);
+    EXPECT_EQ(1, refcnt);
+
+    TestUtils::recordNode(*node, [](TestCanvas& canvas) {});
+    EXPECT_EQ(1, refcnt);
+    TestUtils::syncHierarchyPropertiesAndDisplayList(node);
+    EXPECT_EQ(0, refcnt);
+}
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 7c6adad..2cd9872 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -27,6 +27,7 @@
 import android.media.MediaDescription;
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -475,14 +476,8 @@
         // the service will be told when we connect.
         if (mState == CONNECT_STATE_CONNECTED) {
             try {
-                // NOTE: Do not call addSubscriptionWithOptions when options are null. Otherwise,
-                // it will break the action of support library which expects addSubscription will
-                // be called when options are null.
-                if (options == null) {
-                    mServiceBinder.addSubscription(parentId, mServiceCallbacks);
-                } else {
-                    mServiceBinder.addSubscriptionWithOptions(parentId, options, mServiceCallbacks);
-                }
+                mServiceBinder.addSubscription(parentId, callback.mToken, options,
+                        mServiceCallbacks);
             } catch (RemoteException ex) {
                 // Process is crashing. We will disconnect, and upon reconnect we will
                 // automatically reregister. So nothing to do here.
@@ -497,34 +492,37 @@
             throw new IllegalArgumentException("parentId is empty.");
         }
 
-        // Remove from our list.
         Subscription sub = mSubscriptions.get(parentId);
-
+        if (sub == null) {
+            return;
+        }
         // Tell the service if necessary.
-        if (mState == CONNECT_STATE_CONNECTED && sub != null) {
-            try {
-                if (callback == null) {
-                    mServiceBinder.removeSubscription(parentId, mServiceCallbacks);
-                } else {
-                    final List<SubscriptionCallback> callbacks = sub.getCallbacks();
-                    final List<Bundle> optionsList = sub.getOptionsList();
-                    for (int i = callbacks.size() - 1; i >= 0; --i) {
-                        if (callbacks.get(i) == callback) {
-                            mServiceBinder.removeSubscriptionWithOptions(
-                                    parentId, optionsList.get(i), mServiceCallbacks);
-                            callbacks.remove(i);
-                            optionsList.remove(i);
+        try {
+            if (callback == null) {
+                if (mState == CONNECT_STATE_CONNECTED) {
+                    mServiceBinder.removeSubscription(parentId, null, mServiceCallbacks);
+                }
+            } else {
+                final List<SubscriptionCallback> callbacks = sub.getCallbacks();
+                final List<Bundle> optionsList = sub.getOptionsList();
+                for (int i = callbacks.size() - 1; i >= 0; --i) {
+                    if (callbacks.get(i) == callback) {
+                        if (mState == CONNECT_STATE_CONNECTED) {
+                            mServiceBinder.removeSubscription(
+                                    parentId, callback.mToken, mServiceCallbacks);
                         }
+                        callbacks.remove(i);
+                        optionsList.remove(i);
                     }
                 }
-            } catch (RemoteException ex) {
-                // Process is crashing. We will disconnect, and upon reconnect we will
-                // automatically reregister. So nothing to do here.
-                Log.d(TAG, "removeSubscription failed with RemoteException parentId=" + parentId);
             }
+        } catch (RemoteException ex) {
+            // Process is crashing. We will disconnect, and upon reconnect we will
+            // automatically reregister. So nothing to do here.
+            Log.d(TAG, "removeSubscription failed with RemoteException parentId=" + parentId);
         }
 
-        if (sub != null && (sub.isEmpty() || callback == null)) {
+        if (sub.isEmpty() || callback == null) {
             mSubscriptions.remove(parentId);
         }
     }
@@ -579,17 +577,12 @@
                 for (Entry<String, Subscription> subscriptionEntry : mSubscriptions.entrySet()) {
                     String id = subscriptionEntry.getKey();
                     Subscription sub = subscriptionEntry.getValue();
-                    for (Bundle options : sub.getOptionsList()) {
+                    List<SubscriptionCallback> callbackList = sub.getCallbacks();
+                    List<Bundle> optionsList = sub.getOptionsList();
+                    for (int i = 0; i < callbackList.size(); ++i) {
                         try {
-                            // NOTE: Do not call addSubscriptionWithOptions when options are null.
-                            // Otherwise, it will break the action of support library which expects
-                            // addSubscription will be called when options are null.
-                            if (options == null) {
-                                mServiceBinder.addSubscription(id, mServiceCallbacks);
-                            } else {
-                                mServiceBinder.addSubscriptionWithOptions(
-                                        id, options, mServiceCallbacks);
-                            }
+                            mServiceBinder.addSubscription(id, callbackList.get(i).mToken,
+                                    optionsList.get(i), mServiceCallbacks);
                         } catch (RemoteException ex) {
                             // Process is crashing. We will disconnect, and upon reconnect we will
                             // automatically reregister. So nothing to do here.
@@ -859,6 +852,12 @@
      * Callbacks for subscription related events.
      */
     public static abstract class SubscriptionCallback {
+        Binder mToken;
+
+        public SubscriptionCallback() {
+            mToken = new Binder();
+        }
+
         /**
          * Called when the list of children is loaded or updated.
          *
@@ -1071,12 +1070,7 @@
         }
 
         @Override
-        public void onLoadChildren(String parentId, ParceledListSlice list) {
-            onLoadChildrenWithOptions(parentId, list, null);
-        }
-
-        @Override
-        public void onLoadChildrenWithOptions(String parentId, ParceledListSlice list,
+        public void onLoadChildren(String parentId, ParceledListSlice list,
                 final Bundle options) {
             MediaBrowser mediaBrowser = mMediaBrowser.get();
             if (mediaBrowser != null) {
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index e134635..21211d7 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -839,9 +839,11 @@
         public abstract boolean onTune(Uri channelUri);
 
         /**
-         * Calls {@link #onTune(Uri)}. Override this method in order to handle domain-specific
+         * Tunes to a given channel. Override this method in order to handle domain-specific
          * features that are only known between certain TV inputs and their clients.
          *
+         * <p>The default implementation calls {@link #onTune(Uri)}.
+         *
          * @param channelUri The URI of the channel.
          * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
          *            name, i.e. prefixed with a package name you own, so that different developers
@@ -1693,11 +1695,12 @@
         public abstract void onTune(Uri channelUri);
 
         /**
-         * Calls {@link #onTune(Uri)}. Override this method in order to handle domain-specific
-         * features that are only known between certain TV inputs and their clients.
+         * Called when the application requests to tune to a given channel for TV program recording.
+         * Override this method in order to handle domain-specific features that are only known
+         * between certain TV inputs and their clients.
          *
          * <p>The application may call this method before starting or after stopping recording, but
-         * not during recording.
+         * not during recording. The default implementation calls {@link #onTune(Uri)}.
          *
          * <p>The session must call {@link #notifyTuned(Uri)} if the tune request was fulfilled, or
          * {@link #notifyError(int)} otherwise.
diff --git a/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
index 6ca5ac5..eef5a7c 100644
--- a/media/java/android/service/media/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -14,19 +14,11 @@
  * @hide
  */
 oneway interface IMediaBrowserService {
-
-    // Warning: DO NOT CHANGE the methods signature and order of methods.
-    // A change of the order or the method signatures could break the support library.
-
     void connect(String pkg, in Bundle rootHints, IMediaBrowserServiceCallbacks callbacks);
     void disconnect(IMediaBrowserServiceCallbacks callbacks);
 
-    void addSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
-    void removeSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
+    void addSubscription(String uri, in IBinder token, in Bundle options,
+            IMediaBrowserServiceCallbacks callbacks);
+    void removeSubscription(String uri, in IBinder token, IMediaBrowserServiceCallbacks callbacks);
     void getMediaItem(String uri, in ResultReceiver cb);
-
-    void addSubscriptionWithOptions(String uri, in Bundle options,
-            IMediaBrowserServiceCallbacks callbacks);
-    void removeSubscriptionWithOptions(String uri, in Bundle options,
-            IMediaBrowserServiceCallbacks callbacks);
 }
diff --git a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index e6b0e8c..dadb025 100644
--- a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -13,10 +13,6 @@
  * @hide
  */
 oneway interface IMediaBrowserServiceCallbacks {
-
-    // Warning: DO NOT CHANGE the methods signature and order of methods.
-    // A change of the order or the method signatures could break the support library.
-
     /**
      * Invoked when the connected has been established.
      * @param root The root media id for browsing.
@@ -26,6 +22,5 @@
      */
     void onConnect(String root, in MediaSession.Token session, in Bundle extras);
     void onConnectFailed();
-    void onLoadChildren(String mediaId, in ParceledListSlice list);
-    void onLoadChildrenWithOptions(String mediaId, in ParceledListSlice list, in Bundle options);
+    void onLoadChildren(String mediaId, in ParceledListSlice list, in Bundle options);
 }
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 6954045..ddc0e88 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -39,6 +39,7 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Pair;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -108,7 +109,7 @@
         Bundle rootHints;
         IMediaBrowserServiceCallbacks callbacks;
         BrowserRoot root;
-        HashMap<String, List<Bundle>> subscriptions = new HashMap<>();
+        HashMap<String, List<Pair<IBinder, Bundle>>> subscriptions = new HashMap<>();
     }
 
     /**
@@ -247,13 +248,7 @@
         }
 
         @Override
-        public void addSubscription(final String id,
-                final IMediaBrowserServiceCallbacks callbacks) {
-            addSubscriptionWithOptions(id, null, callbacks);
-        }
-
-        @Override
-        public void addSubscriptionWithOptions(final String id, final Bundle options,
+        public void addSubscription(final String id, final IBinder token, final Bundle options,
                 final IMediaBrowserServiceCallbacks callbacks) {
             mHandler.post(new Runnable() {
                     @Override
@@ -268,19 +263,13 @@
                             return;
                         }
 
-                        MediaBrowserService.this.addSubscription(id, connection, options);
+                        MediaBrowserService.this.addSubscription(id, connection, token, options);
                     }
                 });
         }
 
         @Override
-        public void removeSubscription(final String id,
-                final IMediaBrowserServiceCallbacks callbacks) {
-            removeSubscriptionWithOptions(id, null, callbacks);
-        }
-
-        @Override
-        public void removeSubscriptionWithOptions(final String id, final Bundle options,
+        public void removeSubscription(final String id, final IBinder token,
                 final IMediaBrowserServiceCallbacks callbacks) {
             mHandler.post(new Runnable() {
                 @Override
@@ -293,7 +282,7 @@
                                 + id);
                         return;
                     }
-                    if (!MediaBrowserService.this.removeSubscription(id, connection, options)) {
+                    if (!MediaBrowserService.this.removeSubscription(id, connection, token)) {
                         Log.w(TAG, "removeSubscription called for " + id
                                 + " which is not subscribed");
                     }
@@ -519,11 +508,12 @@
             public void run() {
                 for (IBinder binder : mConnections.keySet()) {
                     ConnectionRecord connection = mConnections.get(binder);
-                    List<Bundle> optionsList = connection.subscriptions.get(parentId);
-                    if (optionsList != null) {
-                        for (Bundle bundle : optionsList) {
-                            if (MediaBrowserUtils.hasDuplicatedItems(options, bundle)) {
-                                performLoadChildren(parentId, connection, bundle);
+                    List<Pair<IBinder, Bundle>> callbackList =
+                            connection.subscriptions.get(parentId);
+                    if (callbackList != null) {
+                        for (Pair<IBinder, Bundle> callback : callbackList) {
+                            if (MediaBrowserUtils.hasDuplicatedItems(options, callback.second)) {
+                                performLoadChildren(parentId, connection, callback.second);
                             }
                         }
                     }
@@ -553,19 +543,21 @@
     /**
      * Save the subscription and if it is a new subscription send the results.
      */
-    private void addSubscription(String id, ConnectionRecord connection, Bundle options) {
+    private void addSubscription(String id, ConnectionRecord connection, IBinder token,
+            Bundle options) {
         // Save the subscription
-        List<Bundle> optionsList = connection.subscriptions.get(id);
-        if (optionsList == null) {
-            optionsList = new ArrayList<>();
+        List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
+        if (callbackList == null) {
+            callbackList = new ArrayList<>();
         }
-        for (Bundle bundle : optionsList) {
-            if (MediaBrowserUtils.areSameOptions(options, bundle)) {
+        for (Pair<IBinder, Bundle> callback : callbackList) {
+            if (token == callback.first
+                    && MediaBrowserUtils.areSameOptions(options, callback.second)) {
                 return;
             }
         }
-        optionsList.add(options);
-        connection.subscriptions.put(id, optionsList);
+        callbackList.add(new Pair<>(token, options));
+        connection.subscriptions.put(id, callbackList);
         // send the results
         performLoadChildren(id, connection, options);
     }
@@ -573,21 +565,20 @@
     /**
      * Remove the subscription.
      */
-    private boolean removeSubscription(String id, ConnectionRecord connection, Bundle options) {
-        if (options == null) {
+    private boolean removeSubscription(String id, ConnectionRecord connection, IBinder token) {
+        if (token == null) {
             return connection.subscriptions.remove(id) != null;
         }
         boolean removed = false;
-        List<Bundle> optionsList = connection.subscriptions.get(id);
-        if (optionsList != null) {
-            for (Bundle bundle : optionsList) {
-                if (MediaBrowserUtils.areSameOptions(options, bundle)) {
+        List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
+        if (callbackList != null) {
+            for (Pair<IBinder, Bundle> callback : callbackList) {
+                if (token == callback.first) {
                     removed = true;
-                    optionsList.remove(bundle);
-                    break;
+                    callbackList.remove(callback);
                 }
             }
-            if (optionsList.size() == 0) {
+            if (callbackList.size() == 0) {
                 connection.subscriptions.remove(id);
             }
         }
@@ -619,14 +610,7 @@
                 final ParceledListSlice<MediaBrowser.MediaItem> pls =
                         filteredList == null ? null : new ParceledListSlice<>(filteredList);
                 try {
-                    // NOTE: Do not call onLoadChildrenWithOptions when options are null. Otherwise,
-                    // it will break the action of support library which expects onLoadChildren will
-                    // be called when options are null.
-                    if (options == null) {
-                        connection.callbacks.onLoadChildren(parentId, pls);
-                    } else {
-                        connection.callbacks.onLoadChildrenWithOptions(parentId, pls, options);
-                    }
+                    connection.callbacks.onLoadChildren(parentId, pls, options);
                 } catch (RemoteException ex) {
                     // The other side is in the process of crashing.
                     Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 64b4842..7b3fd66 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2158,6 +2158,17 @@
     // System UI Tuner > Other > Power notification controls > Toggle on/off
     ACTION_TUNER_POWER_NOTIFICATION_CONTROLS = 393;
 
+    // Action: user enable / disabled data saver using Settings. Arguments:
+    // 0: Data Saver mode is disabled.
+    // 1: Data Saver mode is enabled.
+    ACTION_DATA_SAVER_MODE = 394;
+
+    // User whitelisted an app for Data Saver mode; action pass package name of app.
+    ACTION_DATA_SAVER_WHITELIST = 395;
+
+    // User blacklisted an app for Data Saver mode; action pass package name of app.
+    ACTION_DATA_SAVER_BLACKLIST = 396;
+
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
   }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c971262..40430b4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1471,6 +1471,7 @@
     static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 66;
     static final int NOTIFY_FORCED_RESIZABLE_MSG = 67;
     static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 68;
+    static final int VR_MODE_APPLY_IF_NEEDED_MSG = 69;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -2241,6 +2242,17 @@
                 }
                 vrService.setVrMode(vrMode, requestedPackage, userId, callingPackage);
             } break;
+            case VR_MODE_APPLY_IF_NEEDED_MSG: {
+                final ActivityRecord r = (ActivityRecord) msg.obj;
+                final boolean needsVrMode = r != null && r.requestedVrComponent != null;
+                if (needsVrMode) {
+                    VrManagerInternal vrService =
+                            LocalServices.getService(VrManagerInternal.class);
+                    boolean enable = msg.arg1 == 1;
+                    vrService.setVrMode(enable, r.requestedVrComponent, r.userId,
+                            r.info.getComponentName());
+                }
+            } break;
             }
         }
     };
@@ -3021,6 +3033,11 @@
                 mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
     }
 
+    private void applyVrModeIfNeededLocked(ActivityRecord r, boolean enable) {
+        mHandler.sendMessage(
+                mHandler.obtainMessage(VR_MODE_APPLY_IF_NEEDED_MSG, enable ? 1 : 0, 0, r));
+    }
+
     final void showAskCompatModeDialogLocked(ActivityRecord r) {
         Message msg = Message.obtain();
         msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
@@ -6537,6 +6554,7 @@
 
                     // Some stack visibility might change (e.g. docked stack)
                     mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+                    applyVrModeIfNeededLocked(mFocusedActivity, true);
                 }
             }
         } finally {
@@ -20925,6 +20943,7 @@
                 SleepTokenImpl token = new SleepTokenImpl(tag);
                 mSleepTokens.add(token);
                 updateSleepIfNeededLocked();
+                applyVrModeIfNeededLocked(mFocusedActivity, false);
                 return token;
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index ab3a0b3..cd465d6 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2270,7 +2270,7 @@
         final ActivityRecord r = task.getTopActivity();
         final ActivityStack prevStack = task.stack;
         final boolean wasFocused = isFocusedStack(prevStack) && (topRunningActivityLocked() == r);
-        final boolean wasResumed = wasFocused && (prevStack.mResumedActivity == r);
+        final boolean wasResumed = prevStack.mResumedActivity == r;
         // In some cases the focused stack isn't the front stack. E.g. pinned stack.
         // Whenever we are moving the top activity from the front stack we want to make sure to move
         // the stack to the front.
diff --git a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
index 0c259ae..ac5c4ae 100644
--- a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
+++ b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
@@ -300,14 +300,14 @@
          */
         public ConnectivityMetricsEvent[] getEvents(ConnectivityMetricsEvent.Reference reference) {
             enforceDumpPermission();
-            long ref = reference.value;
+            long ref = reference.getValue();
             if (VDBG) Log.v(TAG, "getEvents(" + ref + ")");
 
             ConnectivityMetricsEvent[] result;
             synchronized (mEvents) {
                 if (ref > mLastEventReference) {
                     Log.e(TAG, "Invalid reference");
-                    reference.value = mLastEventReference;
+                    reference.setValue(mLastEventReference);
                     return null;
                 }
                 if (ref < mLastEventReference - mEvents.size()) {
@@ -329,7 +329,7 @@
                 }
             }
 
-            reference.value = mLastEventReference;
+            reference.setValue(mLastEventReference);
 
             return result;
         }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index fed7e4b..e07d72f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1189,7 +1189,9 @@
         @Override
         public void binderDied() {
             synchronized (mLock) {
-                mRecordListenerRecord = null;
+                if (mRecordListenerRecord == this) {
+                    mRecordListenerRecord = null;
+                }
             }
         }
     }
@@ -1813,7 +1815,9 @@
         @Override
         public void binderDied() {
             synchronized (mLock) {
-                mInputChangeListenerRecord = null;
+                if (mInputChangeListenerRecord == this) {
+                    mInputChangeListenerRecord = null;
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index c248608..3fb786b 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -260,6 +260,8 @@
     private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
     private static final int MSG_SCREEN_ON_CHANGED = 8;
     private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9;
+    private static final int MSG_UPDATE_INTERFACE_QUOTA = 10;
+    private static final int MSG_REMOVE_INTERFACE_QUOTA = 11;
 
     private final Context mContext;
     private final IActivityManager mActivityManager;
@@ -1275,8 +1277,10 @@
                 }
 
                 for (String iface : ifaces) {
-                    removeInterfaceQuota(iface);
-                    setInterfaceQuota(iface, quotaBytes);
+                    // long quotaBytes split up into two ints to fit in message
+                    mHandler.obtainMessage(MSG_UPDATE_INTERFACE_QUOTA,
+                            (int) (quotaBytes >> 32), (int) (quotaBytes & 0xFFFFFFFF), iface)
+                            .sendToTarget();
                     newMeteredIfaces.add(iface);
                 }
             }
@@ -1292,8 +1296,10 @@
 
         for (int i = connIfaces.size()-1; i >= 0; i--) {
             String iface = connIfaces.valueAt(i);
-            removeInterfaceQuota(iface);
-            setInterfaceQuota(iface, Long.MAX_VALUE);
+            // long quotaBytes split up into two ints to fit in message
+            mHandler.obtainMessage(MSG_UPDATE_INTERFACE_QUOTA,
+                    (int) (Long.MAX_VALUE >> 32), (int) (Long.MAX_VALUE & 0xFFFFFFFF), iface)
+                    .sendToTarget();
             newMeteredIfaces.add(iface);
         }
 
@@ -1303,7 +1309,8 @@
         for (int i = mMeteredIfaces.size() - 1; i >= 0; i--) {
             final String iface = mMeteredIfaces.valueAt(i);
             if (!newMeteredIfaces.contains(iface)) {
-                removeInterfaceQuota(iface);
+                mHandler.obtainMessage(MSG_REMOVE_INTERFACE_QUOTA, iface)
+                        .sendToTarget();
             }
         }
         mMeteredIfaces = newMeteredIfaces;
@@ -2950,6 +2957,17 @@
                     updateScreenOn();
                     return true;
                 }
+                case MSG_UPDATE_INTERFACE_QUOTA: {
+                    removeInterfaceQuota((String) msg.obj);
+                    // int params need to be stitched back into a long
+                    setInterfaceQuota((String) msg.obj,
+                            ((long) msg.arg1 << 32) | (msg.arg2 & 0xFFFFFFFFL));
+                    return true;
+                }
+                case MSG_REMOVE_INTERFACE_QUOTA: {
+                    removeInterfaceQuota((String) msg.obj);
+                    return true;
+                }
                 default: {
                     return false;
                 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1fb260d..dc81c65 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2315,24 +2315,29 @@
             // For security and version matching reason, only consider
             // overlay packages if they reside in VENDOR_OVERLAY_DIR.
             File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
-            scanDirTracedLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
-                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
+            scanDirTracedLI(vendorOverlayDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
+                    | PackageParser.PARSE_IS_SYSTEM_DIR
+                    | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
 
             // Find base frameworks (resource packages without code).
-            scanDirTracedLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
+            scanDirTracedLI(frameworkDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR
                     | PackageParser.PARSE_IS_PRIVILEGED,
                     scanFlags | SCAN_NO_DEX, 0);
 
             // Collected privileged system packages.
             final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
-            scanDirTracedLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
+            scanDirTracedLI(privilegedAppDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR
                     | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
 
             // Collect ordinary system packages.
             final File systemAppDir = new File(Environment.getRootDirectory(), "app");
-            scanDirTracedLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
+            scanDirTracedLI(systemAppDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
 
             // Collect all vendor packages.
@@ -2342,12 +2347,14 @@
             } catch (IOException e) {
                 // failed to look up canonical path, continue with original one
             }
-            scanDirTracedLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
+            scanDirTracedLI(vendorAppDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
 
             // Collect all OEM packages.
             final File oemAppDir = new File(Environment.getOemDirectory(), "app");
-            scanDirTracedLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
+            scanDirTracedLI(oemAppDir, mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
 
             // Prune any system packages that no longer exist.
@@ -2428,10 +2435,12 @@
                         SystemClock.uptimeMillis());
                 scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
 
-                scanDirTracedLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
+                scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
+                        | PackageParser.PARSE_FORWARD_LOCK,
                         scanFlags | SCAN_REQUIRE_KNOWN, 0);
 
-                scanDirLI(mEphemeralInstallDir, PackageParser.PARSE_IS_EPHEMERAL,
+                scanDirLI(mEphemeralInstallDir, mDefParseFlags
+                        | PackageParser.PARSE_IS_EPHEMERAL,
                         scanFlags | SCAN_REQUIRE_KNOWN, 0);
 
                 /**
@@ -2476,7 +2485,7 @@
                         logCriticalInfo(Log.WARN, "Expected better " + packageName
                                 + " but never showed up; reverting to system");
 
-                        final int reparseFlags;
+                        int reparseFlags = mDefParseFlags;
                         if (FileUtils.contains(privilegedAppDir, scanFile)) {
                             reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                     | PackageParser.PARSE_IS_SYSTEM_DIR
@@ -6501,7 +6510,7 @@
         return true;
     }
 
-    private void scanDirTracedLI(File dir, int parseFlags, int scanFlags, long currentTime) {
+    private void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir");
         try {
             scanDirLI(dir, parseFlags, scanFlags, currentTime);
@@ -6510,7 +6519,7 @@
         }
     }
 
-    private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
+    private void scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
         final File[] files = dir.listFiles();
         if (ArrayUtils.isEmpty(files)) {
             Log.d(TAG, "No files in app dir " + dir);
@@ -6576,7 +6585,7 @@
     }
 
     private void collectCertificatesLI(PackageSetting ps, PackageParser.Package pkg, File srcFile,
-            int parseFlags) throws PackageManagerException {
+            final int policyFlags) throws PackageManagerException {
         if (ps != null
                 && ps.codePath.equals(srcFile)
                 && ps.timeStamp == srcFile.lastModified()
@@ -6605,7 +6614,7 @@
         }
 
         try {
-            PackageParser.collectCertificates(pkg, parseFlags);
+            PackageParser.collectCertificates(pkg, policyFlags);
         } catch (PackageParserException e) {
             throw PackageManagerException.from(e);
         }
@@ -6615,8 +6624,8 @@
      *  Traces a package scan.
      *  @see #scanPackageLI(File, int, int, long, UserHandle)
      */
-    private PackageParser.Package scanPackageTracedLI(File scanFile, int parseFlags, int scanFlags,
-            long currentTime, UserHandle user) throws PackageManagerException {
+    private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags,
+            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
         try {
             return scanPackageLI(scanFile, parseFlags, scanFlags, currentTime, user);
@@ -6632,7 +6641,6 @@
     private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
             long currentTime, UserHandle user) throws PackageManagerException {
         if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
-        parseFlags |= mDefParseFlags;
         PackageParser pp = new PackageParser();
         pp.setSeparateProcesses(mSeparateProcesses);
         pp.setOnlyCoreApps(mOnlyCore);
@@ -6642,11 +6650,14 @@
             parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
         }
 
+        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
         final PackageParser.Package pkg;
         try {
             pkg = pp.parsePackage(scanFile, parseFlags);
         } catch (PackageParserException e) {
             throw PackageManagerException.from(e);
+        } finally {
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
 
         return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
@@ -6657,7 +6668,7 @@
      *  @throws PackageManagerException on a parse error.
      */
     private PackageParser.Package scanPackageLI(PackageParser.Package pkg, File scanFile,
-            int parseFlags, int scanFlags, long currentTime, UserHandle user)
+            final int policyFlags, int scanFlags, long currentTime, UserHandle user)
             throws PackageManagerException {
         // If the package has children and this is the first dive in the function
         // we scan the package with the SCAN_CHECK_ONLY flag set to see whether all
@@ -6673,20 +6684,20 @@
         }
 
         // Scan the parent
-        PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, parseFlags,
+        PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, policyFlags,
                 scanFlags, currentTime, user);
 
         // Scan the children
         final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
         for (int i = 0; i < childCount; i++) {
             PackageParser.Package childPackage = pkg.childPackages.get(i);
-            scanPackageInternalLI(childPackage, scanFile, parseFlags, scanFlags,
+            scanPackageInternalLI(childPackage, scanFile, policyFlags, scanFlags,
                     currentTime, user);
         }
 
 
         if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
-            return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
+            return scanPackageLI(pkg, scanFile, policyFlags, scanFlags, currentTime, user);
         }
 
         return scannedPkg;
@@ -6697,7 +6708,7 @@
      *  @throws PackageManagerException on a parse error.
      */
     private PackageParser.Package scanPackageInternalLI(PackageParser.Package pkg, File scanFile,
-            int parseFlags, int scanFlags, long currentTime, UserHandle user)
+            int policyFlags, int scanFlags, long currentTime, UserHandle user)
             throws PackageManagerException {
         PackageSetting ps = null;
         PackageSetting updatedPkg;
@@ -6724,7 +6735,7 @@
             // may need to remove disabled child packages on the system partition
             // or may need to not add child packages if the parent apk is updated
             // on the data partition and no longer defines this child package.
-            if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
+            if ((policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
                 // If this is a parent package for an updated system app and this system
                 // app got an OTA update which no longer defines some of the child packages
                 // we have to prune them from the disabled system packages.
@@ -6754,7 +6765,7 @@
 
         boolean updatedPkgBetter = false;
         // First check if this is a system package that may involve an update
-        if (updatedPkg != null && (parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
+        if (updatedPkg != null && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
             // If new package is not located in "/system/priv-app" (e.g. due to an OTA),
             // it needs to drop FLAG_PRIVILEGED.
             if (locationIsPrivileged(scanFile)) {
@@ -6836,17 +6847,17 @@
         if (updatedPkg != null) {
             // An updated system app will not have the PARSE_IS_SYSTEM flag set
             // initially
-            parseFlags |= PackageParser.PARSE_IS_SYSTEM;
+            policyFlags |= PackageParser.PARSE_IS_SYSTEM;
 
             // An updated privileged app will not have the PARSE_IS_PRIVILEGED
             // flag set initially
             if ((updatedPkg.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
-                parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
+                policyFlags |= PackageParser.PARSE_IS_PRIVILEGED;
             }
         }
 
         // Verify certificates against what was last scanned
-        collectCertificatesLI(ps, pkg, scanFile, parseFlags);
+        collectCertificatesLI(ps, pkg, scanFile, policyFlags);
 
         /*
          * A new system app appeared, but we already had a non-system one of the
@@ -6854,7 +6865,7 @@
          */
         boolean shouldHideSystemApp = false;
         if (updatedPkg == null && ps != null
-                && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
+                && (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
             /*
              * Check to make sure the signatures match first. If they don't,
              * wipe the installed application and its data.
@@ -6902,16 +6913,16 @@
         // are kept in different files. (except for app in either system or
         // vendor path).
         // TODO grab this value from PackageSettings
-        if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+        if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
             if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
-                parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
+                policyFlags |= PackageParser.PARSE_FORWARD_LOCK;
             }
         }
 
         // TODO: extend to support forward-locked splits
         String resourcePath = null;
         String baseResourcePath = null;
-        if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
+        if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
             if (ps != null && ps.resourcePathString != null) {
                 resourcePath = ps.resourcePathString;
                 baseResourcePath = ps.resourcePathString;
@@ -6934,7 +6945,7 @@
         pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
 
         // Note that we invoke the following method only if we are about to unpack an application
-        PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags
+        PackageParser.Package scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags
                 | SCAN_UPDATE_SIGNATURE, currentTime, user);
 
         /*
@@ -7576,8 +7587,9 @@
         return cpuAbiOverride;
     }
 
-    private PackageParser.Package scanPackageTracedLI(PackageParser.Package pkg, int parseFlags,
-            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
+    private PackageParser.Package scanPackageTracedLI(PackageParser.Package pkg,
+            final int policyFlags, int scanFlags, long currentTime, UserHandle user)
+                    throws PackageManagerException {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
         // If the package has children and this is the first dive in the function
         // we recursively scan the package with the SCAN_CHECK_ONLY flag set to see
@@ -7595,12 +7607,12 @@
         final PackageParser.Package scannedPkg;
         try {
             // Scan the parent
-            scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags, currentTime, user);
+            scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags, currentTime, user);
             // Scan the children
             final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
             for (int i = 0; i < childCount; i++) {
                 PackageParser.Package childPkg = pkg.childPackages.get(i);
-                scanPackageLI(childPkg, parseFlags,
+                scanPackageLI(childPkg, policyFlags,
                         scanFlags, currentTime, user);
             }
         } finally {
@@ -7608,17 +7620,17 @@
         }
 
         if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
-            return scanPackageTracedLI(pkg, parseFlags, scanFlags, currentTime, user);
+            return scanPackageTracedLI(pkg, policyFlags, scanFlags, currentTime, user);
         }
 
         return scannedPkg;
     }
 
-    private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,
+    private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
             int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
         boolean success = false;
         try {
-            final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags,
+            final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
                     currentTime, user);
             success = true;
             return res;
@@ -7632,8 +7644,8 @@
         }
     }
 
-    private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
-            int scanFlags, long currentTime, UserHandle user)
+    private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
+            final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
             throws PackageManagerException {
         final File scanFile = new File(pkg.codePath);
         if (pkg.applicationInfo.getCodePath() == null ||
@@ -7643,14 +7655,36 @@
                     "Code and resource paths haven't been set correctly");
         }
 
-        if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
+        // Apply policy
+        if ((policyFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+            if (pkg.applicationInfo.isDirectBootAware()) {
+                // we're direct boot aware; set for all components
+                for (PackageParser.Service s : pkg.services) {
+                    s.info.encryptionAware = s.info.directBootAware = true;
+                }
+                for (PackageParser.Provider p : pkg.providers) {
+                    p.info.encryptionAware = p.info.directBootAware = true;
+                }
+                for (PackageParser.Activity a : pkg.activities) {
+                    a.info.encryptionAware = a.info.directBootAware = true;
+                }
+                for (PackageParser.Activity r : pkg.receivers) {
+                    r.info.encryptionAware = r.info.directBootAware = true;
+                }
+            }
         } else {
             // Only allow system apps to be flagged as core apps.
             pkg.coreApp = false;
+            // clear flags not applicable to regular apps
+            pkg.applicationInfo.privateFlags &=
+                    ~ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
+            pkg.applicationInfo.privateFlags &=
+                    ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
         }
+        pkg.mTrustedOverlay = (policyFlags&PackageParser.PARSE_TRUSTED_OVERLAY) != 0;
 
-        if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
+        if ((policyFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
         }
 
@@ -7699,7 +7733,7 @@
         }
 
         if (DEBUG_PACKAGE_SCANNING) {
-            if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
+            if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
                 Log.d(TAG, "Scanning package " + pkg.packageName);
         }
 
@@ -7774,7 +7808,7 @@
                             + " for shared user failed");
                 }
                 if (DEBUG_PACKAGE_SCANNING) {
-                    if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
+                    if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
                         Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
                                 + "): packages=" + suid.packages);
                 }
@@ -7820,6 +7854,7 @@
                                     origPackage = null;
                                     continue;
                                 }
+                                // TODO: Add case when shared user id is added [b/28144775]
                             } else {
                                 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
                                         + pkg.packageName + " to old name " + origPackage.name);
@@ -7886,7 +7921,7 @@
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
 
-            if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+            if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                 // Check all shared libraries and map to their actual file path.
                 // We only do this here for apps not on a system dir, because those
                 // are the only ones that can fail an install due to this.  We
@@ -7907,7 +7942,7 @@
                     // over the latest parsed certs.
                     pkgSetting.signatures.mSignatures = pkg.mSignatures;
                 } else {
-                    if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+                    if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                         throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                                 "Package " + pkg.packageName + " upgrade keys do not match the "
                                 + "previously installed version");
@@ -7925,7 +7960,7 @@
                     // over the latest parsed certs.
                     pkgSetting.signatures.mSignatures = pkg.mSignatures;
                 } catch (PackageManagerException e) {
-                    if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+                    if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                         throw e;
                     }
                     // The signature has changed, but this package is in the system
@@ -8114,7 +8149,7 @@
 
         // Only privileged apps and updated privileged apps can add child packages.
         if (pkg.childPackages != null && !pkg.childPackages.isEmpty()) {
-            if ((parseFlags & PARSE_IS_PRIVILEGED) == 0) {
+            if ((policyFlags & PARSE_IS_PRIVILEGED) == 0) {
                 throw new PackageManagerException("Only privileged apps and updated "
                         + "privileged apps can add child packages. Ignoring package "
                         + pkg.packageName);
@@ -8240,7 +8275,7 @@
             } else if (pkgSetting.firstInstallTime == 0) {
                 // We need *something*.  Take time time stamp of the file.
                 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
-            } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
+            } else if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
                 if (scanFileTime != pkgSetting.timeStamp) {
                     // A package on the system image has changed; consider this
                     // to be an update.
@@ -8283,7 +8318,7 @@
                                 p.info.authority = p.info.authority + ";" + names[j];
                             }
                             if (DEBUG_PACKAGE_SCANNING) {
-                                if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
+                                if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
                                     Log.d(TAG, "Registered content provider: " + names[j]
                                             + ", className = " + p.info.name + ", isSyncable = "
                                             + p.info.isSyncable);
@@ -8298,7 +8333,7 @@
                         }
                     }
                 }
-                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8318,7 +8353,7 @@
                 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
                         s.info.processName, pkg.applicationInfo.uid);
                 mServices.addService(s);
-                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8338,7 +8373,7 @@
                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                         a.info.processName, pkg.applicationInfo.uid);
                 mReceivers.addActivity(a, "receiver");
-                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8358,7 +8393,7 @@
                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                         a.info.processName, pkg.applicationInfo.uid);
                 mActivities.addActivity(a, "activity");
-                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8378,7 +8413,7 @@
                 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
                 if (cur == null) {
                     mPermissionGroups.put(pg.info.name, pg);
-                    if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                         if (r == null) {
                             r = new StringBuilder(256);
                         } else {
@@ -8390,7 +8425,7 @@
                     Slog.w(TAG, "Permission group " + pg.info.name + " from package "
                             + pg.info.packageName + " ignored: original from "
                             + cur.info.packageName);
-                    if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                         if (r == null) {
                             r = new StringBuilder(256);
                         } else {
@@ -8469,7 +8504,7 @@
                             bp.uid = pkg.applicationInfo.uid;
                             bp.sourcePackage = p.info.packageName;
                             p.info.flags |= PermissionInfo.FLAG_INSTALLED;
-                            if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                            if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                                 if (r == null) {
                                     r = new StringBuilder(256);
                                 } else {
@@ -8488,7 +8523,7 @@
                                 + p.info.packageName + " ignored: original from "
                                 + bp.sourcePackage);
                     }
-                } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                } else if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8523,7 +8558,7 @@
                 // need other information about the application, like the ABI and what not ?
                 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
                 mInstrumentation.put(a.getComponentName(), a);
-                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -13538,8 +13573,8 @@
     /*
      * Install a non-existing package.
      */
-    private void installNewPackageLIF(PackageParser.Package pkg, int parseFlags, int scanFlags,
-            UserHandle user, String installerPackageName, String volumeUuid,
+    private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
+            int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
             PackageInstalledInfo res) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");
 
@@ -13568,7 +13603,7 @@
         }
 
         try {
-            PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags, scanFlags,
+            PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
                     System.currentTimeMillis(), user);
 
             updateSettingsLI(newPackage, installerPackageName, null, res, user);
@@ -13625,9 +13660,9 @@
         return false;
     }
 
-    private void replacePackageLIF(PackageParser.Package pkg, int parseFlags, int scanFlags,
+    private void replacePackageLIF(PackageParser.Package pkg, final int policyFlags, int scanFlags,
             UserHandle user, String installerPackageName, PackageInstalledInfo res) {
-        final boolean isEphemeral = (parseFlags & PackageParser.PARSE_IS_EPHEMERAL) != 0;
+        final boolean isEphemeral = (policyFlags & PackageParser.PARSE_IS_EPHEMERAL) != 0;
 
         final PackageParser.Package oldPackage;
         final String pkgName = pkg.packageName;
@@ -13715,10 +13750,18 @@
 
         boolean sysPkg = (isSystemApp(oldPackage));
         if (sysPkg) {
-            replaceSystemPackageLIF(oldPackage, pkg, parseFlags, scanFlags,
+            // Set the system/privileged flags as needed
+            final boolean privileged =
+                    (oldPackage.applicationInfo.privateFlags
+                            & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
+            final int systemPolicyFlags = policyFlags
+                    | PackageParser.PARSE_IS_SYSTEM
+                    | (privileged ? PackageParser.PARSE_IS_PRIVILEGED : 0);
+
+            replaceSystemPackageLIF(oldPackage, pkg, systemPolicyFlags, scanFlags,
                     user, allUsers, installerPackageName, res);
         } else {
-            replaceNonSystemPackageLIF(oldPackage, pkg, parseFlags, scanFlags,
+            replaceNonSystemPackageLIF(oldPackage, pkg, policyFlags, scanFlags,
                     user, allUsers, installerPackageName, res);
         }
     }
@@ -13733,7 +13776,7 @@
     }
 
     private void replaceNonSystemPackageLIF(PackageParser.Package deletedPackage,
-            PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
+            PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user,
             int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
         if (DEBUG_INSTALL) Slog.d(TAG, "replaceNonSystemPackageLI: new=" + pkg + ", old="
                 + deletedPackage);
@@ -13775,7 +13818,7 @@
             clearAppProfilesLIF(pkg);
 
             try {
-                final PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags,
+                final PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags,
                         scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
                 updateSettingsLI(newPackage, installerPackageName, allUsers, res, user);
 
@@ -13872,20 +13915,13 @@
     }
 
     private void replaceSystemPackageLIF(PackageParser.Package deletedPackage,
-            PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
+            PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user,
             int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
         if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
                 + ", old=" + deletedPackage);
 
         final boolean disabledSystem;
 
-        // Set the system/privileged flags as needed
-        parseFlags |= PackageParser.PARSE_IS_SYSTEM;
-        if ((deletedPackage.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
-                != 0) {
-            parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
-        }
-
         // Remove existing system package
         removePackageLI(deletedPackage, true);
 
@@ -13914,7 +13950,7 @@
         PackageParser.Package newPackage = null;
         try {
             // Add the package to the internal data structures
-            newPackage = scanPackageTracedLI(pkg, parseFlags, scanFlags, 0, user);
+            newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags, 0, user);
 
             // Set the update and install times
             PackageSetting deletedPkgSetting = (PackageSetting) deletedPackage.mExtras;
@@ -13967,7 +14003,7 @@
             }
             // Add back the old system package
             try {
-                scanPackageTracedLI(deletedPackage, parseFlags, SCAN_UPDATE_SIGNATURE, 0, user);
+                scanPackageTracedLI(deletedPackage, policyFlags, SCAN_UPDATE_SIGNATURE, 0, user);
             } catch (PackageManagerException e) {
                 Slog.e(TAG, "Failed to restore original package: " + e.getMessage());
             }
@@ -15296,7 +15332,10 @@
 
         // Install the system package
         if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
-        int parseFlags = PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM;
+        int parseFlags = mDefParseFlags
+                | PackageParser.PARSE_MUST_BE_APK
+                | PackageParser.PARSE_IS_SYSTEM
+                | PackageParser.PARSE_IS_SYSTEM_DIR;
         if (locationIsPrivileged(disabledPs.codePath)) {
             parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
         }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index ac6510a..0ac5c1f 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -907,6 +907,16 @@
         }
     }
 
+    public void cleanupBitmapsForPackage(@UserIdInt int userId, String packageName) {
+        final File packagePath = new File(getUserBitmapFilePath(userId), packageName);
+        if (!packagePath.isDirectory()) {
+            return;
+        }
+        if (!(FileUtils.deleteContents(packagePath) && packagePath.delete())) {
+            Slog.w(TAG, "Unable to remove directory " + packagePath);
+        }
+    }
+
     @VisibleForTesting
     static class FileOutputStreamWithPath extends FileOutputStream {
         private final File mFile;
@@ -1572,7 +1582,7 @@
 
         // First, remove the package from the package list (if the package is a publisher).
         if (packageUserId == owningUserId) {
-            if (mUser.removePackage(packageName) != null) {
+            if (mUser.removePackage(this, packageName) != null) {
                 doNotify = true;
             }
         }
@@ -2084,11 +2094,11 @@
             pw.println(mIconPersistFormat);
             pw.print("    Icon quality: ");
             pw.println(mIconPersistQuality);
-            pw.print("    saveDelayMillis:");
+            pw.print("    saveDelayMillis: ");
             pw.println(mSaveDelayMillis);
-            pw.print("    resetInterval:");
+            pw.print("    resetInterval: ");
             pw.println(mResetInterval);
-            pw.print("    maxUpdatesPerInterval:");
+            pw.print("    maxUpdatesPerInterval: ");
             pw.println(mMaxUpdatesPerInterval);
             pw.print("    maxDynamicShortcuts:");
             pw.println(mMaxDynamicShortcuts);
@@ -2416,7 +2426,6 @@
         return mPackageManagerInternal;
     }
 
-    @VisibleForTesting
     File getUserBitmapFilePath(@UserIdInt int userId) {
         return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS);
     }
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 593f607..0b8c3a2 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -18,6 +18,7 @@
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.content.ComponentName;
+import android.text.format.Formatter;
 import android.util.ArrayMap;
 import android.util.Slog;
 
@@ -29,6 +30,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.function.Consumer;
@@ -103,8 +105,12 @@
         return mPackages;
     }
 
-    public ShortcutPackage removePackage(@NonNull String packageName) {
-        return mPackages.remove(packageName);
+    public ShortcutPackage removePackage(@NonNull ShortcutService s, @NonNull String packageName) {
+        final ShortcutPackage removed = mPackages.remove(packageName);
+
+        s.cleanupBitmapsForPackage(mUserId, packageName);
+
+        return removed;
     }
 
     public ArrayMap<PackageWithUser, ShortcutLauncher> getAllLaunchers() {
@@ -279,18 +285,51 @@
         pw.print(mUserId);
         pw.println();
 
+        prefix += prefix + "  ";
+
         pw.print(prefix);
-        pw.print("  ");
         pw.print("Default launcher: ");
         pw.print(mLauncherComponent);
         pw.println();
 
         for (int i = 0; i < mLaunchers.size(); i++) {
-            mLaunchers.valueAt(i).dump(s, pw, prefix + "  ");
+            mLaunchers.valueAt(i).dump(s, pw, prefix);
         }
 
         for (int i = 0; i < mPackages.size(); i++) {
-            mPackages.valueAt(i).dump(s, pw, prefix + "  ");
+            mPackages.valueAt(i).dump(s, pw, prefix);
         }
+
+        pw.println();
+        pw.print(prefix);
+        pw.println("Bitmap directories: ");
+        dumpDirectorySize(s, pw, prefix + "  ", s.getUserBitmapFilePath(mUserId));
+    }
+
+    private void dumpDirectorySize(@NonNull ShortcutService s, @NonNull PrintWriter pw,
+            @NonNull String prefix, File path) {
+        int numFiles = 0;
+        long size = 0;
+        final File[] children = path.listFiles();
+        if (children != null) {
+            for (File child : path.listFiles()) {
+                if (child.isFile()) {
+                    numFiles++;
+                    size += child.length();
+                } else if (child.isDirectory()) {
+                    dumpDirectorySize(s, pw, prefix + "  ", child);
+                }
+            }
+        }
+        pw.print(prefix);
+        pw.print("Path: ");
+        pw.print(path.getName());
+        pw.print("/ has ");
+        pw.print(numFiles);
+        pw.print(" files, size=");
+        pw.print(size);
+        pw.print(" (");
+        pw.print(Formatter.formatFileSize(s.mContext, size));
+        pw.println(")");
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index 6bdcd42..0217c09 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -218,7 +218,7 @@
     }
 
     private int assignAndIncreaseLayerIfNeeded(WindowState win, int layer) {
-        if (win != null && layer > win.mLayer) {
+        if (win != null) {
             assignAnimLayer(win, layer);
             // Make sure we leave space inbetween normal windows for dims and such.
             layer += WINDOW_LAYER_MULTIPLIER;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 6fcc8f9..1f76f31 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1774,6 +1774,10 @@
         }
         if (mWin.mAttrs.type == TYPE_INPUT_METHOD) {
             mService.adjustForImeIfNeeded(mWin.mDisplayContent);
+            if (isEntrance) {
+                mWin.setDisplayLayoutNeeded();
+                mService.mWindowPlacerLocked.requestTraversal();
+            }
         }
         return mAnimation != null;
     }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index ce02a79..d20d5fa 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -15,9 +15,36 @@
  */
 package com.android.server.pm;
 
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamic;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamicOrPinned;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIcon;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIconFile;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIconResId;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIntents;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveTitle;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllKeyFieldsOnly;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotHaveIntents;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotHaveTitle;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotKeyFieldsOnly;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllPinned;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllUnique;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBitmapSize;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBundleEmpty;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertCallbackNotReceived;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertCallbackReceived;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertDynamicAndPinned;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertDynamicOnly;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertShortcutIds;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.hashSet;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.pfdToBitmap;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.resetAll;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyList;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doAnswer;
@@ -27,7 +54,6 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -57,13 +83,11 @@
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
-import android.os.BaseBundle;
 import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.UserHandle;
@@ -71,7 +95,6 @@
 import android.test.InstrumentationTestCase;
 import android.test.mock.MockContext;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
@@ -84,9 +107,6 @@
 import com.android.server.pm.ShortcutService.ConfigConstants;
 import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
 import com.android.server.pm.ShortcutUser.PackageWithUser;
-import com.android.server.testutis.TestUtils;
-
-import libcore.io.IoUtils;
 
 import org.junit.Assert;
 import org.mockito.ArgumentCaptor;
@@ -98,8 +118,6 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -4018,24 +4036,33 @@
         checkCanRestoreTo(false, spi2, 11, "x", "sig2x", "sig1", "y");
     }
 
+    private boolean bitmapDirectoryExists(String packageName, int userId) {
+        final File path = new File(mService.getUserBitmapFilePath(userId), packageName);
+        return path.isDirectory();
+    }
+
     public void testHandlePackageDelete() {
+        final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                getTestContext().getResources(), R.drawable.black_32x32));
         setCaller(CALLING_PACKAGE_1, USER_0);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(
+                makeShortcutWithIcon("s1", bmp32x32), makeShortcutWithIcon("s2", bmp32x32)
+        )));
 
         setCaller(CALLING_PACKAGE_2, USER_0);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         setCaller(CALLING_PACKAGE_3, USER_0);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         setCaller(CALLING_PACKAGE_1, USER_10);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         setCaller(CALLING_PACKAGE_2, USER_10);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         setCaller(CALLING_PACKAGE_3, USER_10);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
@@ -4044,6 +4071,13 @@
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
 
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+
         uninstallPackage(USER_0, CALLING_PACKAGE_1);
         mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageDeleteIntent(CALLING_PACKAGE_1, USER_0));
@@ -4055,6 +4089,13 @@
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
 
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+
         uninstallPackage(USER_10, CALLING_PACKAGE_2);
         mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageDeleteIntent(CALLING_PACKAGE_2, USER_10));
@@ -4066,6 +4107,13 @@
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
 
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+
         mInjectedPackages.remove(CALLING_PACKAGE_1);
         mInjectedPackages.remove(CALLING_PACKAGE_3);
 
@@ -4078,6 +4126,13 @@
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
 
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+
         mService.handleUnlockUser(USER_10);
 
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -4086,6 +4141,13 @@
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
+
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
     }
 
     private void backupAndRestore() {
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 87fc7fa..2579d9f 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -199,6 +199,12 @@
         // Whether STA responder role is supported.
         public boolean responderSupported;
 
+        /** Whether the secure RTT protocol is supported. */
+        public boolean secureRttSupported;
+
+        /** Draft 11mc version supported, including major and minor version. e.g, draft 4.3 is 43 */
+        public int mcVersion;
+
         @Override
         public String toString() {
             StringBuffer sb = new StringBuffer();
@@ -223,7 +229,7 @@
                 sb.append("VHT ");
             }
 
-            sb.append("is supported. \n");
+            sb.append("is supported. ");
 
             if ((bwSupported & RTT_BW_5_SUPPORT) != 0) {
                 sb.append("5 MHz ");
@@ -252,7 +258,10 @@
             sb.append("is supported.");
 
             sb.append(" STA responder role is ")
-                .append(responderSupported ? "supported" : "not supported.");
+                    .append(responderSupported ? "supported" : "not supported");
+            sb.append(" Secure RTT protocol is ")
+                    .append(secureRttSupported ? "supported" : "not supported");
+            sb.append(" 11mc version is " + mcVersion);
 
             return sb.toString();
         }
@@ -272,6 +281,8 @@
             dest.writeInt(preambleSupported);
             dest.writeInt(bwSupported);
             dest.writeInt(responderSupported ? 1 : 0);
+            dest.writeInt(secureRttSupported ? 1 : 0);
+            dest.writeInt(mcVersion);
         }
 
         /** Implement the Parcelable interface {@hide} */
@@ -279,16 +290,18 @@
             new Creator<RttCapabilities>() {
             @Override
             public RttCapabilities createFromParcel(Parcel in) {
-                    RttCapabilities capabilities = new RttCapabilities();
-                    capabilities.oneSidedRttSupported = (in.readInt() == 1);
-                        capabilities.twoSided11McRttSupported = (in.readInt() == 1);
-                        capabilities.lciSupported = (in.readInt() == 1);
-                        capabilities.lcrSupported = (in.readInt() == 1);
-                        capabilities.preambleSupported = in.readInt();
-                        capabilities.bwSupported = in.readInt();
-                        capabilities.responderSupported = (in.readInt() == 1);
-                        return capabilities;
-                    }
+                RttCapabilities capabilities = new RttCapabilities();
+                capabilities.oneSidedRttSupported = (in.readInt() == 1);
+                capabilities.twoSided11McRttSupported = (in.readInt() == 1);
+                capabilities.lciSupported = (in.readInt() == 1);
+                capabilities.lcrSupported = (in.readInt() == 1);
+                capabilities.preambleSupported = in.readInt();
+                capabilities.bwSupported = in.readInt();
+                capabilities.responderSupported = (in.readInt() == 1);
+                capabilities.secureRttSupported = (in.readInt() == 1);
+                capabilities.mcVersion = in.readInt();
+                return capabilities;
+            }
                 /** Implement the Parcelable interface {@hide} */
                 @Override
                 public RttCapabilities[] newArray(int size) {
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 1a8197c..2ee1aef 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
@@ -31,13 +30,11 @@
 import android.util.Log;
 import android.util.SparseArray;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.Protocol;
 
 import java.util.List;
-import java.util.concurrent.CountDownLatch;
 
 
 /**
@@ -1143,7 +1140,6 @@
     private final Object mListenerMapLock = new Object();
 
     private AsyncChannel mAsyncChannel;
-    private final CountDownLatch mConnected;
     private final Handler mInternalHandler;
 
     /**
@@ -1157,22 +1153,6 @@
      * @hide
      */
     public WifiScanner(Context context, IWifiScanner service, Looper looper) {
-        this(context, service, looper, true);
-    }
-
-    /**
-     * Create a new WifiScanner instance.
-     *
-     * @param context The application context.
-     * @param service The IWifiScanner Binder interface
-     * @param looper the Looper used to deliver callbacks
-     * @param waitForConnection If true, this will not return until a connection to Wifi Scanner
-     *          service is established.
-     * @hide
-     */
-    @VisibleForTesting
-    public WifiScanner(Context context, IWifiScanner service, Looper looper,
-            boolean waitForConnection) {
         mContext = context;
         mService = service;
 
@@ -1188,17 +1168,12 @@
         }
 
         mAsyncChannel = new AsyncChannel();
-        mConnected = new CountDownLatch(1);
 
         mInternalHandler = new ServiceHandler(looper);
-        mAsyncChannel.connect(mContext, mInternalHandler, messenger);
-        if (waitForConnection) {
-            try {
-                mConnected.await();
-            } catch (InterruptedException e) {
-                Log.e(TAG, "interrupted wait at init");
-            }
-        }
+        mAsyncChannel.connectSync(mContext, mInternalHandler, messenger);
+        // We cannot use fullyConnectSync because it sends the FULL_CONNECTION message
+        // synchronously, which causes WifiScanningService to receive the wrong replyTo value.
+        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
     }
 
     private void validateChannel() {
@@ -1326,17 +1301,6 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
-                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
-                    } else {
-                        Log.e(TAG, "Failed to set up channel connection");
-                        // This will cause all further async API calls on the WifiManager
-                        // to fail and throw an exception
-                        mAsyncChannel = null;
-                    }
-                    mConnected.countDown();
-                    return;
                 case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
                     return;
                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: