Merge changes I7ef5921c,I3bbd09c5

* changes:
  Create test for CategoryManager.
  Backward-compat for DashboardCategory with app use old keys
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 13c8ab1..bb9c18a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -23,6 +23,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -697,23 +698,23 @@
     public static PackageLite parsePackageLite(File packageFile, int flags)
             throws PackageParserException {
         if (packageFile.isDirectory()) {
-            return parseClusterPackageLite(packageFile, flags);
+            return parseClusterPackageLite(packageFile, flags, null);
         } else {
-            return parseMonolithicPackageLite(packageFile, flags);
+            return parseMonolithicPackageLite(packageFile, flags, null);
         }
     }
 
-    private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
-            throws PackageParserException {
+    private static PackageLite parseMonolithicPackageLite(File packageFile, int flags,
+            AssetManager cachedAssetManager) throws PackageParserException {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
-        final ApkLite baseApk = parseApkLite(packageFile, flags);
+        final ApkLite baseApk = parseApkLite(packageFile, flags, cachedAssetManager);
         final String packagePath = packageFile.getAbsolutePath();
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         return new PackageLite(packagePath, baseApk, null, null, null);
     }
 
-    private static PackageLite parseClusterPackageLite(File packageDir, int flags)
-            throws PackageParserException {
+    private static PackageLite parseClusterPackageLite(File packageDir, int flags,
+            AssetManager cachedAssetManager) throws PackageParserException {
         final File[] files = packageDir.listFiles();
         if (ArrayUtils.isEmpty(files)) {
             throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
@@ -727,7 +728,7 @@
         final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
         for (File file : files) {
             if (isApkFile(file)) {
-                final ApkLite lite = parseApkLite(file, flags);
+                final ApkLite lite = parseApkLite(file, flags, cachedAssetManager);
 
                 // Assert that all package names and version codes are
                 // consistent with the first one we encounter.
@@ -820,16 +821,16 @@
      * must be done separately in {@link #collectCertificates(Package, int)}.
      */
     private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
-        final PackageLite lite = parseClusterPackageLite(packageDir, 0);
+        final AssetManager assets = newConfiguredAssetManager();
+        final PackageLite lite = parseClusterPackageLite(packageDir, 0, assets);
 
         if (mOnlyCoreApps && !lite.coreApp) {
             throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                     "Not a coreApp: " + packageDir);
         }
 
-        final AssetManager assets = new AssetManager();
         try {
-            // Load the base and all splits into the AssetManager
+            // Load all splits into the AssetManager (base has already been loaded earlier)
             // so that resources can be overriden when parsing the manifests.
             loadApkIntoAssetManager(assets, lite.baseCodePath, flags);
 
@@ -879,7 +880,8 @@
      */
     @Deprecated
     public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
-        final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
+        final AssetManager assets = newConfiguredAssetManager();
+        final PackageLite lite = parseMonolithicPackageLite(apkFile, flags, assets);
         if (mOnlyCoreApps) {
             if (!lite.coreApp) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
@@ -887,7 +889,6 @@
             }
         }
 
-        final AssetManager assets = new AssetManager();
         try {
             final Package pkg = parseBaseApk(apkFile, assets, flags);
             pkg.setCodePath(apkFile.getAbsolutePath());
@@ -937,8 +938,6 @@
         XmlResourceParser parser = null;
         try {
             res = new Resources(assets, mMetrics, null);
-            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    Build.VERSION.RESOURCES_SDK_INT);
             parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
 
             final String[] outError = new String[1];
@@ -1304,6 +1303,13 @@
         return res;
     }
 
+    private static AssetManager newConfiguredAssetManager() {
+        AssetManager assetManager = new AssetManager();
+        assetManager.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                Build.VERSION.RESOURCES_SDK_INT);
+        return assetManager;
+    }
+
     /**
      * Utility method that retrieves lightweight details about a single APK
      * file, including package name, split name, and install location.
@@ -1314,15 +1320,17 @@
      */
     public static ApkLite parseApkLite(File apkFile, int flags)
             throws PackageParserException {
+        return parseApkLite(apkFile, flags, null);
+    }
+
+    private static ApkLite parseApkLite(File apkFile, int flags,
+            @Nullable AssetManager cachedAssetManager) throws PackageParserException {
         final String apkPath = apkFile.getAbsolutePath();
 
         AssetManager assets = null;
         XmlResourceParser parser = null;
         try {
-            assets = new AssetManager();
-            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    Build.VERSION.RESOURCES_SDK_INT);
-
+            assets = cachedAssetManager == null ? newConfiguredAssetManager() : cachedAssetManager;
             int cookie = assets.addAssetPath(apkPath);
             if (cookie == 0) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
@@ -1361,7 +1369,9 @@
                     "Failed to parse " + apkPath, e);
         } finally {
             IoUtils.closeQuietly(parser);
-            IoUtils.closeQuietly(assets);
+            if (cachedAssetManager == null) {
+                IoUtils.closeQuietly(assets);
+            }
         }
     }
 
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 39d7883..bccb822 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -85,8 +85,8 @@
     void pauseKeyDispatching(IBinder token);
     void resumeKeyDispatching(IBinder token);
     void setEventDispatching(boolean enabled);
-    void addWindowToken(IBinder token, int type);
-    void removeWindowToken(IBinder token);
+    void addWindowToken(IBinder token, int type, int displayId);
+    void removeWindowToken(IBinder token, int displayId);
     /**
      * Adds an application token to the specified task Id.
      * @param addPos The position to add the token to in the task.
@@ -183,7 +183,7 @@
     void notifyAppStopped(IBinder token);
     void startAppFreezingScreen(IBinder token, int configChanges);
     void stopAppFreezingScreen(IBinder token, boolean force);
-    void removeAppToken(IBinder token);
+    void removeAppToken(IBinder token, int displayId);
 
     /** Used by system ui to report that recents has shown itself. */
     void endProlongedAnimations();
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index f61a637..6e2a92c 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -241,16 +241,19 @@
      *
      * @param token The token to add.
      * @param type The window type.
+     * @param displayId The display to add the token to.
      */
-    public abstract void addWindowToken(android.os.IBinder token, int type);
+    public abstract void addWindowToken(android.os.IBinder token, int type, int displayId);
 
     /**
      * Removes a window token.
      *
      * @param token The toke to remove.
      * @param removeWindows Whether to also remove the windows associated with the token.
+     * @param displayId The display to remove the token from.
      */
-    public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows);
+    public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows,
+            int displayId);
 
     /**
      * Registers a listener to be notified about app transition events.
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 8cedb17..d5a933c 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2168,6 +2168,7 @@
         }
 
         layoutChildren();
+        mInLayout = false;
 
         mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
 
@@ -2175,7 +2176,6 @@
         if (mFastScroll != null) {
             mFastScroll.onItemCountChanged(getChildCount(), mItemCount);
         }
-        mInLayout = false;
     }
 
     /**
@@ -2705,9 +2705,6 @@
      * fail to relayout them properly to accommodate for new bounds.
      */
     void handleBoundsChange() {
-        if (mInLayout) {
-            return;
-        }
         final int childCount = getChildCount();
         if (childCount > 0) {
             mDataChanged = true;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 316dab5..b2a77d0 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -324,6 +324,14 @@
             return false;
         }
 
+        /**
+         * Overridden by subclasses which have (or inherit) an ApplicationInfo instance
+         * as member variable
+         */
+        public boolean hasSameAppInfo(ApplicationInfo parentInfo) {
+            return true;
+        }
+
         int viewId;
     }
 
@@ -1521,11 +1529,11 @@
             }
         }
 
-        public ViewGroupAction(Parcel parcel, BitmapCache bitmapCache) {
+        ViewGroupAction(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info) {
             viewId = parcel.readInt();
             boolean nestedViewsNull = parcel.readInt() == 0;
             if (!nestedViewsNull) {
-                nestedViews = new RemoteViews(parcel, bitmapCache);
+                nestedViews = new RemoteViews(parcel, bitmapCache, info);
             } else {
                 nestedViews = null;
             }
@@ -1544,6 +1552,13 @@
         }
 
         @Override
+        public boolean hasSameAppInfo(ApplicationInfo parentInfo) {
+            return nestedViews != null
+                    && nestedViews.mApplication.packageName.equals(parentInfo.packageName)
+                    && nestedViews.mApplication.uid == parentInfo.uid;
+        }
+
+        @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
             final Context context = root.getContext();
             final ViewGroup target = (ViewGroup) root.findViewById(viewId);
@@ -2195,10 +2210,10 @@
      * @param parcel
      */
     public RemoteViews(Parcel parcel) {
-        this(parcel, null);
+        this(parcel, null, null);
     }
 
-    private RemoteViews(Parcel parcel, BitmapCache bitmapCache) {
+    private RemoteViews(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info) {
         int mode = parcel.readInt();
 
         // We only store a bitmap cache in the root of the RemoteViews.
@@ -2210,7 +2225,8 @@
         }
 
         if (mode == MODE_NORMAL) {
-            mApplication = parcel.readParcelable(null);
+            mApplication = parcel.readInt() == 0 ? info :
+                    ApplicationInfo.CREATOR.createFromParcel(parcel);
             mLayoutId = parcel.readInt();
             mIsWidgetCollectionChild = parcel.readInt() == 1;
 
@@ -2230,7 +2246,7 @@
                             mActions.add(new ReflectionAction(parcel));
                             break;
                         case ViewGroupAction.TAG:
-                            mActions.add(new ViewGroupAction(parcel, mBitmapCache));
+                            mActions.add(new ViewGroupAction(parcel, mBitmapCache, mApplication));
                             break;
                         case ReflectionActionWithoutParams.TAG:
                             mActions.add(new ReflectionActionWithoutParams(parcel));
@@ -2278,8 +2294,8 @@
             }
         } else {
             // MODE_HAS_LANDSCAPE_AND_PORTRAIT
-            mLandscape = new RemoteViews(parcel, mBitmapCache);
-            mPortrait = new RemoteViews(parcel, mBitmapCache);
+            mLandscape = new RemoteViews(parcel, mBitmapCache, info);
+            mPortrait = new RemoteViews(parcel, mBitmapCache, mLandscape.mApplication);
             mApplication = mPortrait.mApplication;
             mLayoutId = mPortrait.getLayoutId();
         }
@@ -2299,11 +2315,11 @@
         // Do not parcel the Bitmap cache - doing so creates an expensive copy of all bitmaps.
         // Instead pretend we're not owning the cache while parceling.
         mIsRoot = false;
-        writeToParcel(p, 0);
+        writeToParcel(p, PARCELABLE_ELIDE_DUPLICATES);
         p.setDataPosition(0);
         mIsRoot = true;
 
-        RemoteViews rv = new RemoteViews(p, mBitmapCache.clone());
+        RemoteViews rv = new RemoteViews(p, mBitmapCache.clone(), mApplication);
         rv.mIsRoot = true;
 
         p.recycle();
@@ -3536,7 +3552,12 @@
             if (mIsRoot) {
                 mBitmapCache.writeBitmapsToParcel(dest, flags);
             }
-            dest.writeParcelable(mApplication, flags);
+            if (!mIsRoot && (flags & PARCELABLE_ELIDE_DUPLICATES) != 0) {
+                dest.writeInt(0);
+            } else {
+                dest.writeInt(1);
+                mApplication.writeToParcel(dest, flags);
+            }
             dest.writeInt(mLayoutId);
             dest.writeInt(mIsWidgetCollectionChild ? 1 : 0);
             int count;
@@ -3548,7 +3569,8 @@
             dest.writeInt(count);
             for (int i=0; i<count; i++) {
                 Action a = mActions.get(i);
-                a.writeToParcel(dest, 0);
+                a.writeToParcel(dest, a.hasSameAppInfo(mApplication)
+                        ? PARCELABLE_ELIDE_DUPLICATES : 0);
             }
         } else {
             dest.writeInt(MODE_HAS_LANDSCAPE_AND_PORTRAIT);
@@ -3558,7 +3580,8 @@
                 mBitmapCache.writeBitmapsToParcel(dest, flags);
             }
             mLandscape.writeToParcel(dest, flags);
-            mPortrait.writeToParcel(dest, flags);
+            // Both RemoteViews already share the same package and user
+            mPortrait.writeToParcel(dest, flags | PARCELABLE_ELIDE_DUPLICATES);
         }
     }
 
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 38452bb..e10fdbd 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -32,7 +32,7 @@
 #include "SkPathEffect.h"
 #include "SkRasterizer.h"
 #include "SkShader.h"
-#include "SkXfermode.h"
+#include "SkBlendMode.h"
 #include "unicode/uloc.h"
 #include "unicode/ushape.h"
 #include "utils/Blur.h"
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index a2416df..6c688a4 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -2,7 +2,7 @@
 #include "SkGradientShader.h"
 #include "SkImagePriv.h"
 #include "SkShader.h"
-#include "SkXfermode.h"
+#include "SkBlendMode.h"
 #include "core_jni_helpers.h"
 
 #include <Caches.h>
@@ -237,7 +237,7 @@
     SkBlendMode mode = static_cast<SkBlendMode>(xfermodeHandle);
     SkShader* shader = SkShader::MakeComposeShader(sk_ref_sp(shaderA),
                                                    sk_ref_sp(shaderB),
-                                                   (SkXfermode::Mode)mode).release();
+                                                   mode).release();
     return reinterpret_cast<jlong>(shader);
 }
 
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 4e0b924..65c1590 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -29,7 +29,7 @@
 #include <SkBitmap.h>
 #include <SkCanvas.h>
 #include <SkMatrix.h>
-#include <SkXfermode.h>
+#include <SkBlendMode.h>
 
 #include <DeferredLayerUpdater.h>
 #include <SkiaShader.h>
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 4e3bf46..7ba46be 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -20,6 +20,7 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.Parcel;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -35,6 +36,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests for RemoteViews.
@@ -43,6 +45,9 @@
 @SmallTest
 public class RemoteViewsTest {
 
+    // This can point to any other package which exists on the device.
+    private static final String OTHER_PACKAGE = "com.android.systemui";
+
     @Rule
     public final ExpectedException exception = ExpectedException.none();
 
@@ -121,4 +126,44 @@
         clone.apply(mContext, mContainer);
     }
 
+    @Test
+    public void parcelSize_nestedViews() {
+        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
+        // We don't care about the actual layout id.
+        RemoteViews child = new RemoteViews(mPackage, 33);
+        int expectedSize = getParcelSize(original) + getParcelSize(child);
+        original.addView(R.id.layout, child);
+
+        // The application info will get written only once.
+        assertTrue(getParcelSize(original) < expectedSize);
+        assertEquals(getParcelSize(original), getParcelSize(original.clone()));
+
+        original = new RemoteViews(mPackage, R.layout.remote_views_test);
+        child = new RemoteViews(OTHER_PACKAGE, 33);
+        expectedSize = getParcelSize(original) + getParcelSize(child);
+        original.addView(R.id.layout, child);
+
+        // Both the views will get written completely along with an additional view operation
+        assertTrue(getParcelSize(original) > expectedSize);
+        assertEquals(getParcelSize(original), getParcelSize(original.clone()));
+    }
+
+    @Test
+    public void parcelSize_differentOrientation() {
+        RemoteViews landscape = new RemoteViews(mPackage, R.layout.remote_views_test);
+        RemoteViews portrait = new RemoteViews(mPackage, 33);
+
+        // The application info will get written only once.
+        RemoteViews views = new RemoteViews(landscape, portrait);
+        assertTrue(getParcelSize(views) < (getParcelSize(landscape) + getParcelSize(portrait)));
+        assertEquals(getParcelSize(views), getParcelSize(views.clone()));
+    }
+
+    private int getParcelSize(RemoteViews view) {
+        Parcel parcel = Parcel.obtain();
+        view.writeToParcel(parcel, 0);
+        int size = parcel.dataSize();
+        parcel.recycle();
+        return size;
+    }
 }
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index b396e22..34c7934 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -25,7 +25,6 @@
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
-#include <SkXfermode.h>
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 3b5fc71..34e6d39 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -257,7 +257,7 @@
             // If the blend mode cannot be implemented using shaders, fall
             // back to the default SrcOver blend mode instead
             if (CC_UNLIKELY(mCaches.extensions().hasFramebufferFetch())) {
-                mDescription.framebufferMode = (SkXfermode::Mode)mode;
+                mDescription.framebufferMode = mode;
                 mDescription.swapSrcDst = (modeUsage == Blend::ModeOrderSwap::Swap);
                 // blending in shader, don't enable
             } else {
@@ -271,11 +271,11 @@
 
     if (colorFilter) {
         SkColor color;
-        SkXfermode::Mode xmode;
+        SkBlendMode bmode;
         SkScalar srcColorMatrix[20];
-        if (colorFilter->asColorMode(&color, &xmode)) {
+        if (colorFilter->asColorMode(&color, &bmode)) {
             mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Blend;
-            mDescription.colorMode = xmode;
+            mDescription.colorMode = bmode;
             mOutGlop->fill.filter.color.set(color);
         } else if (colorFilter->asColorMatrix(srcColorMatrix)) {
             mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Matrix;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index f5beb62..e410d71 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -22,7 +22,7 @@
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
-#include <SkXfermode.h>
+#include <SkBlendMode.h>
 
 #include "Debug.h"
 #include "FloatColor.h"
@@ -142,7 +142,7 @@
     Gradient gradientType;
     bool isSimpleGradient;
 
-    SkXfermode::Mode shadersMode;
+    SkBlendMode shadersMode;
 
     bool isBitmapFirst;
     GLenum bitmapWrapS;
@@ -150,11 +150,11 @@
 
     // Color operations
     ColorFilterMode colorOp;
-    SkXfermode::Mode colorMode;
+    SkBlendMode colorMode;
 
     // Framebuffer blending (requires Extensions.hasFramebufferFetch())
-    // Ignored for all values < SkXfermode::kPlus_Mode
-    SkXfermode::Mode framebufferMode;
+    // Ignored for all values < SkBlendMode::kPlus
+    SkBlendMode framebufferMode;
     bool swapSrcDst;
 
     bool hasDebugHighlight;
@@ -186,16 +186,16 @@
         gradientType = kGradientLinear;
         isSimpleGradient = false;
 
-        shadersMode = SkXfermode::kClear_Mode;
+        shadersMode = SkBlendMode::kClear;
 
         isBitmapFirst = false;
         bitmapWrapS = GL_CLAMP_TO_EDGE;
         bitmapWrapT = GL_CLAMP_TO_EDGE;
 
         colorOp = ColorFilterMode::None;
-        colorMode = SkXfermode::kClear_Mode;
+        colorMode = SkBlendMode::kClear;
 
-        framebufferMode = SkXfermode::kClear_Mode;
+        framebufferMode = SkBlendMode::kClear;
         swapSrcDst = false;
 
         hasDebugHighlight = false;
@@ -244,7 +244,7 @@
         key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
         if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
         if (hasBitmap && hasGradient) {
-            key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
+            key |= ((int)shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
         }
         switch (colorOp) {
             case ColorFilterMode::Matrix:
@@ -252,12 +252,12 @@
                 break;
             case ColorFilterMode::Blend:
                 key |= PROGRAM_KEY_COLOR_BLEND;
-                key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
+                key |= ((int)colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
                 break;
             case ColorFilterMode::None:
                 break;
         }
-        key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
+        key |= ((int)framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
         if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
         if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
         if (hasVertexAlpha) key |= programid(0x1) << PROGRAM_HAS_VERTEX_ALPHA_SHIFT;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 4ef6b85..1afc978 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -572,7 +572,7 @@
 String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) {
     String8 shader(gFS_Header_Start);
 
-    const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode;
+    const bool blendFramebuffer = description.framebufferMode >= SkBlendMode::kPlus;
     if (blendFramebuffer) {
         shader.append(gFS_Header_Extension_FramebufferFetch);
     }
@@ -809,12 +809,12 @@
     return shader;
 }
 
-void ProgramCache::generateBlend(String8& shader, const char* name, SkXfermode::Mode mode) {
+void ProgramCache::generateBlend(String8& shader, const char* name, SkBlendMode mode) {
     shader.append("\nvec4 ");
     shader.append(name);
     shader.append("(vec4 src, vec4 dst) {\n");
     shader.append("    ");
-    shader.append(gBlendOps[mode]);
+    shader.append(gBlendOps[(int)mode]);
     shader.append("}\n");
 }
 
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 292ecdf..c2f715d 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -51,7 +51,7 @@
     Program* generateProgram(const ProgramDescription& description, programid key);
     String8 generateVertexShader(const ProgramDescription& description);
     String8 generateFragmentShader(const ProgramDescription& description);
-    void generateBlend(String8& shader, const char* name, SkXfermode::Mode mode);
+    void generateBlend(String8& shader, const char* name, SkBlendMode mode);
     void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT);
 
     void printLongString(const String8& shader) const;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index b6ac48f..7c97e77 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -546,7 +546,7 @@
 #endif
     const int ptCount = vertexCount >> 1;
     mCanvas->drawVertices(vertexMode, ptCount, (SkPoint*)verts, (SkPoint*)texs,
-                          (SkColor*)colors, NULL, indices, indexCount, paint);
+                          (SkColor*)colors, indices, indexCount, paint);
 }
 
 // ----------------------------------------------------------------------------
@@ -670,7 +670,7 @@
     tmpPaint.setShader(image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode));
 
     mCanvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, (SkPoint*)vertices,
-                         texs, (const SkColor*)colors, NULL, indices,
+                         texs, (const SkColor*)colors, indices,
                          indexCount, tmpPaint);
 }
 
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 863146e..f674086 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -140,8 +140,9 @@
 }
 
 void SkiaCanvasProxy::onDrawVertices(VertexMode mode, int vertexCount, const SkPoint vertices[],
-        const SkPoint texs[], const SkColor colors[], SkXfermode*, const uint16_t indices[],
+        const SkPoint texs[], const SkColor colors[], SkBlendMode, const uint16_t indices[],
         int indexCount, const SkPaint& paint) {
+    // TODO: should we pass through blendmode
     if (mFilterHwuiCalls) {
         return;
     }
@@ -374,7 +375,7 @@
 }
 
 void SkiaCanvasProxy::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-        const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+        const SkPoint texCoords[4], SkBlendMode bmode, const SkPaint& paint) {
     if (mFilterHwuiCalls) {
         return;
     }
@@ -388,7 +389,7 @@
     // If it fails to generate the vertices, then we do not draw.
     if (SkPatchUtils::getVertexData(&data, cubics, colors, texCoords, lod.width(), lod.height())) {
         this->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount, data.fPoints,
-                           data.fTexCoords, data.fColors, xmode, data.fIndices, data.fIndexCount,
+                           data.fTexCoords, data.fColors, bmode, data.fIndices, data.fIndexCount,
                            paint);
     }
 }
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index 3ee8c6e..0111815 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -67,7 +67,7 @@
     virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                   const SkRect& dst, const SkPaint*) override;
     virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
-                                const SkPoint texs[], const SkColor colors[], SkXfermode*,
+                                const SkPoint texs[], const SkColor colors[], SkBlendMode,
                                 const uint16_t indices[], int indexCount,
                                 const SkPaint&) override;
 
@@ -87,7 +87,7 @@
                                 const SkPaint& paint) override;
 
     virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                             const SkPoint texCoords[4], SkXfermode* xmode,
+                             const SkPoint texCoords[4], SkBlendMode,
                              const SkPaint& paint) override;
 
     virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override;
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 489a306..971c2a3 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -309,10 +309,7 @@
         storeCompose(caches, *rec.fShaderB, *rec.fShaderA,
                 transform, textureUnit, description, outData);
     }
-    if (!SkXfermode::AsMode(rec.fMode, &description->shadersMode)) {
-        // TODO: Support other modes.
-        description->shadersMode = SkXfermode::kSrcOver_Mode;
-    }
+    description->shadersMode = rec.fBlendMode;
     return true;
 }
 
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 5854289..d2f37cd 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -22,7 +22,6 @@
 
 #include <GLES2/gl2.h>
 #include <SkShader.h>
-#include <SkXfermode.h>
 #include <cutils/compiler.h>
 
 namespace android {
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index f8a181f..13a0ed8 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "LayerDrawable.h"
+#include "SkColorFilter.h"
 #include "gl/GrGLTypes.h"
 
 namespace android {
@@ -40,12 +41,12 @@
     textureDescription.fConfig = kRGBA_8888_GrPixelConfig;
     textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
     textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
-    sk_sp<SkImage> layerImage(SkImage::NewFromTexture(context, textureDescription));
+    sk_sp<SkImage> layerImage = SkImage::MakeFromTexture(context, textureDescription);
     if (layerImage) {
         SkPaint paint;
         paint.setAlpha(mLayer->getAlpha());
         paint.setBlendMode(mLayer->getMode());
-        paint.setColorFilter(mLayer->getColorFilter());
+        paint.setColorFilter(sk_ref_sp(mLayer->getColorFilter()));
         canvas->drawImage(layerImage, 0, 0, &paint);
     }
     // restore the original matrix
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index cefa893..b656d67 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -130,7 +130,7 @@
             || properties.colorFilter() != nullptr) {
         paint->setAlpha(properties.alpha() * alphaMultiplier);
         paint->setBlendMode(properties.xferMode());
-        paint->setColorFilter(properties.colorFilter());
+        paint->setColorFilter(sk_ref_sp(properties.colorFilter()));
         return true;
     }
     return false;
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 8d77938..ac18587 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -23,7 +23,7 @@
 #include <SkBlurMaskFilter.h>
 #include <SkGaussianEdgeShader.h>
 #include <SkPathOps.h>
-#include <SkRRectsGaussianEdgeShader.h>
+#include <SkRRectsGaussianEdgeMaskFilter.h>
 
 namespace android {
 namespace uirenderer {
@@ -341,7 +341,7 @@
         paint.setAntiAlias(true);
 
         // If the area of the stroked geometry is larger than the fill geometry, just fill it.
-        if (strokedArea > filledArea || casterAlpha < 1.0f) {
+        if (strokedArea > filledArea || casterAlpha < 1.0f || insetAmount < 0.0f) {
             paint.setStyle(SkPaint::kStrokeAndFill_Style);
             paint.setStrokeWidth(srcSpaceSpotRadius);
         } else {
@@ -433,8 +433,8 @@
 
         SkPaint paint;
         paint.setColor(SkColorSetARGB((unsigned char) ambientAlpha, 0, 0, 0));
-        paint.setShader(SkRRectsGaussianEdgeShader::Make(devSpaceAmbientRRect,
-                devSpaceAmbientClipRR, devSpaceAmbientRadius));
+        paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceAmbientRRect,
+            devSpaceAmbientClipRR, devSpaceAmbientRadius));
         canvas->drawRect(cover, paint);
     }
 
@@ -514,8 +514,8 @@
             devSpaceSpotClipRR = SkRRect::MakeRect(devSpaceScaledClipRect);
         }
 
-        paint.setShader(SkRRectsGaussianEdgeShader::Make(devSpaceSpotRRect, devSpaceSpotClipRR,
-                devSpaceSpotRadius));
+        paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceSpotRRect,
+            devSpaceSpotClipRR, devSpaceSpotRadius));
 
         SkRect cover = srcSpaceScaledClipRect;
         if (!cover.intersect(srcSpaceSpotRRect.rect())) {
@@ -556,8 +556,8 @@
         return false;
     }
 
-    // The casterClipRect will contain the casterRect when bounds clipping is disabled
-    bool casterIsClippedByRect = !casterClipRect.contains(casterRect);
+    // The casterClipRect will be empty when bounds clipping is disabled
+    bool casterIsClippedByRect = !casterClipRect.isEmpty();
     bool uniformScale = scaleFactors[0] == scaleFactors[1];
 
     if (revealClip.willClip()) {
@@ -639,11 +639,15 @@
 
     bool clippedToBounds = casterProperties.getClippingFlags() & CLIP_TO_CLIP_BOUNDS;
 
-    SkRect casterClipRect = SkRect::MakeLargest();
+    SkRect casterClipRect = SkRect::MakeEmpty();
     if (clippedToBounds) {
         Rect clipBounds;
         casterProperties.getClippingRectForFlags(CLIP_TO_CLIP_BOUNDS, &clipBounds);
         casterClipRect = clipBounds.toSkRect();
+        if (casterClipRect.isEmpty()) {
+            // An empty clip rect means nothing is drawn
+            return;
+        }
     }
 
     SkAutoCanvasRestore acr(canvas, true);
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 134497c..dda432e 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -776,7 +776,7 @@
                 SkShader::TileMode::kRepeat_TileMode);
 
         sk_sp<SkShader> composeShader = SkShader::MakeComposeShader(std::move(shader1), std::move(shader2),
-                SkXfermode::kMultiply_Mode);
+                SkBlendMode::kMultiply);
         paint.setShader(std::move(composeShader));
         canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
     });
diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
index 49c4da6e..3f80d6e 100644
--- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
+++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
@@ -69,10 +69,10 @@
                 SkColorMatrixFilter::MakeLightingFilter(0x11223344, 0));
 
         SkColor observedColor;
-        SkXfermode::Mode observedMode;
+        SkBlendMode observedMode;
         ASSERT_TRUE(filter->asColorMode(&observedColor, &observedMode));
         EXPECT_EQ(0xFF223344, observedColor);
-        EXPECT_EQ(SkXfermode::Mode::kModulate_Mode, observedMode);
+        EXPECT_EQ(SkBlendMode::kModulate, observedMode);
     }
 
     {
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index 710e063..845a3ea 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -21,7 +21,6 @@
 #include <SkColorFilter.h>
 #include <SkDrawLooper.h>
 #include <SkShader.h>
-#include <SkXfermode.h>
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 89b4fb2..0b22ad5 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -31,7 +31,7 @@
 #include <SkCanvas.h>
 #include <SkColor.h>
 #include <SkPaint.h>
-#include <SkXfermode.h>
+#include <SkBlendMode.h>
 #pragma GCC diagnostic pop
 
 namespace android {
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 6941dba..18ebd47 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -30,7 +30,6 @@
 #include <SkCanvas.h>
 #include <SkColor.h>
 #include <SkPaint.h>
-#include <SkXfermode.h>
 #pragma GCC diagnostic pop
 
 #include <android/native_window.h>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index e7f5f4f..f1d1b1f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -42,7 +42,6 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Debug;
 import android.os.DropBoxManager;
 import android.os.Environment;
 import android.os.Handler;
@@ -53,6 +52,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SELinux;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
@@ -62,6 +62,7 @@
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
@@ -75,6 +76,7 @@
 import java.io.FileNotFoundException;
 import java.io.PrintWriter;
 import java.security.SecureRandom;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -114,7 +116,7 @@
  */
 @SuppressWarnings("deprecation")
 public class SettingsProvider extends ContentProvider {
-    private static final boolean DEBUG = false;
+    static final boolean DEBUG = false;
 
     private static final boolean DROP_DATABASE_ON_MIGRATION = true;
 
@@ -264,6 +266,7 @@
         }
         registerBroadcastReceivers();
         startWatchingUserRestrictionChanges();
+        ServiceManager.addService("settings", new SettingsService(this));
         return true;
     }
 
@@ -560,16 +563,14 @@
         return cacheDir;
     }
 
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
         synchronized (mLock) {
             final long identity = Binder.clearCallingIdentity();
             try {
-                List<UserInfo> users = mUserManager.getUsers(true);
+                SparseBooleanArray users = mSettingsRegistry.getKnownUsersLocked();
                 final int userCount = users.size();
                 for (int i = 0; i < userCount; i++) {
-                    UserInfo user = users.get(i);
-                    dumpForUserLocked(user.id, pw);
+                    dumpForUserLocked(users.keyAt(i), pw);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -580,49 +581,53 @@
     private void dumpForUserLocked(int userId, PrintWriter pw) {
         if (userId == UserHandle.USER_SYSTEM) {
             pw.println("GLOBAL SETTINGS (user " + userId + ")");
-            Cursor globalCursor = getAllGlobalSettings(ALL_COLUMNS);
-            dumpSettings(globalCursor, pw);
-            pw.println();
-
             SettingsState globalSettings = mSettingsRegistry.getSettingsLocked(
                     SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
+            if (globalSettings != null) {
+                dumpSettingsLocked(globalSettings, pw);
+            }
+            pw.println();
+
             globalSettings.dumpHistoricalOperations(pw);
         }
 
         pw.println("SECURE SETTINGS (user " + userId + ")");
-        Cursor secureCursor = getAllSecureSettings(userId, ALL_COLUMNS);
-        dumpSettings(secureCursor, pw);
-        pw.println();
-
         SettingsState secureSettings = mSettingsRegistry.getSettingsLocked(
                 SETTINGS_TYPE_SECURE, userId);
+        if (secureSettings != null) {
+            dumpSettingsLocked(secureSettings, pw);
+        }
+        pw.println();
+
         secureSettings.dumpHistoricalOperations(pw);
 
         pw.println("SYSTEM SETTINGS (user " + userId + ")");
-        Cursor systemCursor = getAllSystemSettings(userId, ALL_COLUMNS);
-        dumpSettings(systemCursor, pw);
-        pw.println();
-
         SettingsState systemSettings = mSettingsRegistry.getSettingsLocked(
                 SETTINGS_TYPE_SYSTEM, userId);
+        if (systemSettings != null) {
+            dumpSettingsLocked(systemSettings, pw);
+        }
+        pw.println();
+
         systemSettings.dumpHistoricalOperations(pw);
     }
 
-    private void dumpSettings(Cursor cursor, PrintWriter pw) {
-        if (cursor == null || !cursor.moveToFirst()) {
-            return;
-        }
+    private void dumpSettingsLocked(SettingsState settingsState, PrintWriter pw) {
+        List<String> names = settingsState.getSettingNamesLocked();
 
-        final int idColumnIdx = cursor.getColumnIndex(Settings.NameValueTable._ID);
-        final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
-        final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
+        final int nameCount = names.size();
 
-        do {
-            pw.append("_id:").append(toDumpString(cursor.getString(idColumnIdx)));
-            pw.append(" name:").append(toDumpString(cursor.getString(nameColumnIdx)));
-            pw.append(" value:").append(toDumpString(cursor.getString(valueColumnIdx)));
+        for (int i = 0; i < nameCount; i++) {
+            String name = names.get(i);
+            Setting setting = settingsState.getSettingLocked(name);
+            pw.print("_id:"); pw.print(toDumpString(setting.getId()));
+            pw.print(" name:"); pw.print(toDumpString(name));
+            if (setting.getPackageName() != null) {
+                pw.print(" pkg:"); pw.print(toDumpString(setting.getPackageName()));
+            }
+            pw.print(" value:"); pw.print(toDumpString(setting.getValue()));
             pw.println();
-        } while (cursor.moveToNext());
+        }
     }
 
     private static String toDumpString(String s) {
@@ -916,8 +921,9 @@
 
         // Special case for location (sigh).
         if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
-            return mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_SECURE,
-                    owningUserId).getNullSetting();
+            SettingsState settings = mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_SECURE,
+                    owningUserId);
+            return settings != null ? settings.getNullSetting() : null;
         }
 
         // Get the value.
@@ -1267,7 +1273,8 @@
                 && (parentId = getGroupParentLocked(userId)) != userId) {
             // The setting has a dependency and the profile has a parent
             String dependency = sSystemCloneFromParentOnDependency.get(setting);
-            if (getSecureSetting(dependency, userId).getValue().equals("1")) {
+            Setting settingObj = getSecureSetting(dependency, userId);
+            if (settingObj != null && settingObj.getValue().equals("1")) {
                 return parentId;
             }
         }
@@ -1405,6 +1412,9 @@
 
         Setting settingValue = getSecureSetting(
                 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
+        if (settingValue == null) {
+            return false;
+        }
 
         String oldProviders = (settingValue != null) ? settingValue.getValue() : "";
 
@@ -1491,14 +1501,14 @@
     private Bundle packageValueForCallResult(Setting setting,
             boolean trackingGeneration) {
         if (!trackingGeneration) {
-            if (setting.isNull()) {
+            if (setting == null || setting.isNull()) {
                 return NULL_SETTING_BUNDLE;
             }
             return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue());
         }
         Bundle result = new Bundle();
         result.putString(Settings.NameValueTable.VALUE,
-                !setting.isNull() ? setting.getValue() : null);
+                setting != null && !setting.isNull() ? setting.getValue() : null);
         mSettingsRegistry.mGenerationRegistry.addGenerationData(result, setting.getkey());
         return result;
     }
@@ -1554,7 +1564,7 @@
     }
 
     private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) {
-        if (setting.isNull()) {
+        if (setting == null || setting.isNull()) {
             return;
         }
         final int columnCount = cursor.getColumnCount();
@@ -1700,15 +1710,32 @@
         public List<String> getSettingsNamesLocked(int type, int userId) {
             final int key = makeKey(type, userId);
             SettingsState settingsState = peekSettingsStateLocked(key);
+            if (settingsState == null) {
+                return new ArrayList<String>();
+            }
             return settingsState.getSettingNamesLocked();
         }
 
+        public SparseBooleanArray getKnownUsersLocked() {
+            SparseBooleanArray users = new SparseBooleanArray();
+            for (int i = mSettingsStates.size()-1; i >= 0; i--) {
+                users.put(getUserIdFromKey(mSettingsStates.keyAt(i)), true);
+            }
+            return users;
+        }
+
         public SettingsState getSettingsLocked(int type, int userId) {
             final int key = makeKey(type, userId);
             return peekSettingsStateLocked(key);
         }
 
-        public void ensureSettingsForUserLocked(int userId) {
+        public boolean ensureSettingsForUserLocked(int userId) {
+            // First make sure this user actually exists.
+            if (mUserManager.getUserInfo(userId) == null) {
+                Slog.wtf(LOG_TAG, "Requested user " + userId + " does not exist");
+                return false;
+            }
+
             // Migrate the setting for this user if needed.
             migrateLegacySettingsForUserIfNeededLocked(userId);
 
@@ -1733,6 +1760,7 @@
             // Upgrade the settings to the latest version.
             UpgradeController upgrader = new UpgradeController(userId);
             upgrader.upgradeIfNeededLocked();
+            return true;
         }
 
         private void ensureSettingsStateLocked(int key) {
@@ -1790,7 +1818,8 @@
             final int key = makeKey(type, userId);
 
             SettingsState settingsState = peekSettingsStateLocked(key);
-            final boolean success = settingsState.insertSettingLocked(name, value, packageName);
+            final boolean success = settingsState != null
+                    && settingsState.insertSettingLocked(name, value, packageName);
 
             if (forceNotify || success) {
                 notifyForSettingsChange(key, name);
@@ -1802,6 +1831,9 @@
             final int key = makeKey(type, userId);
 
             SettingsState settingsState = peekSettingsStateLocked(key);
+            if (settingsState == null) {
+                return false;
+            }
             final boolean success = settingsState.deleteSettingLocked(name);
 
             if (forceNotify || success) {
@@ -1814,6 +1846,9 @@
             final int key = makeKey(type, userId);
 
             SettingsState settingsState = peekSettingsStateLocked(key);
+            if (settingsState == null) {
+                return null;
+            }
             return settingsState.getSettingLocked(name);
         }
 
@@ -1822,7 +1857,8 @@
             final int key = makeKey(type, userId);
 
             SettingsState settingsState = peekSettingsStateLocked(key);
-            final boolean success = settingsState.updateSettingLocked(name, value, packageName);
+            final boolean success = settingsState != null
+                    && settingsState.updateSettingLocked(name, value, packageName);
 
             if (forceNotify || success) {
                 notifyForSettingsChange(key, name);
@@ -1850,7 +1886,9 @@
                 return settingsState;
             }
 
-            ensureSettingsForUserLocked(getUserIdFromKey(key));
+            if (!ensureSettingsForUserLocked(getUserIdFromKey(key))) {
+                return null;
+            }
             return mSettingsStates.get(key);
         }
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
new file mode 100644
index 0000000..169b01f
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -0,0 +1,375 @@
+/*
+ * 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.
+ */
+
+package com.android.providers.settings;
+
+import android.app.ActivityManagerNative;
+import android.content.IContentProvider;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+final public class SettingsService extends Binder {
+    final SettingsProvider mProvider;
+
+    public SettingsService(SettingsProvider provider) {
+        mProvider = provider;
+    }
+
+    @Override
+    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+        (new MyShellCommand(mProvider, false)).exec(
+                this, in, out, err, args, callback, resultReceiver);
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mProvider.getContext().checkCallingPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump SettingsProvider from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " without permission "
+                    + android.Manifest.permission.DUMP);
+            return;
+        }
+
+        int opti = 0;
+        while (opti < args.length) {
+            String opt = args[opti];
+            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
+                break;
+            }
+            opti++;
+            if ("-h".equals(opt)) {
+                MyShellCommand.dumpHelp(pw, true);
+                return;
+            } else {
+                pw.println("Unknown argument: " + opt + "; use -h for help");
+            }
+        }
+
+        long caller = Binder.clearCallingIdentity();
+        try {
+            mProvider.dumpInternal(fd, pw, args);
+        } finally {
+            Binder.restoreCallingIdentity(caller);
+        }
+    }
+
+    final static class MyShellCommand extends ShellCommand {
+        final SettingsProvider mProvider;
+        final boolean mDumping;
+
+        enum CommandVerb {
+            UNSPECIFIED,
+            GET,
+            PUT,
+            DELETE,
+            LIST,
+        }
+
+        int mUser = -1;     // unspecified
+        CommandVerb mVerb = CommandVerb.UNSPECIFIED;
+        String mTable = null;
+        String mKey = null;
+        String mValue = null;
+
+
+        MyShellCommand(SettingsProvider provider, boolean dumping) {
+            mProvider = provider;
+            mDumping = dumping;
+        }
+
+        @Override
+        public int onCommand(String cmd) {
+            if (cmd == null) {
+                return handleDefaultCommands(cmd);
+            }
+
+            final PrintWriter perr = getErrPrintWriter();
+
+            boolean valid = false;
+            String arg = cmd;
+            do {
+                if ("--user".equals(arg)) {
+                    if (mUser != -1) {
+                        // --user specified more than once; invalid
+                        break;
+                    }
+                    arg = getNextArgRequired();
+                    if ("current".equals(arg) || "cur".equals(arg)) {
+                        mUser = UserHandle.USER_CURRENT;
+                    } else {
+                        mUser = Integer.parseInt(arg);
+                    }
+                } else if (mVerb == CommandVerb.UNSPECIFIED) {
+                    if ("get".equalsIgnoreCase(arg)) {
+                        mVerb = CommandVerb.GET;
+                    } else if ("put".equalsIgnoreCase(arg)) {
+                        mVerb = CommandVerb.PUT;
+                    } else if ("delete".equalsIgnoreCase(arg)) {
+                        mVerb = CommandVerb.DELETE;
+                    } else if ("list".equalsIgnoreCase(arg)) {
+                        mVerb = CommandVerb.LIST;
+                    } else {
+                        // invalid
+                        perr.println("Invalid command: " + arg);
+                        return -1;
+                    }
+                } else if (mTable == null) {
+                    if (!"system".equalsIgnoreCase(arg)
+                            && !"secure".equalsIgnoreCase(arg)
+                            && !"global".equalsIgnoreCase(arg)) {
+                        perr.println("Invalid namespace '" + arg + "'");
+                        return -1;
+                    }
+                    mTable = arg.toLowerCase();
+                    if (mVerb == CommandVerb.LIST) {
+                        valid = true;
+                        break;
+                    }
+                } else if (mVerb == CommandVerb.GET || mVerb == CommandVerb.DELETE) {
+                    mKey = arg;
+                    if (peekNextArg() == null) {
+                        valid = true;
+                    } else {
+                        perr.println("Too many arguments");
+                        return -1;
+                    }
+                    break;
+                } else if (mKey == null) {
+                    mKey = arg;
+                    // keep going; there's another PUT arg
+                } else {    // PUT, final arg
+                    mValue = arg;
+                    if (peekNextArg() == null) {
+                        valid = true;
+                    } else {
+                        perr.println("Too many arguments");
+                        return -1;
+                    }
+                    break;
+                }
+            } while ((arg = getNextArg()) != null);
+
+            if (!valid) {
+                perr.println("Bad arguments");
+                return -1;
+            }
+
+            if (mUser == UserHandle.USER_CURRENT) {
+                try {
+                    mUser = ActivityManagerNative.getDefault().getCurrentUser().id;
+                } catch (RemoteException e) {
+                    throw new RuntimeException("Failed in IPC", e);
+                }
+            }
+            if (mUser < 0) {
+                mUser = UserHandle.USER_SYSTEM;
+            } else if (mVerb == CommandVerb.DELETE || mVerb == CommandVerb.LIST) {
+                perr.println("--user not supported for delete and list.");
+                return -1;
+            }
+            UserManager userManager = UserManager.get(mProvider.getContext());
+            if (userManager.getUserInfo(mUser) == null) {
+                perr.println("Invalid user: " + mUser);
+                return -1;
+            }
+
+            final IContentProvider iprovider = mProvider.getIContentProvider();
+            final PrintWriter pout = getOutPrintWriter();
+            switch (mVerb) {
+                case GET:
+                    pout.println(getForUser(iprovider, mUser, mTable, mKey));
+                    break;
+                case PUT:
+                    putForUser(iprovider, mUser, mTable, mKey, mValue);
+                    break;
+                case DELETE:
+                    pout.println("Deleted "
+                            + deleteForUser(iprovider, mUser, mTable, mKey) + " rows");
+                    break;
+                case LIST:
+                    for (String line : listForUser(iprovider, mUser, mTable)) {
+                        pout.println(line);
+                    }
+                    break;
+                default:
+                    perr.println("Unspecified command");
+                    return -1;
+            }
+
+            return 0;
+        }
+
+        private List<String> listForUser(IContentProvider provider, int userHandle, String table) {
+            final Uri uri = "system".equals(table) ? Settings.System.CONTENT_URI
+                    : "secure".equals(table) ? Settings.Secure.CONTENT_URI
+                    : "global".equals(table) ? Settings.Global.CONTENT_URI
+                    : null;
+            final ArrayList<String> lines = new ArrayList<String>();
+            if (uri == null) {
+                return lines;
+            }
+            try {
+                final Cursor cursor = provider.query(resolveCallingPackage(), uri, null, null, null,
+                        null, null);
+                try {
+                    while (cursor != null && cursor.moveToNext()) {
+                        lines.add(cursor.getString(1) + "=" + cursor.getString(2));
+                    }
+                } finally {
+                    if (cursor != null) {
+                        cursor.close();
+                    }
+                }
+                Collections.sort(lines);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+            return lines;
+        }
+
+        String getForUser(IContentProvider provider, int userHandle,
+                final String table, final String key) {
+            final String callGetCommand;
+            if ("system".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SYSTEM;
+            else if ("secure".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SECURE;
+            else if ("global".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_GLOBAL;
+            else {
+                getErrPrintWriter().println("Invalid table; no put performed");
+                throw new IllegalArgumentException("Invalid table " + table);
+            }
+
+            String result = null;
+            try {
+                Bundle arg = new Bundle();
+                arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+                Bundle b = provider.call(resolveCallingPackage(), callGetCommand, key, arg);
+                if (b != null) {
+                    result = b.getPairValue();
+                }
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+            return result;
+        }
+
+        void putForUser(IContentProvider provider, int userHandle,
+                final String table, final String key, final String value) {
+            final String callPutCommand;
+            if ("system".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
+            else if ("secure".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SECURE;
+            else if ("global".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_GLOBAL;
+            else {
+                getErrPrintWriter().println("Invalid table; no put performed");
+                return;
+            }
+
+            try {
+                Bundle arg = new Bundle();
+                arg.putString(Settings.NameValueTable.VALUE, value);
+                arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+                provider.call(resolveCallingPackage(), callPutCommand, key, arg);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+        }
+
+        int deleteForUser(IContentProvider provider, int userHandle,
+                final String table, final String key) {
+            Uri targetUri;
+            if ("system".equals(table)) targetUri = Settings.System.getUriFor(key);
+            else if ("secure".equals(table)) targetUri = Settings.Secure.getUriFor(key);
+            else if ("global".equals(table)) targetUri = Settings.Global.getUriFor(key);
+            else {
+                getErrPrintWriter().println("Invalid table; no delete performed");
+                throw new IllegalArgumentException("Invalid table " + table);
+            }
+
+            int num = 0;
+            try {
+                num = provider.delete(resolveCallingPackage(), targetUri, null, null);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+            return num;
+        }
+
+        public static String resolveCallingPackage() {
+            switch (Binder.getCallingUid()) {
+                case Process.ROOT_UID: {
+                    return "root";
+                }
+
+                case Process.SHELL_UID: {
+                    return "com.android.shell";
+                }
+
+                default: {
+                    return null;
+                }
+            }
+        }
+
+        @Override
+        public void onHelp() {
+            PrintWriter pw = getOutPrintWriter();
+            dumpHelp(pw, mDumping);
+        }
+
+        static void dumpHelp(PrintWriter pw, boolean dumping) {
+            if (dumping) {
+                pw.println("Settings provider dump options:");
+                pw.println("  [-h]");
+                pw.println("  -h: print this help.");
+            } else {
+                pw.println("Settings provider (settings) commands:");
+                pw.println("  help");
+                pw.println("      Print this help text.");
+                pw.println("  get [--user <USER_ID> | current] NAMESPACE KEY");
+                pw.println("      Retrieve the current value of KEY.");
+                pw.println("  put [--user <USER_ID> | current] NAMESPACE KEY VALUE");
+                pw.println("      Change the contents of KEY to VALUE.");
+                pw.println("  delete NAMESPACE KEY");
+                pw.println("      Delete the entry for KEY.");
+                pw.println("  list NAMESPACE");
+                pw.println("      Print all defined keys.");
+                pw.println();
+                pw.println("  NAMESPACE is one of {system, secure, global}, case-insensitive");
+            }
+        }
+    }
+}
+
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 832c9d9..d682fe9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -350,8 +350,11 @@
                 pw.print(" ");
                 pw.print(operation.mOperation);
                 if (operation.mSetting != null) {
-                    pw.print("  ");
-                    pw.print(operation.mSetting);
+                    pw.print(" ");
+                    // Only print the name of the setting, since we don't know the
+                    // historical package and values for it so they would be misleading
+                    // to print here (all we could print is what the current data is).
+                    pw.print(operation.mSetting.getName());
                 }
                 pw.println();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 484e008..dc68112 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -44,6 +44,9 @@
 import com.android.systemui.statusbar.phone.QSTileHost;
 import libcore.util.Objects;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+
 public class CustomTile extends QSTile<QSTile.State> implements TileChangeListener {
     public static final String PREFIX = "custom(";
 
@@ -171,7 +174,7 @@
         mIsShowingDialog = false;
         try {
             if (DEBUG) Log.d(TAG, "Removing token");
-            mWindowManager.removeWindowToken(mToken);
+            mWindowManager.removeWindowToken(mToken, DEFAULT_DISPLAY);
         } catch (RemoteException e) {
         }
     }
@@ -193,7 +196,7 @@
                 if (mIsTokenGranted && !mIsShowingDialog) {
                     try {
                         if (DEBUG) Log.d(TAG, "Removing token");
-                        mWindowManager.removeWindowToken(mToken);
+                        mWindowManager.removeWindowToken(mToken, DEFAULT_DISPLAY);
                     } catch (RemoteException e) {
                     }
                     mIsTokenGranted = false;
@@ -212,7 +215,7 @@
         if (mIsTokenGranted) {
             try {
                 if (DEBUG) Log.d(TAG, "Removing token");
-                mWindowManager.removeWindowToken(mToken);
+                mWindowManager.removeWindowToken(mToken, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
             }
         }
@@ -252,7 +255,7 @@
         }
         try {
             if (DEBUG) Log.d(TAG, "Adding token");
-            mWindowManager.addWindowToken(mToken, WindowManager.LayoutParams.TYPE_QS_DIALOG);
+            mWindowManager.addWindowToken(mToken, TYPE_QS_DIALOG, DEFAULT_DISPLAY);
             mIsTokenGranted = true;
         } catch (RemoteException e) {
         }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 4819c0a..c89f158 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -17,6 +17,8 @@
 package com.android.server.accessibility;
 
 import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 
 import android.Manifest;
 import android.accessibilityservice.AccessibilityService;
@@ -3129,7 +3131,7 @@
             final long identity = Binder.clearCallingIdentity();
             try {
                 mWindowManagerService.addWindowToken(mOverlayWindowToken,
-                        WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY);
+                        TYPE_ACCESSIBILITY_OVERLAY, DEFAULT_DISPLAY);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -3138,7 +3140,7 @@
         public void onRemoved() {
             final long identity = Binder.clearCallingIdentity();
             try {
-                mWindowManagerService.removeWindowToken(mOverlayWindowToken, true);
+                mWindowManagerService.removeWindowToken(mOverlayWindowToken, true, DEFAULT_DISPLAY);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -3668,7 +3670,7 @@
                     return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER;
                 }
 
-                case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: {
+                case TYPE_ACCESSIBILITY_OVERLAY: {
                     return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
                 }
 
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index df1b6f5..6e871a8 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -15,6 +15,8 @@
 
 package com.android.server;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import com.android.internal.content.PackageMonitor;
@@ -1481,8 +1483,7 @@
             mCurToken = new Binder();
             try {
                 if (true || DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
-                mIWindowManager.addWindowToken(mCurToken,
-                        WindowManager.LayoutParams.TYPE_INPUT_METHOD);
+                mIWindowManager.addWindowToken(mCurToken, TYPE_INPUT_METHOD, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
             }
             return new InputBindResult(null, null, mCurId, mCurSeq,
@@ -1590,7 +1591,7 @@
                     // The current IME is shown. Hence an IME switch (transition) is happening.
                     mWindowManagerInternal.saveLastInputMethodWindowForTransition();
                 }
-                mIWindowManager.removeWindowToken(mCurToken);
+                mIWindowManager.removeWindowToken(mCurToken, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
             }
             mCurToken = null;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index ffe2185..1c3a8851 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3714,7 +3714,7 @@
         r.state = ActivityState.DESTROYED;
         if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
         r.app = null;
-        mWindowManager.removeAppToken(r.appToken);
+        mWindowManager.removeAppToken(r.appToken, r.getDisplayId());
         final TaskRecord task = r.task;
         if (task != null && task.removeActivity(r)) {
             if (DEBUG_STACK) Slog.i(TAG_STACK,
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 3072f43..393199d 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -44,6 +44,9 @@
 import java.io.PrintWriter;
 import java.util.NoSuchElementException;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+
 /**
  * Internal controller for starting and stopping the current dream and managing related state.
  *
@@ -138,7 +141,7 @@
                     mCurrentDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
 
             try {
-                mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
+                mIWindowManager.addWindowToken(token, TYPE_DREAM, DEFAULT_DISPLAY);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "Unable to add window token for dream.", ex);
                 stopDream(true /*immediate*/);
@@ -236,7 +239,7 @@
             oldDream.releaseWakeLockIfNeeded();
 
             try {
-                mIWindowManager.removeWindowToken(oldDream.mToken);
+                mIWindowManager.removeWindowToken(oldDream.mToken, DEFAULT_DISPLAY);
             } catch (RemoteException ex) {
                 Slog.w(TAG, "Error removing window token for dream.", ex);
             }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d782211..6ebdb3c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -43,6 +43,8 @@
 import static android.service.notification.NotificationListenerService.TRIM_FULL;
 import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 
 import android.Manifest;
@@ -1402,8 +1404,7 @@
                         }
 
                         Binder token = new Binder();
-                        mWindowManagerInternal.addWindowToken(token,
-                                WindowManager.LayoutParams.TYPE_TOAST);
+                        mWindowManagerInternal.addWindowToken(token, TYPE_TOAST, DEFAULT_DISPLAY);
                         record = new ToastRecord(callingPid, pkg, callback, duration, token);
                         mToastQueue.add(record);
                         index = mToastQueue.size() - 1;
@@ -3253,7 +3254,7 @@
         }
 
         ToastRecord lastToast = mToastQueue.remove(index);
-        mWindowManagerInternal.removeWindowToken(lastToast.token, true);
+        mWindowManagerInternal.removeWindowToken(lastToast.token, true, DEFAULT_DISPLAY);
 
         keepProcessAliveIfNeededLocked(record.pid);
         if (mToastQueue.size() > 0) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a15af3c..67488ce 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1487,8 +1487,7 @@
         // Skip over users being removed
         for (int i = 0; i < totalUserCount; i++) {
             UserInfo user = mUsers.valueAt(i).info;
-            if (!mRemovingUserIds.get(user.id)
-                    && !user.isGuest() && !user.partial) {
+            if (!mRemovingUserIds.get(user.id) && !user.isGuest()) {
                 aliveUserCount++;
             }
         }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 6b967a2..d755e58 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2631,9 +2631,18 @@
                 state = new UidState(uid);
                 mUidState.put(uid, state);
             }
+            final boolean oldShouldAllow = state.mProcState
+                    <= ActivityManager.PROCESS_STATE_RECEIVER;
             state.mProcState = procState;
-            if (mDeviceIdleMode && state.mNumWakeLocks > 0) {
-                handleUidStateChangeLocked();
+            if (state.mNumWakeLocks > 0) {
+                if (mDeviceIdleMode) {
+                    handleUidStateChangeLocked();
+                } else if (!state.mActive && oldShouldAllow !=
+                        (procState <= ActivityManager.PROCESS_STATE_RECEIVER)) {
+                    // If this uid is not active, but the process state has changed such
+                    // that we may still want to allow it to hold a wake lock, then take care of it.
+                    handleUidStateChangeLocked();
+                }
             }
         }
     }
@@ -2721,7 +2730,8 @@
                         disabled = true;
                     }
                 } else {
-                    disabled = !wakeLock.mUidState.mActive;
+                    disabled = !wakeLock.mUidState.mActive &&
+                            wakeLock.mUidState.mProcState > ActivityManager.PROCESS_STATE_RECEIVER;
                 }
             }
             if (wakeLock.mDisabled != disabled) {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 7439f535..96662b5 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -22,6 +22,8 @@
 import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
 import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
 import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
@@ -1692,8 +1694,7 @@
                 if (wallpaper.userId == mCurrentUserId) {
                     if (DEBUG)
                         Slog.v(TAG, "Adding window token: " + newConn.mToken);
-                    mIWindowManager.addWindowToken(newConn.mToken,
-                            WindowManager.LayoutParams.TYPE_WALLPAPER);
+                    mIWindowManager.addWindowToken(newConn.mToken, TYPE_WALLPAPER, DEFAULT_DISPLAY);
                     mLastWallpaper = wallpaper;
                 }
             } catch (RemoteException e) {
@@ -1728,7 +1729,7 @@
             try {
                 if (DEBUG)
                     Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
-                mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
+                mIWindowManager.removeWindowToken(wallpaper.connection.mToken, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
             }
             wallpaper.connection.mService = null;
@@ -1745,7 +1746,7 @@
     void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
         try {
             conn.mService.attach(conn, conn.mToken,
-                    WindowManager.LayoutParams.TYPE_WALLPAPER, false,
+                    TYPE_WALLPAPER, false,
                     wallpaper.width, wallpaper.height, wallpaper.padding);
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index a44c8aa..622eece 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -26,22 +26,27 @@
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
 import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowManagerService.logWithStack;
 
+import android.os.Debug;
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.wm.WindowManagerService.H;
 
@@ -398,6 +403,63 @@
         return super.checkCompleteDeferredRemoval();
     }
 
+    void onRemovedFromDisplay() {
+        AppWindowToken startingToken = null;
+
+        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
+
+        boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, voiceInteraction);
+
+        mService.mOpeningApps.remove(this);
+        waitingToShow = false;
+        if (mService.mClosingApps.contains(this)) {
+            delayed = true;
+        } else if (mService.mAppTransition.isTransitionSet()) {
+            mService.mClosingApps.add(this);
+            delayed = true;
+        }
+
+        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
+                + " animation=" + mAppAnimator.animation + " animating=" + mAppAnimator.animating);
+
+        if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
+                + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
+
+        final TaskStack stack = mTask.mStack;
+        if (delayed && !isEmpty()) {
+            // set the token aside because it has an active animation to be finished
+            if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
+                    "removeAppToken make exiting: " + this);
+            stack.mExitingAppTokens.add(this);
+            mIsExiting = true;
+        } else {
+            // Make sure there is no animation running on this token, so any windows associated
+            // with it will be removed as soon as their animations are complete
+            mAppAnimator.clearAnimation();
+            mAppAnimator.animating = false;
+            removeIfPossible();
+        }
+
+        removed = true;
+        if (startingData != null) {
+            startingToken = this;
+        }
+        stopFreezingScreen(true, true);
+        if (mService.mFocusedApp == this) {
+            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this);
+            mService.mFocusedApp = null;
+            mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
+            mService.mInputMonitor.setFocusedAppLw(null);
+        }
+
+        if (!delayed) {
+            updateReportedVisibilityLocked();
+        }
+
+        // Will only remove if startingToken non null.
+        mService.scheduleRemoveStartingWindowLocked(startingToken);
+    }
+
     void clearAnimatingFlags() {
         boolean wallpaperMightChange = false;
         for (int i = mChildren.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 1960285..13099dc 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -62,7 +62,6 @@
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
@@ -314,6 +313,23 @@
         return token;
     }
 
+    void removeAppToken(IBinder binder) {
+        final WindowToken token = removeWindowToken(binder);
+        if (token == null) {
+            Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
+            return;
+        }
+
+        final AppWindowToken appToken = token.asAppWindowToken();
+
+        if (appToken == null) {
+            Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
+            return;
+        }
+
+        appToken.onRemovedFromDisplay();
+    }
+
     Display getDisplay() {
         return mDisplay;
     }
@@ -638,7 +654,7 @@
         rebuildAppWindowList();
     }
 
-    void resetAnimationBackgroundAnimator() {
+    private void resetAnimationBackgroundAnimator() {
         for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
             mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator();
         }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 26f79a9..6325cda 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -126,15 +126,6 @@
 
     private final ArrayList<Integer> mChangedStackList = new ArrayList();
 
-    private final ArrayList<WindowToken> mTmpTokensList = new ArrayList();
-
-    // Collection of binder tokens mapped to their window type we are allowed to create window
-    // tokens for but that are not current attached to any display. We need to track this here
-    // because a binder token can be added through {@link WindowManagerService#addWindowToken},
-    // but we don't know what display windows for the token will be added to until
-    // {@link WindowManagerService#addWindow} is called.
-    private final HashMap<IBinder, Integer> mUnattachedBinderTokens = new HashMap();
-
     // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl
     // instances will be replaced with an instance that writes a binary representation of all
     // commands to mSurfaceTraceFd.
@@ -340,36 +331,6 @@
         return null;
     }
 
-    /** Return the window token associated with the input binder token on the input display */
-    WindowToken getWindowToken(IBinder binder, DisplayContent dc) {
-        final WindowToken token = dc.getWindowToken(binder);
-        if (token != null) {
-            return token;
-        }
-
-        // There is no window token mapped to the binder on the display. Create and map a window
-        // token if it is currently allowed.
-        if (!mUnattachedBinderTokens.containsKey(binder)) {
-            return null;
-        }
-
-        final int type = mUnattachedBinderTokens.get(binder);
-        return new WindowToken(mService, binder, type, true, dc);
-    }
-
-    /** Returns all window tokens mapped to the input binder. */
-    ArrayList<WindowToken> getWindowTokens(IBinder binder) {
-        mTmpTokensList.clear();
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final DisplayContent dc = mChildren.get(i);
-            final WindowToken token = dc.getWindowToken(binder);
-            if (token != null) {
-                mTmpTokensList.add(token);
-            }
-        }
-        return mTmpTokensList;
-    }
-
     /**
      * Returns the app window token for the input binder if it exist in the system.
      * NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since
@@ -403,140 +364,6 @@
         return null;
     }
 
-    void addWindowToken(IBinder binder, int type) {
-        if (mUnattachedBinderTokens.containsKey(binder)) {
-            Slog.w(TAG_WM, "addWindowToken: Attempted to add existing binder token: " + binder);
-            return;
-        }
-
-        final ArrayList<WindowToken> tokens = getWindowTokens(binder);
-
-        if (!tokens.isEmpty()) {
-            Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
-                    + " for already created window tokens: " + tokens);
-            return;
-        }
-
-        mUnattachedBinderTokens.put(binder, type);
-
-        // TODO(multi-display): By default we add this to the default display, but maybe we
-        // should provide an API for a token to be added to any display?
-        final DisplayContent dc = getDisplayContent(DEFAULT_DISPLAY);
-        final WindowToken token = new WindowToken(mService, binder, type, true, dc);
-        if (type == TYPE_WALLPAPER) {
-            dc.mWallpaperController.addWallpaperToken(token);
-        }
-    }
-
-    ArrayList<WindowToken> removeWindowToken(IBinder binder) {
-        mUnattachedBinderTokens.remove(binder);
-
-        mTmpTokensList.clear();
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final DisplayContent dc = mChildren.get(i);
-            final WindowToken token = dc.removeWindowToken(binder);
-            if (token != null) {
-                mTmpTokensList.add(token);
-            }
-        }
-        return mTmpTokensList;
-    }
-
-    /**
-     * Removed the mapping to the input binder for the system if it no longer as a window token
-     * associated with it on any display.
-     */
-    void removeWindowTokenIfPossible(IBinder binder) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final DisplayContent dc = mChildren.get(i);
-            final WindowToken token = dc.getWindowToken(binder);
-            if (token != null) {
-                return;
-            }
-        }
-
-        mUnattachedBinderTokens.remove(binder);
-    }
-
-    void removeAppToken(IBinder binder) {
-        final ArrayList<WindowToken> removedTokens = removeWindowToken(binder);
-        if (removedTokens == null || removedTokens.isEmpty()) {
-            Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
-            return;
-        }
-
-        for (int i = removedTokens.size() - 1; i >= 0; --i) {
-            WindowToken wtoken = removedTokens.get(i);
-            AppWindowToken appToken = wtoken.asAppWindowToken();
-
-            if (appToken == null) {
-                Slog.w(TAG_WM,
-                        "Attempted to remove non-App token: " + binder + " wtoken=" + wtoken);
-                continue;
-            }
-
-            AppWindowToken startingToken = null;
-
-            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + appToken);
-
-            boolean delayed = appToken.setVisibility(null, false, TRANSIT_UNSET, true,
-                    appToken.voiceInteraction);
-
-            mService.mOpeningApps.remove(appToken);
-            mService.mUnknownAppVisibilityController.appRemoved(appToken);
-            appToken.waitingToShow = false;
-            if (mService.mClosingApps.contains(appToken)) {
-                delayed = true;
-            } else if (mService.mAppTransition.isTransitionSet()) {
-                mService.mClosingApps.add(appToken);
-                delayed = true;
-            }
-
-            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + appToken
-                    + " delayed=" + delayed
-                    + " animation=" + appToken.mAppAnimator.animation
-                    + " animating=" + appToken.mAppAnimator.animating);
-
-            if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
-                    + appToken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
-
-            final TaskStack stack = appToken.mTask.mStack;
-            if (delayed && !appToken.isEmpty()) {
-                // set the token aside because it has an active animation to be finished
-                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
-                        "removeAppToken make exiting: " + appToken);
-                stack.mExitingAppTokens.add(appToken);
-                appToken.mIsExiting = true;
-            } else {
-                // Make sure there is no animation running on this token, so any windows associated
-                // with it will be removed as soon as their animations are complete
-                appToken.mAppAnimator.clearAnimation();
-                appToken.mAppAnimator.animating = false;
-                appToken.removeIfPossible();
-            }
-
-            appToken.removed = true;
-            if (appToken.startingData != null) {
-                startingToken = appToken;
-            }
-            appToken.stopFreezingScreen(true, true);
-            if (mService.mFocusedApp == appToken) {
-                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + appToken);
-                mService.mFocusedApp = null;
-                mService.updateFocusedWindowLocked(
-                        UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
-                mService.mInputMonitor.setFocusedAppLw(null);
-            }
-
-            if (!delayed) {
-                appToken.updateReportedVisibilityLocked();
-            }
-
-            // Will only remove if startingToken non null.
-            mService.scheduleRemoveStartingWindowLocked(startingToken);
-        }
-    }
-
     // TODO: Users would have their own window containers under the display container?
     void switchUser() {
         final int count = mChildren.size();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2fef928..66b2cbc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1166,8 +1166,8 @@
             final boolean hasParent = parentWindow != null;
             // Use existing parent window token for child windows since they go in the same token
             // as there parent window so we can apply the same policy on them.
-            WindowToken token = mRoot.getWindowToken(
-                    hasParent ? parentWindow.mAttrs.token : attrs.token, displayContent);
+            WindowToken token = displayContent.getWindowToken(
+                    hasParent ? parentWindow.mAttrs.token : attrs.token);
             // If this is a child window, we want to apply the same type checking rules as the
             // parent window type.
             final int rootType = hasParent ? parentWindow.mAttrs.type : type;
@@ -2395,18 +2395,29 @@
     }
 
     @Override
-    public void addWindowToken(IBinder token, int type) {
+    public void addWindowToken(IBinder binder, int type, int displayId) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized(mWindowMap) {
-            mRoot.addWindowToken(token, type);
+            final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
+            WindowToken token = dc.getWindowToken(binder);
+            if (token != null) {
+                Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
+                        + " for already created window token: " + token
+                        + " displayId=" + displayId);
+                return;
+            }
+            token = new WindowToken(this, binder, type, true, dc);
+            if (type == TYPE_WALLPAPER) {
+                dc.mWallpaperController.addWallpaperToken(token);
+            }
         }
     }
 
     @Override
-    public void removeWindowToken(IBinder token) {
+    public void removeWindowToken(IBinder binder, int displayId) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
@@ -2414,22 +2425,26 @@
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mWindowMap) {
-                final ArrayList<WindowToken> removedTokens = mRoot.removeWindowToken(token);
-                if (removedTokens == null || removedTokens.isEmpty()) {
-                    Slog.w(TAG_WM,
-                            "removeWindowToken: Attempted to remove non-existing token: " + token);
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
+                            + " for non-exiting displayId=" + displayId);
                     return;
                 }
 
-                for (int i = removedTokens.size() - 1; i >= 0; --i) {
-                    final WindowToken wtoken = removedTokens.get(i);
-                    wtoken.setExiting();
-                    if (wtoken.windowType == TYPE_WALLPAPER) {
-                        wtoken.getDisplayContent().mWallpaperController.removeWallpaperToken(wtoken);
-                    }
-
-                    mInputMonitor.updateInputWindowsLw(true /*force*/);
+                final WindowToken token = dc.removeWindowToken(binder);
+                if (token == null) {
+                    Slog.w(TAG_WM,
+                            "removeWindowToken: Attempted to remove non-existing token: " + binder);
+                    return;
                 }
+
+                token.setExiting();
+                if (token.windowType == TYPE_WALLPAPER) {
+                    dc.mWallpaperController.removeWallpaperToken(token);
+                }
+
+                mInputMonitor.updateInputWindowsLw(true /*force*/);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -3262,7 +3277,7 @@
     }
 
     @Override
-    public void removeAppToken(IBinder token) {
+    public void removeAppToken(IBinder binder, int displayId) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeAppToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
@@ -3270,7 +3285,13 @@
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                mRoot.removeAppToken(token);
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    Slog.w(TAG_WM, "removeAppToken: Attempted to remove binder token: " + binder
+                            + " from non-existing displayId=" + displayId);
+                    return;
+                }
+                dc.removeAppToken(binder);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -5790,33 +5811,29 @@
     private boolean mEventDispatchingEnabled;
 
     @Override
-    public void pauseKeyDispatching(IBinder _token) {
+    public void pauseKeyDispatching(IBinder binder) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "pauseKeyDispatching()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized (mWindowMap) {
-            final ArrayList<WindowToken> tokens = mRoot.getWindowTokens(_token);
-            if (tokens != null && !tokens.isEmpty()) {
-                for (int i = tokens.size() - 1; i >= 0; --i) {
-                    mInputMonitor.pauseDispatchingLw(tokens.get(i));
-                }
+            WindowToken token = mRoot.getAppWindowToken(binder);
+            if (token != null) {
+                mInputMonitor.pauseDispatchingLw(token);
             }
         }
     }
 
     @Override
-    public void resumeKeyDispatching(IBinder _token) {
+    public void resumeKeyDispatching(IBinder binder) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "resumeKeyDispatching()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized (mWindowMap) {
-            final ArrayList<WindowToken> tokens = mRoot.getWindowTokens(_token);
-            if (tokens != null && !tokens.isEmpty()) {
-                for (int i = tokens.size() - 1; i >= 0; --i) {
-                    mInputMonitor.resumeDispatchingLw(tokens.get(i));
-                }
+            WindowToken token = mRoot.getAppWindowToken(binder);
+            if (token != null) {
+                mInputMonitor.resumeDispatchingLw(token);
             }
         }
     }
@@ -8807,23 +8824,31 @@
         }
 
         @Override
-        public void addWindowToken(IBinder token, int type) {
-            WindowManagerService.this.addWindowToken(token, type);
+        public void addWindowToken(IBinder token, int type, int displayId) {
+            WindowManagerService.this.addWindowToken(token, type, displayId);
         }
 
         @Override
-        public void removeWindowToken(IBinder token, boolean removeWindows) {
+        public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) {
             synchronized(mWindowMap) {
                 if (removeWindows) {
-                    final ArrayList<WindowToken> removedTokens = mRoot.removeWindowToken(token);
-                    if (removedTokens != null && !removedTokens.isEmpty()) {
-                        for (int i = removedTokens.size() - 1; i >= 0; --i) {
-                            final WindowToken wtoken = removedTokens.get(i);
-                            wtoken.removeAllWindows();
-                        }
+                    final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                    if (dc == null) {
+                        Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
+                                + " for non-exiting displayId=" + displayId);
+                        return;
                     }
+
+                    final WindowToken token = dc.removeWindowToken(binder);
+                    if (token == null) {
+                        Slog.w(TAG_WM, "removeWindowToken: Attempted to remove non-existing token: "
+                                + binder);
+                        return;
+                    }
+
+                    token.removeAllWindows();
                 }
-                WindowManagerService.this.removeWindowToken(token);
+                WindowManagerService.this.removeWindowToken(binder, displayId);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index cf1a98a..b821f09 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -469,7 +469,6 @@
     void removeImmediately() {
         if (mDisplayContent != null) {
             mDisplayContent.removeWindowToken(token);
-            mService.mRoot.removeWindowTokenIfPossible(token);
         }
         // Needs to occur after the token is removed from the display above to avoid attempt at
         // duplicate removal of this window container from it's parent.
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 1f0422b..40d8ac0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -37,6 +37,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /** Test {@link UserManager} functionality. */
 public class UserManagerTest extends AndroidTestCase {
@@ -441,6 +445,33 @@
         switchUser(startUser);
     }
 
+    @MediumTest
+    public void testConcurrentUserCreate() throws Exception {
+        int userCount = mUserManager.getUserCount();
+        int maxSupportedUsers = UserManager.getMaxSupportedUsers();
+        int canBeCreatedCount = maxSupportedUsers - userCount;
+        // Test exceeding the limit while running in parallel
+        int createUsersCount = canBeCreatedCount + 5;
+        ExecutorService es = Executors.newCachedThreadPool();
+        AtomicInteger created = new AtomicInteger();
+        for (int i = 0; i < createUsersCount; i++) {
+            final String userName = "testConcUser" + i;
+            es.submit(() -> {
+                UserInfo user = mUserManager.createUser(userName, 0);
+                if (user != null) {
+                    created.incrementAndGet();
+                    synchronized (mUserRemoveLock) {
+                        usersToRemove.add(user.id);
+                    }
+                }
+            });
+        }
+        es.shutdown();
+        es.awaitTermination(20, TimeUnit.SECONDS);
+        assertEquals(maxSupportedUsers, mUserManager.getUserCount());
+        assertEquals(canBeCreatedCount, created.get());
+    }
+
     private boolean isPackageInstalledForUser(String packageName, int userId) {
         try {
             return mPackageManager.getPackageInfoAsUser(packageName, 0, userId) != null;
@@ -523,4 +554,5 @@
         }
         return profile;
     }
+
 }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 8268b40..7dacf16 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -59,6 +59,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+
 final class VoiceInteractionSessionConnection implements ServiceConnection {
 
     final static String TAG = "VoiceInteractionServiceManager";
@@ -198,8 +201,7 @@
                         | Context.BIND_ALLOW_OOM_MANAGEMENT, new UserHandle(mUser));
         if (mBound) {
             try {
-                mIWindowManager.addWindowToken(mToken,
-                        WindowManager.LayoutParams.TYPE_VOICE_INTERACTION);
+                mIWindowManager.addWindowToken(mToken, TYPE_VOICE_INTERACTION, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Failed adding window token", e);
             }
@@ -501,7 +503,7 @@
             }
             mContext.unbindService(this);
             try {
-                mIWindowManager.removeWindowToken(mToken);
+                mIWindowManager.removeWindowToken(mToken, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Failed removing window token", e);
             }
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index df7d539..f3fada9 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -93,7 +93,8 @@
             ParcelableConnection connection) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.handleCreateConnectionComplete(id, request, connection);
+                adapter.handleCreateConnectionComplete(id, request, connection,
+                        Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -108,7 +109,7 @@
     void setActive(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setActive(callId);
+                adapter.setActive(callId, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -122,7 +123,7 @@
     void setRinging(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setRinging(callId);
+                adapter.setRinging(callId, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -136,7 +137,7 @@
     void setDialing(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setDialing(callId);
+                adapter.setDialing(callId, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -151,7 +152,7 @@
     void setPulling(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setPulling(callId);
+                adapter.setPulling(callId, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -167,7 +168,7 @@
     void setDisconnected(String callId, DisconnectCause disconnectCause) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setDisconnected(callId, disconnectCause);
+                adapter.setDisconnected(callId, disconnectCause, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -181,7 +182,7 @@
     void setOnHold(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setOnHold(callId);
+                adapter.setOnHold(callId, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -196,7 +197,7 @@
     void setRingbackRequested(String callId, boolean ringback) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setRingbackRequested(callId, ringback);
+                adapter.setRingbackRequested(callId, ringback, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -205,7 +206,7 @@
     void setConnectionCapabilities(String callId, int capabilities) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setConnectionCapabilities(callId, capabilities);
+                adapter.setConnectionCapabilities(callId, capabilities, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -214,7 +215,7 @@
     void setConnectionProperties(String callId, int properties) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setConnectionProperties(callId, properties);
+                adapter.setConnectionProperties(callId, properties, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -232,7 +233,7 @@
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
                 Log.d(this, "sending connection %s with conference %s", callId, conferenceCallId);
-                adapter.setIsConferenced(callId, conferenceCallId);
+                adapter.setIsConferenced(callId, conferenceCallId, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -247,7 +248,7 @@
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
                 Log.d(this, "merge failed for call %s", callId);
-                adapter.setConferenceMergeFailed(callId);
+                adapter.setConferenceMergeFailed(callId, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -262,7 +263,7 @@
     void removeCall(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.removeCall(callId);
+                adapter.removeCall(callId, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -271,7 +272,7 @@
     void onPostDialWait(String callId, String remaining) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.onPostDialWait(callId, remaining);
+                adapter.onPostDialWait(callId, remaining, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -280,7 +281,7 @@
     void onPostDialChar(String callId, char nextChar) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.onPostDialChar(callId, nextChar);
+                adapter.onPostDialChar(callId, nextChar, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -294,7 +295,7 @@
     void addConferenceCall(String callId, ParcelableConference parcelableConference) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.addConferenceCall(callId, parcelableConference);
+                adapter.addConferenceCall(callId, parcelableConference, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -307,7 +308,8 @@
         // Only supported when there is only one adapter.
         if (mAdapters.size() == 1) {
             try {
-                mAdapters.iterator().next().queryRemoteConnectionServices(callback);
+                mAdapters.iterator().next().queryRemoteConnectionServices(callback,
+                        Log.getExternalSession());
             } catch (RemoteException e) {
                 Log.e(this, e, "Exception trying to query for remote CSs");
             }
@@ -326,7 +328,8 @@
             try {
                 adapter.setVideoProvider(
                         callId,
-                        videoProvider == null ? null : videoProvider.getInterface());
+                        videoProvider == null ? null : videoProvider.getInterface(),
+                        Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -341,7 +344,7 @@
     void setIsVoipAudioMode(String callId, boolean isVoip) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setIsVoipAudioMode(callId, isVoip);
+                adapter.setIsVoipAudioMode(callId, isVoip, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -350,7 +353,7 @@
     void setStatusHints(String callId, StatusHints statusHints) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setStatusHints(callId, statusHints);
+                adapter.setStatusHints(callId, statusHints, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -359,7 +362,7 @@
     void setAddress(String callId, Uri address, int presentation) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setAddress(callId, address, presentation);
+                adapter.setAddress(callId, address, presentation, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -368,7 +371,8 @@
     void setCallerDisplayName(String callId, String callerDisplayName, int presentation) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setCallerDisplayName(callId, callerDisplayName, presentation);
+                adapter.setCallerDisplayName(callId, callerDisplayName, presentation,
+                        Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -389,7 +393,7 @@
         Log.v(this, "setVideoState: %d", videoState);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setVideoState(callId, videoState);
+                adapter.setVideoState(callId, videoState, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -399,7 +403,8 @@
         Log.v(this, "setConferenceableConnections: %s, %s", callId, conferenceableCallIds);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setConferenceableConnections(callId, conferenceableCallIds);
+                adapter.setConferenceableConnections(callId, conferenceableCallIds,
+                        Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -415,7 +420,7 @@
         Log.v(this, "addExistingConnection: %s", callId);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.addExistingConnection(callId, connection);
+                adapter.addExistingConnection(callId, connection, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -431,7 +436,7 @@
         Log.v(this, "putExtras: %s", callId);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.putExtras(callId, extras);
+                adapter.putExtras(callId, extras, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -450,7 +455,7 @@
             try {
                 Bundle bundle = new Bundle();
                 bundle.putBoolean(key, value);
-                adapter.putExtras(callId, bundle);
+                adapter.putExtras(callId, bundle, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -469,7 +474,7 @@
             try {
                 Bundle bundle = new Bundle();
                 bundle.putInt(key, value);
-                adapter.putExtras(callId, bundle);
+                adapter.putExtras(callId, bundle, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -488,7 +493,7 @@
             try {
                 Bundle bundle = new Bundle();
                 bundle.putString(key, value);
-                adapter.putExtras(callId, bundle);
+                adapter.putExtras(callId, bundle, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -503,7 +508,7 @@
         Log.v(this, "removeExtras: %s %s", callId, keys);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.removeExtras(callId, keys);
+                adapter.removeExtras(callId, keys, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -520,7 +525,7 @@
         Log.v(this, "onConnectionEvent: %s", event);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.onConnectionEvent(callId, event, extras);
+                adapter.onConnectionEvent(callId, event, extras, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 486f9d5..afe5e33 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -21,6 +21,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
+import android.telecom.Logging.Session;
 
 import com.android.internal.os.SomeArgs;
 import com.android.internal.telecom.IConnectionServiceAdapter;
@@ -87,49 +88,55 @@
                         mDelegate.handleCreateConnectionComplete(
                                 (String) args.arg1,
                                 (ConnectionRequest) args.arg2,
-                                (ParcelableConnection) args.arg3);
+                                (ParcelableConnection) args.arg3,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_SET_ACTIVE:
-                    mDelegate.setActive((String) msg.obj);
+                    mDelegate.setActive((String) msg.obj, null /*Session.Info*/);
                     break;
                 case MSG_SET_RINGING:
-                    mDelegate.setRinging((String) msg.obj);
+                    mDelegate.setRinging((String) msg.obj, null /*Session.Info*/);
                     break;
                 case MSG_SET_DIALING:
-                    mDelegate.setDialing((String) msg.obj);
+                    mDelegate.setDialing((String) msg.obj, null /*Session.Info*/);
                     break;
                 case MSG_SET_PULLING:
-                    mDelegate.setPulling((String) msg.obj);
+                    mDelegate.setPulling((String) msg.obj, null /*Session.Info*/);
                     break;
                 case MSG_SET_DISCONNECTED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setDisconnected((String) args.arg1, (DisconnectCause) args.arg2);
+                        mDelegate.setDisconnected((String) args.arg1, (DisconnectCause) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_SET_ON_HOLD:
-                    mDelegate.setOnHold((String) msg.obj);
+                    mDelegate.setOnHold((String) msg.obj, null /*Session.Info*/);
                     break;
                 case MSG_SET_RINGBACK_REQUESTED:
-                    mDelegate.setRingbackRequested((String) msg.obj, msg.arg1 == 1);
+                    mDelegate.setRingbackRequested((String) msg.obj, msg.arg1 == 1,
+                            null /*Session.Info*/);
                     break;
                 case MSG_SET_CONNECTION_CAPABILITIES:
-                    mDelegate.setConnectionCapabilities((String) msg.obj, msg.arg1);
+                    mDelegate.setConnectionCapabilities((String) msg.obj, msg.arg1,
+                            null /*Session.Info*/);
                     break;
                 case MSG_SET_CONNECTION_PROPERTIES:
-                    mDelegate.setConnectionProperties((String) msg.obj, msg.arg1);
+                    mDelegate.setConnectionProperties((String) msg.obj, msg.arg1,
+                            null /*Session.Info*/);
                     break;
                 case MSG_SET_IS_CONFERENCED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setIsConferenced((String) args.arg1, (String) args.arg2);
+                        mDelegate.setIsConferenced((String) args.arg1, (String) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -139,19 +146,22 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         mDelegate.addConferenceCall(
-                                (String) args.arg1, (ParcelableConference) args.arg2);
+                                (String) args.arg1, (ParcelableConference) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_REMOVE_CALL:
-                    mDelegate.removeCall((String) msg.obj);
+                    mDelegate.removeCall((String) msg.obj,
+                            null /*Session.Info*/);
                     break;
                 case MSG_ON_POST_DIAL_WAIT: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.onPostDialWait((String) args.arg1, (String) args.arg2);
+                        mDelegate.onPostDialWait((String) args.arg1, (String) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -160,35 +170,39 @@
                 case MSG_ON_POST_DIAL_CHAR: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.onPostDialChar((String) args.arg1, (char) args.argi1);
+                        mDelegate.onPostDialChar((String) args.arg1, (char) args.argi1,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_QUERY_REMOTE_CALL_SERVICES:
-                    mDelegate.queryRemoteConnectionServices((RemoteServiceCallback) msg.obj);
+                    mDelegate.queryRemoteConnectionServices((RemoteServiceCallback) msg.obj,
+                            null /*Session.Info*/);
                     break;
                 case MSG_SET_VIDEO_STATE:
-                    mDelegate.setVideoState((String) msg.obj, msg.arg1);
+                    mDelegate.setVideoState((String) msg.obj, msg.arg1, null /*Session.Info*/);
                     break;
                 case MSG_SET_VIDEO_CALL_PROVIDER: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         mDelegate.setVideoProvider((String) args.arg1,
-                                (IVideoProvider) args.arg2);
+                                (IVideoProvider) args.arg2, null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_SET_IS_VOIP_AUDIO_MODE:
-                    mDelegate.setIsVoipAudioMode((String) msg.obj, msg.arg1 == 1);
+                    mDelegate.setIsVoipAudioMode((String) msg.obj, msg.arg1 == 1,
+                            null /*Session.Info*/);
                     break;
                 case MSG_SET_STATUS_HINTS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setStatusHints((String) args.arg1, (StatusHints) args.arg2);
+                        mDelegate.setStatusHints((String) args.arg1, (StatusHints) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -197,7 +211,8 @@
                 case MSG_SET_ADDRESS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setAddress((String) args.arg1, (Uri) args.arg2, args.argi1);
+                        mDelegate.setAddress((String) args.arg1, (Uri) args.arg2, args.argi1,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -207,7 +222,8 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         mDelegate.setCallerDisplayName(
-                                (String) args.arg1, (String) args.arg2, args.argi1);
+                                (String) args.arg1, (String) args.arg2, args.argi1,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -216,8 +232,8 @@
                 case MSG_SET_CONFERENCEABLE_CONNECTIONS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setConferenceableConnections(
-                                (String) args.arg1, (List<String>) args.arg2);
+                        mDelegate.setConferenceableConnections((String) args.arg1,
+                                (List<String>) args.arg2, null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -226,8 +242,8 @@
                 case MSG_ADD_EXISTING_CONNECTION: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.addExistingConnection(
-                                (String) args.arg1, (ParcelableConnection) args.arg2);
+                        mDelegate.addExistingConnection((String) args.arg1,
+                                (ParcelableConnection) args.arg2, null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -236,7 +252,8 @@
                 case MSG_SET_CONFERENCE_MERGE_FAILED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setConferenceMergeFailed((String) args.arg1);
+                        mDelegate.setConferenceMergeFailed((String) args.arg1,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -245,7 +262,8 @@
                 case MSG_PUT_EXTRAS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.putExtras((String) args.arg1, (Bundle) args.arg2);
+                        mDelegate.putExtras((String) args.arg1, (Bundle) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -254,7 +272,8 @@
                 case MSG_REMOVE_EXTRAS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.removeExtras((String) args.arg1, (List<String>) args.arg2);
+                        mDelegate.removeExtras((String) args.arg1, (List<String>) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -264,7 +283,7 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2,
-                                (Bundle) args.arg3);
+                                (Bundle) args.arg3, null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -279,7 +298,8 @@
         public void handleCreateConnectionComplete(
                 String id,
                 ConnectionRequest request,
-                ParcelableConnection connection) {
+                ParcelableConnection connection,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = id;
             args.arg2 = request;
@@ -288,28 +308,28 @@
         }
 
         @Override
-        public void setActive(String connectionId) {
+        public void setActive(String connectionId, Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_ACTIVE, connectionId).sendToTarget();
         }
 
         @Override
-        public void setRinging(String connectionId) {
+        public void setRinging(String connectionId, Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_RINGING, connectionId).sendToTarget();
         }
 
         @Override
-        public void setDialing(String connectionId) {
+        public void setDialing(String connectionId, Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_DIALING, connectionId).sendToTarget();
         }
 
         @Override
-        public void setPulling(String connectionId) {
+        public void setPulling(String connectionId, Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_PULLING, connectionId).sendToTarget();
         }
 
         @Override
-        public void setDisconnected(
-                String connectionId, DisconnectCause disconnectCause) {
+        public void setDisconnected(String connectionId, DisconnectCause disconnectCause,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = disconnectCause;
@@ -317,39 +337,43 @@
         }
 
         @Override
-        public void setOnHold(String connectionId) {
+        public void setOnHold(String connectionId, Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_ON_HOLD, connectionId).sendToTarget();
         }
 
         @Override
-        public void setRingbackRequested(String connectionId, boolean ringback) {
+        public void setRingbackRequested(String connectionId, boolean ringback,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_RINGBACK_REQUESTED, ringback ? 1 : 0, 0, connectionId)
                     .sendToTarget();
         }
 
         @Override
-        public void setConnectionCapabilities(String connectionId, int connectionCapabilities) {
+        public void setConnectionCapabilities(String connectionId, int connectionCapabilities,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(
                     MSG_SET_CONNECTION_CAPABILITIES, connectionCapabilities, 0, connectionId)
                     .sendToTarget();
         }
 
         @Override
-        public void setConnectionProperties(String connectionId, int connectionProperties) {
+        public void setConnectionProperties(String connectionId, int connectionProperties,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(
                     MSG_SET_CONNECTION_PROPERTIES, connectionProperties, 0, connectionId)
                     .sendToTarget();
         }
 
         @Override
-        public void setConferenceMergeFailed(String callId) {
+        public void setConferenceMergeFailed(String callId, Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
             mHandler.obtainMessage(MSG_SET_CONFERENCE_MERGE_FAILED, args).sendToTarget();
         }
 
         @Override
-        public void setIsConferenced(String callId, String conferenceCallId) {
+        public void setIsConferenced(String callId, String conferenceCallId,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
             args.arg2 = conferenceCallId;
@@ -357,7 +381,8 @@
         }
 
         @Override
-        public void addConferenceCall(String callId, ParcelableConference parcelableConference) {
+        public void addConferenceCall(String callId, ParcelableConference parcelableConference,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
             args.arg2 = parcelableConference;
@@ -365,12 +390,14 @@
         }
 
         @Override
-        public void removeCall(String connectionId) {
+        public void removeCall(String connectionId,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_REMOVE_CALL, connectionId).sendToTarget();
         }
 
         @Override
-        public void onPostDialWait(String connectionId, String remainingDigits) {
+        public void onPostDialWait(String connectionId, String remainingDigits,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = remainingDigits;
@@ -378,7 +405,8 @@
         }
 
         @Override
-        public void onPostDialChar(String connectionId, char nextChar) {
+        public void onPostDialChar(String connectionId, char nextChar,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.argi1 = nextChar;
@@ -386,17 +414,20 @@
         }
 
         @Override
-        public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
+        public void queryRemoteConnectionServices(RemoteServiceCallback callback,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_QUERY_REMOTE_CALL_SERVICES, callback).sendToTarget();
         }
 
         @Override
-        public void setVideoState(String connectionId, int videoState) {
+        public void setVideoState(String connectionId, int videoState,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_VIDEO_STATE, videoState, 0, connectionId).sendToTarget();
         }
 
         @Override
-        public void setVideoProvider(String connectionId, IVideoProvider videoProvider) {
+        public void setVideoProvider(String connectionId, IVideoProvider videoProvider,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = videoProvider;
@@ -404,13 +435,15 @@
         }
 
         @Override
-        public final void setIsVoipAudioMode(String connectionId, boolean isVoip) {
+        public final void setIsVoipAudioMode(String connectionId, boolean isVoip,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_IS_VOIP_AUDIO_MODE, isVoip ? 1 : 0, 0,
                     connectionId).sendToTarget();
         }
 
         @Override
-        public final void setStatusHints(String connectionId, StatusHints statusHints) {
+        public final void setStatusHints(String connectionId, StatusHints statusHints,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = statusHints;
@@ -418,7 +451,8 @@
         }
 
         @Override
-        public final void setAddress(String connectionId, Uri address, int presentation) {
+        public final void setAddress(String connectionId, Uri address, int presentation,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = address;
@@ -428,7 +462,8 @@
 
         @Override
         public final void setCallerDisplayName(
-                String connectionId, String callerDisplayName, int presentation) {
+                String connectionId, String callerDisplayName, int presentation,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = callerDisplayName;
@@ -437,8 +472,8 @@
         }
 
         @Override
-        public final void setConferenceableConnections(
-                String connectionId, List<String> conferenceableConnectionIds) {
+        public final void setConferenceableConnections(String connectionId,
+                List<String> conferenceableConnectionIds, Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = conferenceableConnectionIds;
@@ -446,8 +481,8 @@
         }
 
         @Override
-        public final void addExistingConnection(
-                String connectionId, ParcelableConnection connection) {
+        public final void addExistingConnection(String connectionId,
+                ParcelableConnection connection, Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = connection;
@@ -455,7 +490,7 @@
         }
 
         @Override
-        public final void putExtras(String connectionId, Bundle extras) {
+        public final void putExtras(String connectionId, Bundle extras, Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = extras;
@@ -463,7 +498,8 @@
         }
 
         @Override
-        public final void removeExtras(String connectionId, List<String> keys) {
+        public final void removeExtras(String connectionId, List<String> keys,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = keys;
@@ -471,7 +507,8 @@
         }
 
         @Override
-        public final void onConnectionEvent(String connectionId, String event, Bundle extras) {
+        public final void onConnectionEvent(String connectionId, String event, Bundle extras,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = event;
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 3927d81..0a8470a 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -21,6 +21,7 @@
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
 import android.os.RemoteException;
+import android.telecom.Logging.Session;
 
 import com.android.internal.telecom.IConnectionService;
 import com.android.internal.telecom.IConnectionServiceAdapter;
@@ -54,7 +55,8 @@
         public void handleCreateConnectionComplete(
                 String id,
                 ConnectionRequest request,
-                ParcelableConnection parcel) {
+                ParcelableConnection parcel,
+                Session.Info info) {
             RemoteConnection connection =
                     findConnectionForAction(id, "handleCreateConnectionSuccessful");
             if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
@@ -95,7 +97,7 @@
         }
 
         @Override
-        public void setActive(String callId) {
+        public void setActive(String callId, Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "setActive")
                         .setState(Connection.STATE_ACTIVE);
@@ -106,25 +108,26 @@
         }
 
         @Override
-        public void setRinging(String callId) {
+        public void setRinging(String callId, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setRinging")
                     .setState(Connection.STATE_RINGING);
         }
 
         @Override
-        public void setDialing(String callId) {
+        public void setDialing(String callId, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setDialing")
                     .setState(Connection.STATE_DIALING);
         }
 
         @Override
-        public void setPulling(String callId) {
+        public void setPulling(String callId, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setPulling")
                     .setState(Connection.STATE_PULLING_CALL);
         }
 
         @Override
-        public void setDisconnected(String callId, DisconnectCause disconnectCause) {
+        public void setDisconnected(String callId, DisconnectCause disconnectCause,
+                Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "setDisconnected")
                         .setDisconnected(disconnectCause);
@@ -135,7 +138,7 @@
         }
 
         @Override
-        public void setOnHold(String callId) {
+        public void setOnHold(String callId, Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "setOnHold")
                         .setState(Connection.STATE_HOLDING);
@@ -146,13 +149,14 @@
         }
 
         @Override
-        public void setRingbackRequested(String callId, boolean ringing) {
+        public void setRingbackRequested(String callId, boolean ringing, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setRingbackRequested")
                     .setRingbackRequested(ringing);
         }
 
         @Override
-        public void setConnectionCapabilities(String callId, int connectionCapabilities) {
+        public void setConnectionCapabilities(String callId, int connectionCapabilities,
+                Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "setConnectionCapabilities")
                         .setConnectionCapabilities(connectionCapabilities);
@@ -163,7 +167,8 @@
         }
 
         @Override
-        public void setConnectionProperties(String callId, int connectionProperties) {
+        public void setConnectionProperties(String callId, int connectionProperties,
+                Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "setConnectionProperties")
                         .setConnectionProperties(connectionProperties);
@@ -174,7 +179,8 @@
         }
 
         @Override
-        public void setIsConferenced(String callId, String conferenceCallId) {
+        public void setIsConferenced(String callId, String conferenceCallId,
+                Session.Info sessionInfo) {
             // Note: callId should not be null; conferenceCallId may be null
             RemoteConnection connection =
                     findConnectionForAction(callId, "setIsConferenced");
@@ -195,7 +201,7 @@
         }
 
         @Override
-        public void setConferenceMergeFailed(String callId) {
+        public void setConferenceMergeFailed(String callId, Session.Info sessionInfo) {
             // Nothing to do here.
             // The event has already been handled and there is no state to update
             // in the underlying connection or conference objects
@@ -203,8 +209,7 @@
 
         @Override
         public void addConferenceCall(
-                final String callId,
-                ParcelableConference parcel) {
+                final String callId, ParcelableConference parcel, Session.Info sessionInfo) {
             RemoteConference conference = new RemoteConference(callId,
                     mOutgoingConnectionServiceRpc);
 
@@ -247,7 +252,7 @@
         }
 
         @Override
-        public void removeCall(String callId) {
+        public void removeCall(String callId, Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "removeCall")
                         .setDestroyed();
@@ -258,24 +263,26 @@
         }
 
         @Override
-        public void onPostDialWait(String callId, String remaining) {
+        public void onPostDialWait(String callId, String remaining, Session.Info sessionInfo) {
             findConnectionForAction(callId, "onPostDialWait")
                     .setPostDialWait(remaining);
         }
 
         @Override
-        public void onPostDialChar(String callId, char nextChar) {
+        public void onPostDialChar(String callId, char nextChar, Session.Info sessionInfo) {
             findConnectionForAction(callId, "onPostDialChar")
                     .onPostDialChar(nextChar);
         }
 
         @Override
-        public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
+        public void queryRemoteConnectionServices(RemoteServiceCallback callback,
+                Session.Info sessionInfo) {
             // Not supported from remote connection service.
         }
 
         @Override
-        public void setVideoProvider(String callId, IVideoProvider videoProvider) {
+        public void setVideoProvider(String callId, IVideoProvider videoProvider,
+                Session.Info sessionInfo) {
             RemoteConnection.VideoProvider remoteVideoProvider = null;
             if (videoProvider != null) {
                 remoteVideoProvider = new RemoteConnection.VideoProvider(videoProvider);
@@ -285,32 +292,34 @@
         }
 
         @Override
-        public void setVideoState(String callId, int videoState) {
+        public void setVideoState(String callId, int videoState, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setVideoState")
                     .setVideoState(videoState);
         }
 
         @Override
-        public void setIsVoipAudioMode(String callId, boolean isVoip) {
+        public void setIsVoipAudioMode(String callId, boolean isVoip, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setIsVoipAudioMode")
                     .setIsVoipAudioMode(isVoip);
         }
 
         @Override
-        public void setStatusHints(String callId, StatusHints statusHints) {
+        public void setStatusHints(String callId, StatusHints statusHints,
+                Session.Info sessionInfo) {
             findConnectionForAction(callId, "setStatusHints")
                     .setStatusHints(statusHints);
         }
 
         @Override
-        public void setAddress(String callId, Uri address, int presentation) {
+        public void setAddress(String callId, Uri address, int presentation,
+                Session.Info sessionInfo) {
             findConnectionForAction(callId, "setAddress")
                     .setAddress(address, presentation);
         }
 
         @Override
         public void setCallerDisplayName(String callId, String callerDisplayName,
-                int presentation) {
+                int presentation, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setCallerDisplayName")
                     .setCallerDisplayName(callerDisplayName, presentation);
         }
@@ -321,8 +330,8 @@
         }
 
         @Override
-        public final void setConferenceableConnections(
-                String callId, List<String> conferenceableConnectionIds) {
+        public final void setConferenceableConnections(String callId,
+                List<String> conferenceableConnectionIds, Session.Info sessionInfo) {
             List<RemoteConnection> conferenceable = new ArrayList<>();
             for (String id : conferenceableConnectionIds) {
                 if (mConnectionById.containsKey(id)) {
@@ -340,7 +349,8 @@
         }
 
         @Override
-        public void addExistingConnection(final String callId, ParcelableConnection connection) {
+        public void addExistingConnection(String callId, ParcelableConnection connection,
+                Session.Info sessionInfo) {
             RemoteConnection remoteConnection = new RemoteConnection(callId,
                     mOutgoingConnectionServiceRpc, connection);
             mConnectionById.put(callId, remoteConnection);
@@ -355,7 +365,7 @@
         }
 
         @Override
-        public void putExtras(String callId, Bundle extras) {
+        public void putExtras(String callId, Bundle extras, Session.Info sessionInfo) {
             if (hasConnection(callId)) {
                 findConnectionForAction(callId, "putExtras").putExtras(extras);
             } else {
@@ -364,7 +374,7 @@
         }
 
         @Override
-        public void removeExtras(String callId, List<String> keys) {
+        public void removeExtras(String callId, List<String> keys, Session.Info sessionInfo) {
             if (hasConnection(callId)) {
                 findConnectionForAction(callId, "removeExtra").removeExtras(keys);
             } else {
@@ -373,7 +383,8 @@
         }
 
         @Override
-        public void onConnectionEvent(String callId, String event, Bundle extras) {
+        public void onConnectionEvent(String callId, String event, Bundle extras,
+                Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event,
                         extras);
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 3bf83ae..002c3bb 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.telecom.ConnectionRequest;
 import android.telecom.DisconnectCause;
+import android.telecom.Logging.Session;
 import android.telecom.ParcelableConnection;
 import android.telecom.ParcelableConference;
 import android.telecom.StatusHints;
@@ -39,59 +40,68 @@
     void handleCreateConnectionComplete(
             String callId,
             in ConnectionRequest request,
-            in ParcelableConnection connection);
+            in ParcelableConnection connection,
+            in Session.Info sessionInfo);
 
-    void setActive(String callId);
+    void setActive(String callId, in Session.Info sessionInfo);
 
-    void setRinging(String callId);
+    void setRinging(String callId, in Session.Info sessionInfo);
 
-    void setDialing(String callId);
+    void setDialing(String callId, in Session.Info sessionInfo);
 
-    void setPulling(String callId);
+    void setPulling(String callId, in Session.Info sessionInfo);
 
-    void setDisconnected(String callId, in DisconnectCause disconnectCause);
+    void setDisconnected(String callId, in DisconnectCause disconnectCause,
+    in Session.Info sessionInfo);
 
-    void setOnHold(String callId);
+    void setOnHold(String callId, in Session.Info sessionInfo);
 
-    void setRingbackRequested(String callId, boolean ringing);
+    void setRingbackRequested(String callId, boolean ringing, in Session.Info sessionInfo);
 
-    void setConnectionCapabilities(String callId, int connectionCapabilities);
+    void setConnectionCapabilities(String callId, int connectionCapabilities,
+    in Session.Info sessionInfo);
 
-    void setConnectionProperties(String callId, int connectionProperties);
+    void setConnectionProperties(String callId, int connectionProperties,
+    in Session.Info sessionInfo);
 
-    void setIsConferenced(String callId, String conferenceCallId);
+    void setIsConferenced(String callId, String conferenceCallId, in Session.Info sessionInfo);
 
-    void setConferenceMergeFailed(String callId);
+    void setConferenceMergeFailed(String callId, in Session.Info sessionInfo);
 
-    void addConferenceCall(String callId, in ParcelableConference conference);
+    void addConferenceCall(String callId, in ParcelableConference conference,
+    in Session.Info sessionInfo);
 
-    void removeCall(String callId);
+    void removeCall(String callId, in Session.Info sessionInfo);
 
-    void onPostDialWait(String callId, String remaining);
+    void onPostDialWait(String callId, String remaining, in Session.Info sessionInfo);
 
-    void onPostDialChar(String callId, char nextChar);
+    void onPostDialChar(String callId, char nextChar, in Session.Info sessionInfo);
 
-    void queryRemoteConnectionServices(RemoteServiceCallback callback);
+    void queryRemoteConnectionServices(RemoteServiceCallback callback, in Session.Info sessionInfo);
 
-    void setVideoProvider(String callId, IVideoProvider videoProvider);
+    void setVideoProvider(String callId, IVideoProvider videoProvider, in Session.Info sessionInfo);
 
-    void setVideoState(String callId, int videoState);
+    void setVideoState(String callId, int videoState, in Session.Info sessionInfo);
 
-    void setIsVoipAudioMode(String callId, boolean isVoip);
+    void setIsVoipAudioMode(String callId, boolean isVoip, in Session.Info sessionInfo);
 
-    void setStatusHints(String callId, in StatusHints statusHints);
+    void setStatusHints(String callId, in StatusHints statusHints, in Session.Info sessionInfo);
 
-    void setAddress(String callId, in Uri address, int presentation);
+    void setAddress(String callId, in Uri address, int presentation, in Session.Info sessionInfo);
 
-    void setCallerDisplayName(String callId, String callerDisplayName, int presentation);
+    void setCallerDisplayName(String callId, String callerDisplayName, int presentation,
+    in Session.Info sessionInfo);
 
-    void setConferenceableConnections(String callId, in List<String> conferenceableCallIds);
+    void setConferenceableConnections(String callId, in List<String> conferenceableCallIds,
+    in Session.Info sessionInfo);
 
-    void addExistingConnection(String callId, in ParcelableConnection connection);
+    void addExistingConnection(String callId, in ParcelableConnection connection,
+    in Session.Info sessionInfo);
 
-    void putExtras(String callId, in Bundle extras);
+    void putExtras(String callId, in Bundle extras, in Session.Info sessionInfo);
 
-    void removeExtras(String callId, in List<String> keys);
+    void removeExtras(String callId, in List<String> keys, in Session.Info sessionInfo);
 
-    void onConnectionEvent(String callId, String event, in Bundle extras);
+    void onConnectionEvent(String callId, String event, in Bundle extras,
+    in Session.Info sessionInfo);
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 987b1d1..d75dd7d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1193,7 +1193,7 @@
     private int getPhoneTypeFromProperty(int phoneId) {
         String type = getTelephonyProperty(phoneId,
                 TelephonyProperties.CURRENT_ACTIVE_PHONE, null);
-        if (type == null || type.equals("")) {
+        if (type == null || type.isEmpty()) {
             return getPhoneTypeFromNetworkType(phoneId);
         }
         return Integer.parseInt(type);
@@ -1209,7 +1209,7 @@
         // use the system property for default network type.
         // This is a fail safe, and can only happen at first boot.
         String mode = getTelephonyProperty(phoneId, "ro.telephony.default_network", null);
-        if (mode != null) {
+        if (mode != null && !mode.isEmpty()) {
             return TelephonyManager.getPhoneType(Integer.parseInt(mode));
         }
         return TelephonyManager.PHONE_TYPE_NONE;
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index f737b24..7d6f32b 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -73,7 +73,7 @@
         }
 
         try {
-            mWm.addWindowToken(null, 0);
+            mWm.addWindowToken(null, 0, DEFAULT_DISPLAY);
             fail("IWindowManager.addWindowToken did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
@@ -83,7 +83,7 @@
         }
 
         try {
-            mWm.removeWindowToken(null);
+            mWm.removeWindowToken(null, DEFAULT_DISPLAY);
             fail("IWindowManager.removeWindowToken did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
@@ -126,7 +126,7 @@
 
         try {
             mWm.setAppOrientation(null, 0);
-            mWm.addWindowToken(null, 0);
+            mWm.addWindowToken(null, 0, DEFAULT_DISPLAY);
             fail("IWindowManager.setAppOrientation did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
@@ -206,7 +206,7 @@
         }
 
         try {
-            mWm.removeAppToken(null);
+            mWm.removeAppToken(null, DEFAULT_DISPLAY);
             fail("IWindowManager.removeAppToken did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index c86f5c3..4596210 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -86,7 +86,7 @@
     }
 
     @Override
-    public void addWindowToken(IBinder arg0, int arg1) throws RemoteException {
+    public void addWindowToken(IBinder arg0, int arg1, int arg2) throws RemoteException {
         // TODO Auto-generated method stub
 
     }
@@ -277,13 +277,13 @@
     }
 
     @Override
-    public void removeAppToken(IBinder arg0) throws RemoteException {
+    public void removeAppToken(IBinder arg0, int arg1) throws RemoteException {
         // TODO Auto-generated method stub
 
     }
 
     @Override
-    public void removeWindowToken(IBinder arg0) throws RemoteException {
+    public void removeWindowToken(IBinder arg0, int arg1) throws RemoteException {
         // TODO Auto-generated method stub
 
     }