Merge "Report touchable region changes to Accessibility." into pi-dev
diff --git a/api/test-current.txt b/api/test-current.txt
index 5cffd0e..f1c6120 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -564,6 +564,11 @@
     field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
   }
 
+  public final class NetworkCapabilities implements android.os.Parcelable {
+    method public int[] getCapabilities();
+    method public int[] getTransportTypes();
+  }
+
   public class TrafficStats {
     method public static long getLoopbackRxBytes();
     method public static long getLoopbackRxPackets();
@@ -897,6 +902,14 @@
 
 }
 
+package android.telecom {
+
+  public final class CallAudioState implements android.os.Parcelable {
+    ctor public CallAudioState(boolean, int, int, android.bluetooth.BluetoothDevice, java.util.Collection<android.bluetooth.BluetoothDevice>);
+  }
+
+}
+
 package android.telephony {
 
   public class MbmsDownloadSession implements java.lang.AutoCloseable {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index df8763c..136fd14 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -87,7 +87,8 @@
       mDimensionHardLimit(StatsdStats::kAtomDimensionKeySizeLimitMap.find(pullTagId) !=
                                           StatsdStats::kAtomDimensionKeySizeLimitMap.end()
                                   ? StatsdStats::kAtomDimensionKeySizeLimitMap.at(pullTagId).second
-                                  : StatsdStats::kDimensionKeySizeHardLimit) {
+                                  : StatsdStats::kDimensionKeySizeHardLimit),
+      mUseAbsoluteValueOnReset(metric.use_absolute_value_on_reset()) {
     // TODO: valuemetric for pushed events may need unlimited bucket length
     int64_t bucketSizeMills = 0;
     if (metric.has_bucket()) {
@@ -393,15 +394,20 @@
             }
         } else {
             // Generally we expect value to be monotonically increasing.
-            // If not, there was a reset event. We take the absolute value as
-            // diff in this case.
+            // If not, take absolute value or drop it, based on config.
             if (interval.startUpdated) {
                 if (value >= interval.start) {
                     interval.sum += (value - interval.start);
+                    interval.hasValue = true;
                 } else {
-                    interval.sum += value;
+                    if (mUseAbsoluteValueOnReset) {
+                        interval.sum += value;
+                        interval.hasValue = true;
+                    } else {
+                        VLOG("Dropping data for atom %d, prev: %lld, now: %lld", mPullTagId,
+                             (long long)interval.start, (long long)value);
+                    }
                 }
-                interval.hasValue = true;
                 interval.startUpdated = false;
             } else {
                 VLOG("No start for matching end %lld", (long long)value);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 113be4b..0136ec1 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -164,6 +164,8 @@
 
     const size_t mDimensionHardLimit;
 
+    const bool mUseAbsoluteValueOnReset;
+
     FRIEND_TEST(ValueMetricProducerTest, TestNonDimensionalEvents);
     FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
     FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade);
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 849d5f6..eb77299 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -265,6 +265,8 @@
   optional AggregationType aggregation_type = 8 [default = SUM];
 
   optional int64 min_bucket_size_nanos = 10;
+
+  optional bool use_absolute_value_on_reset = 11 [default = false];
 }
 
 message Alert {
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 9e3a1ca..7ecfbe6 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -3208,8 +3208,6 @@
 Landroid/net/NetworkCapabilities;-><init>()V
 Landroid/net/NetworkCapabilities;->addCapability(I)Landroid/net/NetworkCapabilities;
 Landroid/net/NetworkCapabilities;->addTransportType(I)Landroid/net/NetworkCapabilities;
-Landroid/net/NetworkCapabilities;->getCapabilities()[I
-Landroid/net/NetworkCapabilities;->getTransportTypes()[I
 Landroid/net/NetworkCapabilities;->mNetworkCapabilities:J
 Landroid/net/NetworkCapabilities;->mSignalStrength:I
 Landroid/net/NetworkCapabilities;->removeCapability(I)Landroid/net/NetworkCapabilities;
@@ -6664,6 +6662,7 @@
 Landroid/widget/RemoteViews;->mergeRemoteViews(Landroid/widget/RemoteViews;)V
 Landroid/widget/RemoteViews;->mLayoutId:I
 Landroid/widget/RemoteViews;->mPortrait:Landroid/widget/RemoteViews;
+Landroid/widget/RemoteViews;->setIsWidgetCollectionChild(Z)V
 Landroid/widget/RemoteViews;->setRemoteAdapter(ILjava/util/ArrayList;I)V
 Landroid/widget/RemoteViewsAdapter;->getRemoteViewsServiceIntent()Landroid/content/Intent;
 Landroid/widget/RemoteViewsAdapter;->isDataReady()Z
@@ -8059,6 +8058,7 @@
 Lcom/android/org/conscrypt/TrustedCertificateStore;->getCertificateChain(Ljava/security/cert/X509Certificate;)Ljava/util/List;
 Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
 Lcom/android/org/conscrypt/TrustManagerImpl;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
+Ldalvik/system/BaseDexClassLoader;-><init>(Ljava/lang/String;Ljava/io/File;Ljava/lang/String;Ljava/lang/ClassLoader;Z)V
 Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;)V
 Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;Z)V
 Ldalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 3b62bd7..7b383d4 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -979,7 +979,9 @@
     @Override
     protected void attachBaseContext(Context newBase) {
         super.attachBaseContext(newBase);
-        newBase.setAutofillClient(this);
+        if (newBase != null) {
+            newBase.setAutofillClient(this);
+        }
     }
 
     /** @hide */
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
new file mode 100644
index 0000000..24c5d23
--- /dev/null
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 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 android.app;
+
+import android.util.SparseIntArray;
+
+/**
+ * App ops service local interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class AppOpsManagerInternal {
+    /**
+     * Set the currently configured device and profile owners.  Specifies the package uid (value)
+     * that has been configured for each user (key) that has one.  These will be allowed privileged
+     * access to app ops for their user.
+     */
+    public abstract void setDeviceAndProfileOwners(SparseIntArray owners);
+}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index ca3257f..9db642b 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -700,7 +700,7 @@
                         librarySearchPath, libraryPermittedPath, mBaseClassLoader,
                         null /* classLoaderName */);
                 StrictMode.setThreadPolicy(oldPolicy);
-                mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
+                mAppComponentFactory = AppComponentFactory.DEFAULT;
             }
 
             return;
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 1b05402..1b07784 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -513,7 +513,7 @@
         try {
             mService.setAppStandbyBucket(packageName, bucket, mContext.getUserId());
         } catch (RemoteException e) {
-            // Nothing to do
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -539,8 +539,8 @@
             }
             return bucketMap;
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return Collections.EMPTY_MAP;
     }
 
     /**
@@ -563,6 +563,7 @@
         try {
             mService.setAppStandbyBuckets(slice, mContext.getUserId());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -596,6 +597,7 @@
             mService.registerAppUsageObserver(observerId, packages, timeUnit.toMillis(timeLimit),
                     callbackIntent, mContext.getOpPackageName());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -614,6 +616,7 @@
         try {
             mService.unregisterAppUsageObserver(observerId, mContext.getOpPackageName());
         } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -698,6 +701,7 @@
         try {
             mService.whitelistAppTemporarily(packageName, duration, user.getIdentifier());
         } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
     }
 
@@ -709,6 +713,7 @@
         try {
             mService.onCarrierPrivilegedAppsChanged();
         } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 65dfb13..a808c64 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.net.ConnectivityManager.NetworkCallback;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -427,6 +428,7 @@
      * @return an array of capability values for this instance.
      * @hide
      */
+    @TestApi
     public @NetCapability int[] getCapabilities() {
         return BitUtils.unpackBits(mNetworkCapabilities);
     }
@@ -690,6 +692,7 @@
      * @return an array of transport type values for this instance.
      * @hide
      */
+    @TestApi
     public @Transport int[] getTransportTypes() {
         return BitUtils.unpackBits(mTransportTypes);
     }
diff --git a/core/java/android/print/IPrintManager.aidl b/core/java/android/print/IPrintManager.aidl
index d7c267b..d3d3874 100644
--- a/core/java/android/print/IPrintManager.aidl
+++ b/core/java/android/print/IPrintManager.aidl
@@ -143,4 +143,21 @@
     void stopPrinterStateTracking(in PrinterId printerId, int userId);
     void destroyPrinterDiscoverySession(in IPrinterDiscoveryObserver observer,
             int userId);
+
+    /**
+     * Check if the system will bind to print services in intant app.
+     *
+     * @param userId the Id of the user the behavior should be checked for
+     *
+     * @return {@code true} iff the system will bind to print services in instant apps.
+     */
+    boolean getBindInstantServiceAllowed(int userId);
+
+    /**
+     * Set if the system will bind to print services in intant app.
+     *
+     * @param userId the Id of the user the behavior should be changed for
+     * @param allows iff {@code true} the system will bind to print services in instant apps
+     */
+    void setBindInstantServiceAllowed(int userId, boolean allowed);
 }
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index d51a13f..f1e937e 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -644,9 +644,11 @@
         if (osize <= 1) {
             // Now empty.
             if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0");
-            freeArrays(mHashes, mArray, osize);
+            final int[] ohashes = mHashes;
+            final Object[] oarray = mArray;
             mHashes = EmptyArray.INT;
             mArray = EmptyArray.OBJECT;
+            freeArrays(ohashes, oarray, osize);
             nsize = 0;
         } else {
             nsize = osize - 1;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3807079..049d34f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -15049,8 +15049,7 @@
     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
         ensureTransformationInfo();
         if (mTransformationInfo.mAlpha != alpha) {
-            float oldAlpha = mTransformationInfo.mAlpha;
-            mTransformationInfo.mAlpha = alpha;
+            setAlphaInternal(alpha);
             if (onSetAlpha((int) (alpha * 255))) {
                 mPrivateFlags |= PFLAG_ALPHA_SET;
                 // subclass is handling alpha - don't optimize rendering cache invalidation
@@ -15061,10 +15060,6 @@
                 invalidateViewProperty(true, false);
                 mRenderNode.setAlpha(getFinalAlpha());
             }
-            // Report visibility changes, which can affect children, to accessibility
-            if ((alpha == 0) ^ (oldAlpha == 0)) {
-                notifySubtreeAccessibilityStateChangedIfNeeded();
-            }
         }
     }
 
@@ -15081,7 +15076,7 @@
     boolean setAlphaNoInvalidation(float alpha) {
         ensureTransformationInfo();
         if (mTransformationInfo.mAlpha != alpha) {
-            mTransformationInfo.mAlpha = alpha;
+            setAlphaInternal(alpha);
             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
             if (subclassHandlesAlpha) {
                 mPrivateFlags |= PFLAG_ALPHA_SET;
@@ -15094,6 +15089,15 @@
         return false;
     }
 
+    private void setAlphaInternal(float alpha) {
+        float oldAlpha = mTransformationInfo.mAlpha;
+        mTransformationInfo.mAlpha = alpha;
+        // Report visibility changes, which can affect children, to accessibility
+        if ((alpha == 0) ^ (oldAlpha == 0)) {
+            notifySubtreeAccessibilityStateChangedIfNeeded();
+        }
+    }
+
     /**
      * This property is hidden and intended only for use by the Fade transition, which
      * animates it to produce a visual translucency that does not side-effect (or get
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 2ec42c0..65a6125 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -8574,6 +8574,8 @@
 
         private final Rect mLocation = new Rect();
 
+        private ViewGroup mRoot;
+
         public View mView;
 
         private int mLayoutDirection;
@@ -8603,47 +8605,100 @@
                 return 1;
             }
 
+            int boundsResult = compareBoundsOfTree(this, another);
+            if (boundsResult != 0) {
+                return boundsResult;
+            }
+
+            // Just break the tie somehow. The accessibility ids are unique
+            // and stable, hence this is deterministic tie breaking.
+            return mView.getAccessibilityViewId() - another.mView.getAccessibilityViewId();
+        }
+
+        /**
+         * Compare two views based on their bounds. Use the bounds of their children to break ties.
+         *
+         * @param holder1 Holder of first view to compare
+         * @param holder2 Holder of second view to compare. Must have the same root at holder1.
+         * @return The compare result, with equality if no good comparison was found.
+         */
+        private static int compareBoundsOfTree(
+                ViewLocationHolder holder1, ViewLocationHolder holder2) {
             if (sComparisonStrategy == COMPARISON_STRATEGY_STRIPE) {
                 // First is above second.
-                if (mLocation.bottom - another.mLocation.top <= 0) {
+                if (holder1.mLocation.bottom - holder2.mLocation.top <= 0) {
                     return -1;
                 }
                 // First is below second.
-                if (mLocation.top - another.mLocation.bottom >= 0) {
+                if (holder1.mLocation.top - holder2.mLocation.bottom >= 0) {
                     return 1;
                 }
             }
 
             // We are ordering left-to-right, top-to-bottom.
-            if (mLayoutDirection == LAYOUT_DIRECTION_LTR) {
-                final int leftDifference = mLocation.left - another.mLocation.left;
+            if (holder1.mLayoutDirection == LAYOUT_DIRECTION_LTR) {
+                final int leftDifference = holder1.mLocation.left - holder2.mLocation.left;
                 if (leftDifference != 0) {
                     return leftDifference;
                 }
             } else { // RTL
-                final int rightDifference = mLocation.right - another.mLocation.right;
+                final int rightDifference = holder1.mLocation.right - holder2.mLocation.right;
                 if (rightDifference != 0) {
                     return -rightDifference;
                 }
             }
             // We are ordering left-to-right, top-to-bottom.
-            final int topDifference = mLocation.top - another.mLocation.top;
+            final int topDifference = holder1.mLocation.top - holder2.mLocation.top;
             if (topDifference != 0) {
                 return topDifference;
             }
             // Break tie by height.
-            final int heightDiference = mLocation.height() - another.mLocation.height();
+            final int heightDiference = holder1.mLocation.height() - holder2.mLocation.height();
             if (heightDiference != 0) {
                 return -heightDiference;
             }
             // Break tie by width.
-            final int widthDiference = mLocation.width() - another.mLocation.width();
-            if (widthDiference != 0) {
-                return -widthDiference;
+            final int widthDifference = holder1.mLocation.width() - holder2.mLocation.width();
+            if (widthDifference != 0) {
+                return -widthDifference;
             }
-            // Just break the tie somehow. The accessibliity ids are unique
-            // and stable, hence this is deterministic tie breaking.
-            return mView.getAccessibilityViewId() - another.mView.getAccessibilityViewId();
+
+            // Find a child of each view with different screen bounds.
+            final Rect view1Bounds = new Rect();
+            final Rect view2Bounds = new Rect();
+            final Rect tempRect = new Rect();
+            holder1.mView.getBoundsOnScreen(view1Bounds, true);
+            holder2.mView.getBoundsOnScreen(view2Bounds, true);
+            final View child1 = holder1.mView.findViewByPredicateTraversal((view) -> {
+                view.getBoundsOnScreen(tempRect, true);
+                return !tempRect.equals(view1Bounds);
+            }, null);
+            final View child2 = holder2.mView.findViewByPredicateTraversal((view) -> {
+                view.getBoundsOnScreen(tempRect, true);
+                return !tempRect.equals(view2Bounds);
+            }, null);
+
+
+            // Compare the children recursively
+            if ((child1 != null) && (child2 != null)) {
+                final ViewLocationHolder childHolder1 =
+                        ViewLocationHolder.obtain(holder1.mRoot, child1);
+                final ViewLocationHolder childHolder2 =
+                        ViewLocationHolder.obtain(holder1.mRoot, child2);
+                return compareBoundsOfTree(childHolder1, childHolder2);
+            }
+
+            // If only one has a child, use that one
+            if (child1 != null) {
+                return 1;
+            }
+
+            if (child2 != null) {
+                return -1;
+            }
+
+            // Give up
+            return 0;
         }
 
         private void init(ViewGroup root, View view) {
@@ -8651,6 +8706,7 @@
             view.getDrawingRect(viewLocation);
             root.offsetDescendantRectToMyCoords(view, viewLocation);
             mView = view;
+            mRoot = root;
             mLayoutDirection = root.getLayoutDirection();
         }
 
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 4104728..7e6af49 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -53,6 +53,7 @@
 import android.view.View;
 import android.view.ViewRootImpl;
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import android.view.autofill.AutofillManager;
 
 import com.android.internal.inputmethod.IInputContentUriToken;
 import com.android.internal.os.SomeArgs;
@@ -406,6 +407,17 @@
     static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 9;
     static final int MSG_REPORT_FULLSCREEN_MODE = 10;
 
+    private static boolean isAutofillUIShowing(View servedView) {
+        AutofillManager afm = servedView.getContext().getSystemService(AutofillManager.class);
+        return afm != null && afm.isAutofillUiShowing();
+    }
+
+    private static boolean canStartInput(View servedView) {
+        // We can start input ether the servedView has window focus
+        // or the activity is showing autofill ui.
+        return servedView.hasWindowFocus() || isAutofillUIShowing(servedView);
+    }
+
     class H extends Handler {
         H(Looper looper) {
             super(looper, null, true);
@@ -506,7 +518,7 @@
                         }
                         // Check focus again in case that "onWindowFocus" is called before
                         // handling this message.
-                        if (mServedView != null && mServedView.hasWindowFocus()) {
+                        if (mServedView != null && canStartInput(mServedView)) {
                             if (checkFocusNoStartInput(mRestartOnNextWindowFocus)) {
                                 final int reason = active ?
                                         InputMethodClient.START_INPUT_REASON_ACTIVATED_BY_IMMS :
@@ -1435,7 +1447,7 @@
                 // at times when we don't really want it to.  For now it
                 // seems better to just turn it all off.
                 // TODO: Check view.isTemporarilyDetached() when re-enable the following code.
-                if (false && view.hasWindowFocus()) {
+                if (false && canStartInput(view)) {
                     mNextServedView = null;
                     scheduleCheckFocusLocked(view);
                 }
@@ -2572,6 +2584,7 @@
         sb.append(view);
         sb.append(",focus=" + view.hasFocus());
         sb.append(",windowFocus=" + view.hasWindowFocus());
+        sb.append(",autofillUiShowing=" + isAutofillUIShowing(view));
         sb.append(",window=" + view.getWindowToken());
         sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
         return sb.toString();
diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java
index 25af355..f42a195 100644
--- a/core/java/com/android/internal/app/SuspendedAppActivity.java
+++ b/core/java/com/android/internal/app/SuspendedAppActivity.java
@@ -16,10 +16,12 @@
 
 package com.android.internal.app;
 
+import android.Manifest;
 import android.app.AlertDialog;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.Slog;
@@ -30,35 +32,47 @@
 public class SuspendedAppActivity extends AlertActivity
         implements DialogInterface.OnClickListener {
     private static final String TAG = "SuspendedAppActivity";
-
     public static final String EXTRA_SUSPENDED_PACKAGE =
             "SuspendedAppActivity.extra.SUSPENDED_PACKAGE";
     public static final String EXTRA_SUSPENDING_PACKAGE =
             "SuspendedAppActivity.extra.SUSPENDING_PACKAGE";
     public static final String EXTRA_DIALOG_MESSAGE = "SuspendedAppActivity.extra.DIALOG_MESSAGE";
-    public static final String EXTRA_MORE_DETAILS_INTENT =
-            "SuspendedAppActivity.extra.MORE_DETAILS_INTENT";
 
     private Intent mMoreDetailsIntent;
     private int mUserId;
+    private PackageManager mPm;
 
     private CharSequence getAppLabel(String packageName) {
-        final PackageManager pm = getPackageManager();
         try {
-            return pm.getApplicationInfoAsUser(packageName, 0, mUserId).loadLabel(pm);
+            return mPm.getApplicationInfoAsUser(packageName, 0, mUserId).loadLabel(mPm);
         } catch (PackageManager.NameNotFoundException ne) {
             Slog.e(TAG, "Package " + packageName + " not found", ne);
         }
         return packageName;
     }
 
+    private Intent getMoreDetailsActivity(String suspendingPackage, String suspendedPackage,
+            int userId) {
+        final Intent moreDetailsIntent = new Intent(Intent.ACTION_SHOW_SUSPENDED_APP_DETAILS)
+                .setPackage(suspendingPackage);
+        final String requiredPermission = Manifest.permission.SEND_SHOW_SUSPENDED_APP_DETAILS;
+        final ResolveInfo resolvedInfo = mPm.resolveActivityAsUser(moreDetailsIntent, 0, userId);
+        if (resolvedInfo != null && resolvedInfo.activityInfo != null
+                && requiredPermission.equals(resolvedInfo.activityInfo.permission)) {
+            moreDetailsIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, suspendedPackage)
+                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            return moreDetailsIntent;
+        }
+        return null;
+    }
+
     @Override
     public void onCreate(Bundle icicle) {
-        getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
         super.onCreate(icicle);
+        mPm = getPackageManager();
+        getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
 
         final Intent intent = getIntent();
-        mMoreDetailsIntent = intent.getParcelableExtra(EXTRA_MORE_DETAILS_INTENT);
         mUserId = intent.getIntExtra(Intent.EXTRA_USER_ID, -1);
         if (mUserId < 0) {
             Slog.wtf(TAG, "Invalid user: " + mUserId);
@@ -66,13 +80,13 @@
             return;
         }
         final String suppliedMessage = intent.getStringExtra(EXTRA_DIALOG_MESSAGE);
-        final CharSequence suspendedAppLabel = getAppLabel(
-                intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE));
+        final String suspendedPackage = intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE);
+        final String suspendingPackage = intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE);
+        final CharSequence suspendedAppLabel = getAppLabel(suspendedPackage);
         final CharSequence dialogMessage;
         if (suppliedMessage == null) {
-            dialogMessage = getString(R.string.app_suspended_default_message,
-                    suspendedAppLabel,
-                    getAppLabel(intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE)));
+            dialogMessage = getString(R.string.app_suspended_default_message, suspendedAppLabel,
+                    getAppLabel(suspendingPackage));
         } else {
             dialogMessage = String.format(getResources().getConfiguration().getLocales().get(0),
                     suppliedMessage, suspendedAppLabel);
@@ -82,6 +96,7 @@
         ap.mTitle = getString(R.string.app_suspended_title);
         ap.mMessage = dialogMessage;
         ap.mPositiveButtonText = getString(android.R.string.ok);
+        mMoreDetailsIntent = getMoreDetailsActivity(suspendingPackage, suspendedPackage, mUserId);
         if (mMoreDetailsIntent != null) {
             ap.mNeutralButtonText = getString(R.string.app_suspended_more_details);
         }
@@ -99,4 +114,16 @@
         }
         finish();
     }
+
+    public static Intent createSuspendedAppInterceptIntent(String suspendedPackage,
+            String suspendingPackage, String dialogMessage, int userId) {
+        return new Intent()
+                .setClassName("android", SuspendedAppActivity.class.getName())
+                .putExtra(EXTRA_SUSPENDED_PACKAGE, suspendedPackage)
+                .putExtra(EXTRA_DIALOG_MESSAGE, dialogMessage)
+                .putExtra(EXTRA_SUSPENDING_PACKAGE, suspendingPackage)
+                .putExtra(Intent.EXTRA_USER_ID, userId)
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+    }
 }
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index b2903c4..5563cce 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -218,8 +218,7 @@
     }
 
     /**
-     * Reports whether {@link #getCarrierFrequencyHz(int satIndex)} is available (i.e. carrier
-     * frequency is available for the satellite at the specified index).
+     * Reports whether a valid {@link #getCarrierFrequencyHz(int satIndex)} is available.
      *
      * @param satIndex the index of the satellite in the list.
      */
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 83d7e16..06fbf9f 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -811,6 +811,8 @@
         List<ResolveInfo> resolvedActivities = getPackageManager()
                 .queryIntentActivities(intent, 0);
         if (resolvedActivities.isEmpty()) {
+            Log.w(LOG_TAG, "Advanced options activity " + mAdvancedPrintOptionsActivity + " could "
+                    + "not be found");
             return;
         }
 
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
index 299e337..680f14b 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
@@ -38,7 +38,7 @@
 public interface NotificationMenuRowPlugin extends Plugin {
 
     public static final String ACTION = "com.android.systemui.action.PLUGIN_NOTIFICATION_MENU_ROW";
-    public static final int VERSION = 3;
+    public static final int VERSION = 4;
 
     @ProvidesInterface(version = OnMenuEventListener.VERSION)
     public interface OnMenuEventListener {
@@ -75,6 +75,11 @@
      */
     public MenuItem getAppOpsMenuItem(Context context);
 
+    /**
+     * @return the {@link MenuItem} to display when snooze item is pressed.
+     */
+    public MenuItem getSnoozeMenuItem(Context context);
+
     public void setMenuItems(ArrayList<MenuItem> items);
 
     public void setMenuClickListener(OnMenuEventListener listener);
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 458e133d7..99138b0 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -99,6 +99,7 @@
     <item type="id" name="action_snooze_long"/>
     <item type="id" name="action_snooze_longer"/>
     <item type="id" name="action_snooze_assistant_suggestion_1"/>
+    <item type="id" name="action_snooze"/>
 
     <!-- For StatusBarIconContainer to tag its icon views -->
     <item type="id" name="status_bar_view_state_tag" />
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 939a868..2ff98ba 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -85,4 +85,9 @@
      * cancel (long) press.
      */
     void onQuickStep(in MotionEvent event);
+
+    /**
+     * Sent when there was an action on one of the onboarding tips view.
+     */
+    void onTip(int actionType, int viewType);
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/LauncherEventUtil.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/LauncherEventUtil.java
new file mode 100644
index 0000000..eed9580
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/LauncherEventUtil.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 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.systemui.shared.system;
+
+public class LauncherEventUtil {
+
+    // Constants for the Action
+    public static final int VISIBLE = 0;
+    public static final int DISMISS = 1;
+
+    // Constants for the Target (View)
+    public static final int RECENTS_SWIPE_UP_ONBOARDING_TIP = 0;
+    public static final int RECENTS_QUICK_SCRUB_ONBOARDING_TIP = 1;
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index d16e1b1..69b0f31 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -24,11 +24,18 @@
 import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING;
 import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_COUNT;
 import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_FROM_HOME_COUNT;
+import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
+import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS;
+import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
 
 import android.annotation.StringRes;
 import android.annotation.TargetApi;
 import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.CornerPathEffect;
@@ -38,6 +45,7 @@
 import android.os.Build;
 import android.os.SystemProperties;
 import android.os.UserManager;
+import android.os.RemoteException;
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -53,7 +61,9 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
+import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.LauncherEventUtil;
 
 import java.util.Collections;
 import java.util.HashSet;
@@ -120,6 +130,7 @@
                     return;
                 }
 
+                boolean shouldLog = false;
                 if (!alreadySeenSwipeUpOnboarding) {
                     if (getOpenedOverviewFromHomeCount()
                             >= SWIPE_UP_SHOW_ON_OVERVIEW_OPENED_FROM_HOME_COUNT) {
@@ -128,10 +139,13 @@
                             if (mNumAppsLaunchedSinceSwipeUpTipDismiss
                                     == SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS) {
                                 mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
-                                show(R.string.recents_swipe_up_onboarding);
+                                shouldLog = show(R.string.recents_swipe_up_onboarding);
                             }
                         } else {
-                            show(R.string.recents_swipe_up_onboarding);
+                            shouldLog = show(R.string.recents_swipe_up_onboarding);
+                        }
+                        if (shouldLog) {
+                            notifyOnTip(VISIBLE, RECENTS_SWIPE_UP_ONBOARDING_TIP);
                         }
                     }
                 } else {
@@ -140,12 +154,16 @@
                             if (mOverviewOpenedCountSinceQuickScrubTipDismiss
                                     == QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
                                 mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
-                                show(R.string.recents_quick_scrub_onboarding);
+                                shouldLog = show(R.string.recents_quick_scrub_onboarding);
                             }
                         } else {
-                            show(R.string.recents_quick_scrub_onboarding);
+                            shouldLog = show(R.string.recents_quick_scrub_onboarding);
+                        }
+                        if (shouldLog) {
+                            notifyOnTip(VISIBLE, RECENTS_QUICK_SCRUB_ONBOARDING_TIP);
                         }
                     }
+
                 }
             } else {
                 hide(false);
@@ -191,6 +209,7 @@
         @Override
         public void onViewAttachedToWindow(View view) {
             if (view == mLayout) {
+                mContext.registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
                 mLayoutAttachedToWindow = true;
                 if (view.getTag().equals(R.string.recents_swipe_up_onboarding)) {
                     mHasDismissedSwipeUpTip = false;
@@ -215,6 +234,7 @@
                     }
                     mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
                 }
+                mContext.unregisterReceiver(mReceiver);
             }
         }
     };
@@ -244,6 +264,9 @@
             if (v.getTag().equals(R.string.recents_swipe_up_onboarding)) {
                 mHasDismissedSwipeUpTip = true;
                 mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
+                notifyOnTip(DISMISS, RECENTS_SWIPE_UP_ONBOARDING_TIP);
+            } else {
+                notifyOnTip(DISMISS, RECENTS_QUICK_SCRUB_ONBOARDING_TIP);
             }
         });
 
@@ -265,6 +288,15 @@
         }
     }
 
+    private void notifyOnTip(int action, int target) {
+        try {
+            IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+            if(overviewProxy != null) {
+                overviewProxy.onTip(action, target);
+            }
+        } catch (RemoteException e) {}
+    }
+
     public void onConnectedToLauncher() {
         if (!ONBOARDING_ENABLED) {
             return;
@@ -307,9 +339,9 @@
         }
     }
 
-    public void show(@StringRes int stringRes) {
+    public boolean show(@StringRes int stringRes) {
         if (!shouldShow()) {
-            return;
+            return false;
         }
         mDismissView.setTag(stringRes);
         mLayout.setTag(stringRes);
@@ -328,7 +360,9 @@
                     .setDuration(SHOW_DURATION_MS)
                     .setInterpolator(new DecelerateInterpolator())
                     .start();
+            return true;
         }
+        return false;
     }
 
     /**
@@ -370,7 +404,7 @@
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
                 0, -mNavBarHeight / 2,
-                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
+                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
                 flags,
                 PixelFormat.TRANSLUCENT);
         lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
@@ -427,4 +461,13 @@
     private void setOpenedOverviewCount(int openedOverviewCount) {
         Prefs.putInt(mContext, OVERVIEW_OPENED_COUNT, openedOverviewCount);
     }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
+                hide(false);
+            }
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 82cf93e..b010199 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -54,6 +54,7 @@
 import android.view.ViewStub;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.widget.Chronometer;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -1599,6 +1600,10 @@
     public void doLongClickCallback(int x, int y) {
         createMenu();
         MenuItem menuItem = getProvider().getLongpressMenuItem(mContext);
+        doLongClickCallback(x, y, menuItem);
+    }
+
+    private void doLongClickCallback(int x, int y, MenuItem menuItem) {
         if (mLongPressListener != null && menuItem != null) {
             mLongPressListener.onLongPress(this, x, y, menuItem);
         }
@@ -2707,6 +2712,16 @@
                 info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
             }
         }
+        NotificationMenuRowPlugin provider = getProvider();
+        if (provider != null) {
+            MenuItem snoozeMenu = provider.getSnoozeMenuItem(getContext());
+            if (snoozeMenu != null) {
+                AccessibilityAction action = new AccessibilityAction(R.id.action_snooze,
+                    getContext().getResources()
+                        .getString(R.string.notification_menu_snooze_action));
+                info.addAction(action);
+            }
+        }
     }
 
     @Override
@@ -2725,6 +2740,16 @@
             case AccessibilityNodeInfo.ACTION_LONG_CLICK:
                 doLongClickCallback();
                 return true;
+            case R.id.action_snooze:
+                NotificationMenuRowPlugin provider = getProvider();
+                if (provider == null) {
+                    provider = createMenu();
+                }
+                MenuItem snoozeMenu = provider.getSnoozeMenuItem(getContext());
+                if (snoozeMenu != null) {
+                    doLongClickCallback(getWidth() / 2, getHeight() / 2, snoozeMenu);
+                }
+                return true;
         }
         return false;
     }
@@ -2743,6 +2768,10 @@
         return mNotificationViewState;
     }
 
+    public NotificationViewState getViewState() {
+        return mNotificationViewState;
+    }
+
     @Override
     public boolean isAboveShelf() {
         return !isOnKeyguard()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 8fa1b67..08d530b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -178,7 +178,7 @@
         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
         boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
         boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
-        int maxSize = Integer.MAX_VALUE;
+        int maxSize = Integer.MAX_VALUE / 2;
         int width = MeasureSpec.getSize(widthMeasureSpec);
         if (hasFixedHeight || isHeightLimited) {
             maxSize = MeasureSpec.getSize(heightMeasureSpec);
@@ -189,17 +189,15 @@
             if (mExpandedSmartReplyView != null) {
                 notificationMaxHeight += mExpandedSmartReplyView.getHeightUpperLimit();
             }
-            int size = Math.min(maxSize, notificationMaxHeight);
+            int size = notificationMaxHeight;
             ViewGroup.LayoutParams layoutParams = mExpandedChild.getLayoutParams();
             boolean useExactly = false;
             if (layoutParams.height >= 0) {
                 // An actual height is set
-                size = Math.min(maxSize, layoutParams.height);
+                size = Math.min(size, layoutParams.height);
                 useExactly = true;
             }
-            int spec = size == Integer.MAX_VALUE
-                    ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
-                    : MeasureSpec.makeMeasureSpec(size, useExactly
+            int spec = MeasureSpec.makeMeasureSpec(size, useExactly
                             ? MeasureSpec.EXACTLY
                             : MeasureSpec.AT_MOST);
             measureChildWithMargins(mExpandedChild, widthMeasureSpec, 0, spec, 0);
@@ -207,7 +205,7 @@
         }
         if (mContractedChild != null) {
             int heightSpec;
-            int size = Math.min(maxSize, mSmallHeight);
+            int size = mSmallHeight;
             ViewGroup.LayoutParams layoutParams = mContractedChild.getLayoutParams();
             boolean useExactly = false;
             if (layoutParams.height >= 0) {
@@ -241,7 +239,7 @@
         if (mHeadsUpChild != null) {
             int maxHeight = mHeadsUpHeight;
             maxHeight += mHeadsUpWrapper.getExtraMeasureHeight();
-            int size = Math.min(maxSize, maxHeight);
+            int size = maxHeight;
             ViewGroup.LayoutParams layoutParams = mHeadsUpChild.getLayoutParams();
             boolean useExactly = false;
             if (layoutParams.height >= 0) {
@@ -263,11 +261,11 @@
                         MeasureSpec.EXACTLY);
             }
             mSingleLineView.measure(singleLineWidthSpec,
-                    MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.AT_MOST));
+                    MeasureSpec.makeMeasureSpec(mNotificationMaxHeight, MeasureSpec.AT_MOST));
             maxChildHeight = Math.max(maxChildHeight, mSingleLineView.getMeasuredHeight());
         }
         if (mAmbientChild != null) {
-            int size = Math.min(maxSize, mNotificationAmbientHeight);
+            int size = mNotificationAmbientHeight;
             ViewGroup.LayoutParams layoutParams = mAmbientChild.getLayoutParams();
             boolean useExactly = false;
             if (layoutParams.height >= 0) {
@@ -281,7 +279,7 @@
             maxChildHeight = Math.max(maxChildHeight, mAmbientChild.getMeasuredHeight());
         }
         if (mAmbientSingleLineChild != null) {
-            int size = Math.min(maxSize, mNotificationAmbientHeight);
+            int size = mNotificationAmbientHeight;
             ViewGroup.LayoutParams layoutParams = mAmbientSingleLineChild.getLayoutParams();
             boolean useExactly = false;
             if (layoutParams.height >= 0) {
@@ -1201,8 +1199,13 @@
     }
     private void updateSingleLineView() {
         if (mIsChildInGroup) {
+            boolean isNewView = mSingleLineView == null;
             mSingleLineView = mHybridGroupManager.bindFromNotification(
                     mSingleLineView, mStatusBarNotification.getNotification());
+            if (isNewView) {
+                updateViewVisibility(mVisibleType, VISIBLE_TYPE_SINGLELINE,
+                        mSingleLineView, mSingleLineView);
+            }
         } else if (mSingleLineView != null) {
             removeView(mSingleLineView);
             mSingleLineView = null;
@@ -1211,8 +1214,13 @@
 
     private void updateAmbientSingleLineView() {
         if (mIsChildInGroup) {
+            boolean isNewView = mAmbientSingleLineChild == null;
             mAmbientSingleLineChild = mHybridGroupManager.bindAmbientFromNotification(
                     mAmbientSingleLineChild, mStatusBarNotification.getNotification());
+            if (isNewView) {
+                updateViewVisibility(mVisibleType, VISIBLE_TYPE_AMBIENT_SINGLELINE,
+                        mAmbientSingleLineChild, mAmbientSingleLineChild);
+            }
         } else if (mAmbientSingleLineChild != null) {
             removeView(mAmbientSingleLineChild);
             mAmbientSingleLineChild = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
index 7681530..f14ca71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
@@ -229,6 +229,7 @@
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
         mMessagingUtil = new NotificationMessagingUtil(context);
         mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
+        mGroupManager.setPendingEntries(mPendingNotifications);
     }
 
     public void setUpWithPresenter(NotificationPresenter presenter,
@@ -739,6 +740,7 @@
                 mNotificationData.getImportance(key));
 
         mPendingNotifications.put(key, shadeEntry);
+        mGroupManager.onPendingEntryAdded(shadeEntry);
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 0cc6137..eb46fba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -25,6 +25,7 @@
 import android.os.Handler;
 import android.support.annotation.Nullable;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 import android.view.ViewAnimationUtils;
 import android.view.accessibility.AccessibilityEvent;
@@ -247,25 +248,29 @@
     /** Animates in the guts view via either a fade or a circular reveal. */
     private void animateOpen(
             boolean shouldDoCircularReveal, int x, int y, @Nullable Runnable onAnimationEnd) {
-        if (shouldDoCircularReveal) {
-            double horz = Math.max(getWidth() - x, x);
-            double vert = Math.max(getHeight() - y, y);
-            float r = (float) Math.hypot(horz, vert);
-            // Circular reveal originating at (x, y)
-            Animator a = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
-            a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-            a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-            a.addListener(new AnimateOpenListener(onAnimationEnd));
-            a.start();
+        if (isAttachedToWindow()) {
+            if (shouldDoCircularReveal) {
+                double horz = Math.max(getWidth() - x, x);
+                double vert = Math.max(getHeight() - y, y);
+                float r = (float) Math.hypot(horz, vert);
+                // Circular reveal originating at (x, y)
+                Animator a = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
+                a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+                a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+                a.addListener(new AnimateOpenListener(onAnimationEnd));
+                a.start();
+            } else {
+                // Fade in content
+                this.setAlpha(0f);
+                this.animate()
+                        .alpha(1f)
+                        .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
+                        .setInterpolator(Interpolators.ALPHA_IN)
+                        .setListener(new AnimateOpenListener(onAnimationEnd))
+                        .start();
+            }
         } else {
-            // Fade in content
-            this.setAlpha(0f);
-            this.animate()
-                    .alpha(1f)
-                    .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
-                    .setInterpolator(Interpolators.ALPHA_IN)
-                    .setListener(new AnimateOpenListener(onAnimationEnd))
-                    .start();
+            Log.w(TAG, "Failed to animate guts open");
         }
     }
 
@@ -273,29 +278,33 @@
     /** Animates out the guts view via either a fade or a circular reveal. */
     @VisibleForTesting
     void animateClose(int x, int y, boolean shouldDoCircularReveal) {
-        if (shouldDoCircularReveal) {
-            // Circular reveal originating at (x, y)
-            if (x == -1 || y == -1) {
-                x = (getLeft() + getRight()) / 2;
-                y = (getTop() + getHeight() / 2);
+        if (isAttachedToWindow()) {
+            if (shouldDoCircularReveal) {
+                // Circular reveal originating at (x, y)
+                if (x == -1 || y == -1) {
+                    x = (getLeft() + getRight()) / 2;
+                    y = (getTop() + getHeight() / 2);
+                }
+                double horz = Math.max(getWidth() - x, x);
+                double vert = Math.max(getHeight() - y, y);
+                float r = (float) Math.hypot(horz, vert);
+                Animator a = ViewAnimationUtils.createCircularReveal(this,
+                        x, y, r, 0);
+                a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+                a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+                a.addListener(new AnimateCloseListener(this /* view */));
+                a.start();
+            } else {
+                // Fade in the blocking helper.
+                this.animate()
+                        .alpha(0f)
+                        .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
+                        .setInterpolator(Interpolators.ALPHA_OUT)
+                        .setListener(new AnimateCloseListener(this /* view */))
+                        .start();
             }
-            double horz = Math.max(getWidth() - x, x);
-            double vert = Math.max(getHeight() - y, y);
-            float r = (float) Math.hypot(horz, vert);
-            Animator a = ViewAnimationUtils.createCircularReveal(this,
-                    x, y, r, 0);
-            a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-            a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-            a.addListener(new AnimateCloseListener(this /* view */));
-            a.start();
         } else {
-            // Fade in the blocking helper.
-            this.animate()
-                    .alpha(0f)
-                    .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
-                    .setInterpolator(Interpolators.ALPHA_OUT)
-                    .setListener(new AnimateCloseListener(this /* view */))
-                    .start();
+            Log.w(TAG, "Failed to animate guts close");
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 0eb6bd4e..ada1a17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -70,6 +70,7 @@
     private FrameLayout mMenuContainer;
     private MenuItem mInfoItem;
     private MenuItem mAppOpsItem;
+    private MenuItem mSnoozeItem;
     private ArrayList<MenuItem> mMenuItems;
     private OnMenuEventListener mMenuListener;
 
@@ -128,6 +129,11 @@
     }
 
     @Override
+    public MenuItem getSnoozeMenuItem(Context context) {
+        return mSnoozeItem;
+    }
+
+    @Override
     public void setSwipeActionHelper(NotificationSwipeActionHelper helper) {
         mSwipeHelper = helper;
     }
@@ -190,7 +196,8 @@
             boolean isForeground = (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
             if (!isForeground) {
                 // Only show snooze for non-foreground notifications
-                mMenuItems.add(createSnoozeItem(mContext));
+                mSnoozeItem = createSnoozeItem(mContext);
+                mMenuItems.add(mSnoozeItem);
             }
         }
         mInfoItem = createInfoItem(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index c4a7814..76860e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -266,7 +266,9 @@
     }
 
     private void showBouncer() {
-        mStatusBarKeyguardViewManager.showBouncer(false);
+        if (calculateMode() == MODE_SHOW_BOUNCER) {
+            mStatusBarKeyguardViewManager.showBouncer(false);
+        }
         mStatusBarKeyguardViewManager.animateCollapsePanels(
                 FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
         mPendingShowBouncer = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 9ec5609..06f3c50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -36,7 +36,7 @@
 /**
  * Controls the appearance of heads up notifications in the icon area and the header itself.
  */
-class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
+public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
         DarkIconDispatcher.DarkReceiver {
     public static final int CONTENT_FADE_DURATION = 110;
     public static final int CONTENT_FADE_DELAY = 100;
@@ -92,6 +92,7 @@
         panelView.setHeadsUpAppearanceController(this);
         mStackScroller.addOnExpandedHeightListener(mSetExpandedHeight);
         mStackScroller.addOnLayoutChangeListener(mStackScrollLayoutChangeListener);
+        mStackScroller.setHeadsUpAppearanceController(this);
         mClockView = clockView;
         mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
         mDarkIconDispatcher.addDarkReceiver(this);
@@ -226,10 +227,10 @@
         });
     }
 
-    private void updateHeader(NotificationData.Entry entry) {
+    public void updateHeader(NotificationData.Entry entry) {
         ExpandableNotificationRow row = entry.row;
         float headerVisibleAmount = 1.0f;
-        if (row.isPinned() || row == mTrackedChild) {
+        if (row.isPinned() || row.isHeadsUpAnimatingAway() || row == mTrackedChild) {
             headerVisibleAmount = mExpandFraction;
         }
         row.setHeaderVisibleAmount(headerVisibleAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index ca65965..55ffb3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.Notification;
+import android.os.SystemClock;
 import android.service.notification.StatusBarNotification;
 import android.support.annotation.Nullable;
 import android.util.Log;
@@ -29,9 +31,11 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * A class to handle notifications and their corresponding groups.
@@ -39,12 +43,14 @@
 public class NotificationGroupManager implements OnHeadsUpChangedListener {
 
     private static final String TAG = "NotificationGroupManager";
+    private static final long HEADS_UP_TRANSFER_TIMEOUT = 300;
     private final HashMap<String, NotificationGroup> mGroupMap = new HashMap<>();
     private OnGroupChangeListener mListener;
     private int mBarState = -1;
     private HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>();
     private HeadsUpManager mHeadsUpManager;
     private boolean mIsUpdatingUnchangedGroup;
+    private HashMap<String, NotificationData.Entry> mPendingNotifications;
 
     public void setOnGroupChangeListener(OnGroupChangeListener listener) {
         mListener = listener;
@@ -147,6 +153,103 @@
                 mListener.onGroupCreatedFromChildren(group);
             }
         }
+        cleanUpHeadsUpStatesOnAdd(group, false /* addIsPending */);
+    }
+
+    public void onPendingEntryAdded(NotificationData.Entry shadeEntry) {
+        String groupKey = getGroupKey(shadeEntry.notification);
+        NotificationGroup group = mGroupMap.get(groupKey);
+        if (group != null) {
+            cleanUpHeadsUpStatesOnAdd(group, true /* addIsPending */);
+        }
+    }
+
+    /**
+     * Clean up the heads up states when a new child was added.
+     * @param group The group where a view was added or will be added.
+     * @param addIsPending True if is the addition still pending or false has it already been added.
+     */
+    private void cleanUpHeadsUpStatesOnAdd(NotificationGroup group, boolean addIsPending) {
+        if (!addIsPending && group.hunSummaryOnNextAddition) {
+            if (!mHeadsUpManager.isHeadsUp(group.summary.key)) {
+                mHeadsUpManager.showNotification(group.summary);
+            }
+            group.hunSummaryOnNextAddition = false;
+        }
+        // Because notification groups are not delivered as a whole unit, it may happen that a
+        // group child gets added quite a bit after the summary got posted. Our guidance is, that
+        // apps should always post the group summary as well and we'll hide it for them if the child
+        // is the only child in a group. Because of this, we also have to transfer heads up to the
+        // child, otherwise the invisible summary would be heads-upped.
+        // This transfer to the child is not always correct in case the app has just posted another
+        // child in addition to the existing one, but it hasn't arrived in systemUI yet. In such
+        // a scenario we would transfer the heads up to the old child and the wrong notification
+        // would be heads-upped. In oder to avoid this, we'll recover from this issue and hun the
+        // summary again instead of the old child if it's within a certain timeout.
+        if (SystemClock.elapsedRealtime() - group.lastHeadsUpTransfer < HEADS_UP_TRANSFER_TIMEOUT) {
+            if (!onlySummaryAlerts(group.summary)) {
+                return;
+            }
+            int numChildren = group.children.size();
+            NotificationData.Entry isolatedChild = getIsolatedChild(getGroupKey(
+                    group.summary.notification));
+            int numPendingChildren = getPendingChildrenNotAlerting(group);
+            numChildren += numPendingChildren;
+            if (isolatedChild != null) {
+                numChildren++;
+            }
+            if (numChildren <= 1) {
+                return;
+            }
+            boolean releasedChild = false;
+            ArrayList<NotificationData.Entry> children = new ArrayList<>(group.children.values());
+            int size = children.size();
+            for (int i = 0; i < size; i++) {
+                NotificationData.Entry entry = children.get(i);
+                if (onlySummaryAlerts(entry) && entry.row.isHeadsUp()) {
+                    releasedChild = true;
+                    mHeadsUpManager.releaseImmediately(entry.key);
+                }
+            }
+            if (isolatedChild != null && onlySummaryAlerts(isolatedChild)
+                    && isolatedChild.row.isHeadsUp()) {
+                releasedChild = true;
+                mHeadsUpManager.releaseImmediately(isolatedChild.key);
+            }
+            if (releasedChild && !mHeadsUpManager.isHeadsUp(group.summary.key)) {
+                boolean notifyImmediately = (numChildren - numPendingChildren) > 1;
+                if (notifyImmediately) {
+                    mHeadsUpManager.showNotification(group.summary);
+                } else {
+                    group.hunSummaryOnNextAddition = true;
+                }
+                group.lastHeadsUpTransfer = 0;
+            }
+        }
+    }
+
+    private int getPendingChildrenNotAlerting(NotificationGroup group) {
+        if (mPendingNotifications == null) {
+            return 0;
+        }
+        int number = 0;
+        String groupKey = getGroupKey(group.summary.notification);
+        Collection<NotificationData.Entry> values = mPendingNotifications.values();
+        for (NotificationData.Entry entry : values) {
+            if (!isGroupChild(entry.notification)) {
+                continue;
+            }
+            if (!Objects.equals(getGroupKey(entry.notification), groupKey)) {
+                continue;
+            }
+            if (group.children.containsKey(entry.key)) {
+                continue;
+            }
+            if (onlySummaryAlerts(entry)) {
+                number++;
+            }
+        }
+        return number;
     }
 
     private void onEntryBecomingChild(NotificationData.Entry entry) {
@@ -421,8 +524,16 @@
                 || !entry.row.isHeadsUp()) {
             return;
         }
+
         // The parent of a suppressed group got huned, lets hun the child!
         NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
+
+        if (pendingInflationsWillAddChildren(notificationGroup)) {
+            // New children will actually be added to this group, let's not transfer the heads
+            // up
+            return;
+        }
+
         if (notificationGroup != null) {
             Iterator<NotificationData.Entry> iterator
                     = notificationGroup.children.values().iterator();
@@ -438,6 +549,9 @@
                 if (mHeadsUpManager.isHeadsUp(child.key)) {
                     mHeadsUpManager.updateNotification(child, true);
                 } else {
+                    if (onlySummaryAlerts(entry)) {
+                        notificationGroup.lastHeadsUpTransfer = SystemClock.elapsedRealtime();
+                    }
                     mHeadsUpManager.showNotification(child);
                 }
             }
@@ -445,6 +559,35 @@
         mHeadsUpManager.releaseImmediately(entry.key);
     }
 
+    private boolean onlySummaryAlerts(NotificationData.Entry entry) {
+        return entry.notification.getNotification().getGroupAlertBehavior()
+                == Notification.GROUP_ALERT_SUMMARY;
+    }
+
+    /**
+     * Check if the pending inflations will add children to this group.
+     * @param group The group to check.
+     */
+    private boolean pendingInflationsWillAddChildren(NotificationGroup group) {
+        if (mPendingNotifications == null) {
+            return false;
+        }
+        Collection<NotificationData.Entry> values = mPendingNotifications.values();
+        String groupKey = getGroupKey(group.summary.notification);
+        for (NotificationData.Entry entry : values) {
+            if (!isGroupChild(entry.notification)) {
+                continue;
+            }
+            if (!Objects.equals(getGroupKey(entry.notification), groupKey)) {
+                continue;
+            }
+            if (!group.children.containsKey(entry.key)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private boolean shouldIsolate(StatusBarNotification sbn) {
         NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
         return (sbn.isGroup() && !sbn.getNotification().isGroupSummary())
@@ -477,6 +620,10 @@
         }
     }
 
+    public void setPendingEntries(HashMap<String, NotificationData.Entry> pendingNotifications) {
+        mPendingNotifications = pendingNotifications;
+    }
+
     public static class NotificationGroup {
         public final HashMap<String, NotificationData.Entry> children = new HashMap<>();
         public NotificationData.Entry summary;
@@ -485,6 +632,12 @@
          * Is this notification group suppressed, i.e its summary is hidden
          */
         public boolean suppressed;
+        /**
+         * The time when the last heads transfer from group to child happened, while the summary
+         * has the flags to heads up on its own.
+         */
+        public long lastHeadsUpTransfer;
+        public boolean hunSummaryOnNextAddition;
 
         @Override
         public String toString() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index 55ec142..45fa44c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -269,6 +269,12 @@
 
         updateGroupOverflow();
         row.setContentTransformationAmount(0, false /* isLastChild */);
+        // It doesn't make sense to keep old animations around, lets cancel them!
+        ExpandableNotificationRow.NotificationViewState viewState = row.getViewState();
+        if (viewState != null) {
+            viewState.cancelAnimations(row);
+            row.cancelAppearDrawing();
+        }
     }
 
     public void removeNotification(ExpandableNotificationRow row) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 236ead0..ee70019 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -98,6 +98,7 @@
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.ScrimController;
@@ -292,7 +293,7 @@
     private int[] mTempInt2 = new int[2];
     private boolean mGenerateChildOrderChangedEvent;
     private HashSet<Runnable> mAnimationFinishedRunnables = new HashSet<>();
-    private HashSet<View> mClearOverlayViewsWhenFinished = new HashSet<>();
+    private HashSet<ExpandableView> mClearTransientViewsWhenFinished = new HashSet<>();
     private HashSet<Pair<ExpandableNotificationRow, Boolean>> mHeadsUpChangeAnimations
             = new HashSet<>();
     private HeadsUpManagerPhone mHeadsUpManager;
@@ -413,6 +414,7 @@
     private int mAntiBurnInOffsetX;
     private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>();
     private int mHeadsUpInset;
+    private HeadsUpAppearanceController mHeadsUpAppearanceController;
 
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -727,7 +729,7 @@
     }
 
     private void updateAlgorithmLayoutMinHeight() {
-        mAmbientState.setLayoutMinHeight(mQsExpanded && !onKeyguard() || isHeadsUpTransition()
+        mAmbientState.setLayoutMinHeight(mQsExpanded || isHeadsUpTransition()
                 ? getLayoutMinHeight() : 0);
     }
 
@@ -2451,7 +2453,6 @@
             }
             int finalHeight = ExpandableViewState.getFinalActualHeight(lastView);
             int finalBottom = finalTranslationY + finalHeight - lastView.getClipBottomAmount();
-            finalBottom = Math.min(finalBottom, getHeight());
             if (mAnimateNextBackgroundBottom
                     || mBottomAnimator == null && mCurrentBounds.bottom == finalBottom
                     || mBottomAnimator != null && mEndAnimationRect.bottom == finalBottom) {
@@ -2460,7 +2461,6 @@
             } else {
                 bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight()
                         - lastView.getClipBottomAmount());
-                bottom = Math.min(bottom, getHeight());
             }
         } else {
             top = mTopPadding;
@@ -2473,7 +2473,7 @@
             top = Math.max(0, top);
         }
         mBackgroundBounds.top = top;
-        mBackgroundBounds.bottom = Math.min(getHeight(), Math.max(bottom, top));
+        mBackgroundBounds.bottom = Math.max(bottom, top);
     }
 
     private ActivatableNotificationView getFirstPinnedHeadsUp() {
@@ -2831,8 +2831,8 @@
             return false;
         }
         if (isClickedHeadsUp(child)) {
-            // An animation is already running, add it to the Overlay
-            mClearOverlayViewsWhenFinished.add(child);
+            // An animation is already running, add it transiently
+            mClearTransientViewsWhenFinished.add((ExpandableView) child);
             return true;
         }
         if (mIsExpanded && mAnimationsEnabled && !isChildInInvisibleGroup(child)) {
@@ -3079,8 +3079,10 @@
 
     @Override
     public void bindRow(ExpandableNotificationRow row) {
-        row.setHeadsUpAnimatingAwayListener(animatingAway
-                -> mRoundnessManager.onHeadsupAnimatingAwayChanged(row, animatingAway));
+        row.setHeadsUpAnimatingAwayListener(animatingAway -> {
+            mRoundnessManager.onHeadsupAnimatingAwayChanged(row, animatingAway);
+            mHeadsUpAppearanceController.updateHeader(row.getEntry());
+        });
     }
 
     @Override
@@ -3202,6 +3204,7 @@
                 if (row.isChildInGroup()) {
                     // We can otherwise get stuck in there if it was just isolated
                     row.setHeadsUpAnimatingAway(false);
+                    continue;
                 }
             } else {
                 ExpandableViewState viewState = mCurrentStackScrollState.getViewStateForView(row);
@@ -3622,7 +3625,7 @@
     }
 
     private void clearTemporaryViews() {
-        // lets make sure nothing is in the overlay / transient anymore
+        // lets make sure nothing is transient anymore
         clearTemporaryViewsInGroup(this);
         for (int i = 0; i < getChildCount(); i++) {
             ExpandableView child = (ExpandableView) getChildAt(i);
@@ -3637,9 +3640,6 @@
         while (viewGroup != null && viewGroup.getTransientViewCount() != 0) {
             viewGroup.removeTransientView(viewGroup.getTransientView(0));
         }
-        if (viewGroup != null) {
-            viewGroup.getOverlay().clear();
-        }
     }
 
     public void onPanelTrackingStarted() {
@@ -3747,7 +3747,7 @@
         setAnimationRunning(false);
         requestChildrenUpdate();
         runAnimationFinishedRunnables();
-        clearViewOverlays();
+        clearTransient();
         clearHeadsUpDisappearRunning();
     }
 
@@ -3766,11 +3766,11 @@
         }
     }
 
-    private void clearViewOverlays() {
-        for (View view : mClearOverlayViewsWhenFinished) {
-            StackStateAnimator.removeFromOverlay(view);
+    private void clearTransient() {
+        for (ExpandableView view : mClearTransientViewsWhenFinished) {
+            StackStateAnimator.removeTransientView(view);
         }
-        mClearOverlayViewsWhenFinished.clear();
+        mClearTransientViewsWhenFinished.clear();
     }
 
     private void runAnimationFinishedRunnables() {
@@ -4638,6 +4638,11 @@
         mExpandedHeightListeners.remove(listener);
     }
 
+    public void setHeadsUpAppearanceController(
+            HeadsUpAppearanceController headsUpAppearanceController) {
+        mHeadsUpAppearanceController = headsUpAppearanceController;
+    }
+
     /**
      * A listener that is notified when the empty space below the notifications is clicked on
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index f4d7f8d..85f33d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -478,6 +478,22 @@
                 childState.hidden = false;
             }
         }
+        // Let's hide all the views if we are not expanded. the views might otherwise be visible
+        // in the headsup area if a view was swiped away
+        if (!mIsExpanded) {
+            for (int i = 0; i < childCount; i++) {
+                boolean visible = false;
+                View child = algorithmState.visibleChildren.get(i);
+                if (child instanceof ExpandableNotificationRow) {
+                    ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                    visible = row.isHeadsUp() || row.isHeadsUpAnimatingAway();
+                }
+                if (!visible) {
+                    ExpandableViewState childState = resultState.getViewStateForView(child);
+                    childState.hidden = true;
+                }
+            }
+        }
     }
 
     private void clampHunToTop(AmbientState ambientState, ExpandableNotificationRow row,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index d01db14..4e8fcac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -419,9 +419,6 @@
                 }, null);
             } else if (event.animationType ==
                 NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT) {
-                // A race condition can trigger the view to be added to the overlay even though
-                // it was fully swiped out. So let's remove it
-                mHostLayout.getOverlay().remove(changingView);
                 if (Math.abs(changingView.getTranslation()) == changingView.getWidth()
                         && changingView.getTransientContainer() != null) {
                     changingView.getTransientContainer().removeTransientView(changingView);
@@ -469,8 +466,9 @@
                         ? ANIMATION_DELAY_HEADS_UP_CLICKED
                         : 0;
                 if (changingView.getParent() == null) {
-                    // This notification was actually removed, so we need to add it to the overlay
-                    mHostLayout.getOverlay().add(changingView);
+                    // This notification was actually removed, so we need to add it transiently
+                    mHostLayout.addTransientView(changingView, 0);
+                    changingView.setTransientContainer(mHostLayout);
                     mTmpState.initFrom(changingView);
                     mTmpState.yTranslation = 0;
                     // We temporarily enable Y animations, the real filter will be combined
@@ -479,10 +477,7 @@
                     mAnimationProperties.delay = extraDelay + ANIMATION_DELAY_HEADS_UP;
                     mAnimationProperties.duration = ANIMATION_DURATION_HEADS_UP_DISAPPEAR;
                     mTmpState.animateTo(changingView, mAnimationProperties);
-                    endRunnable = () -> {
-                        // remove the temporary overlay
-                        removeFromOverlay(changingView);
-                    };
+                    endRunnable = () -> removeTransientView(changingView);
                 }
                 float targetLocation = 0;
                 boolean needsAnimation = true;
@@ -517,19 +512,12 @@
         }
     }
 
-    private static void removeTransientView(ExpandableView viewToRemove) {
+    public static void removeTransientView(ExpandableView viewToRemove) {
         if (viewToRemove.getTransientContainer() != null) {
             viewToRemove.getTransientContainer().removeTransientView(viewToRemove);
         }
     }
 
-    public static void removeFromOverlay(View changingView) {
-        ViewGroup parent = (ViewGroup) changingView.getParent();
-        if (parent != null) {
-            parent.removeView(changingView);
-        }
-    }
-
     public void animateOverScrollToAmount(float targetAmount, final boolean onTop,
             final boolean isRubberbanded) {
         final float startOverScrollAmount = mHostLayout.getCurrentOverScrollAmount(onTop);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 611d4eb..1bdb7ad 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -54,6 +54,7 @@
     // shouldn't be reset with tuner settings.
     private static final String[] RESET_BLACKLIST = new String[] {
             QSTileHost.TILES_SETTING,
+            Settings.Secure.DOZE_ALWAYS_ON
     };
 
     private final Observer mObserver = new Observer();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index a97effd..b360edc 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -17,6 +17,8 @@
 package com.android.systemui.volume;
 
 import static android.media.AudioManager.RINGER_MODE_NORMAL;
+import static android.media.AudioManager.RINGER_MODE_SILENT;
+import static android.media.AudioManager.RINGER_MODE_VIBRATE;
 
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
@@ -581,11 +583,28 @@
         mState.ringerModeInternal = rm;
         Events.writeEvent(mContext, Events.EVENT_INTERNAL_RINGER_MODE_CHANGED, rm);
 
-        if (mState.ringerModeInternal == RINGER_MODE_NORMAL) {
-            playTouchFeedback();
+        provideFeedback(mState.ringerModeInternal);
+        return true;
+    }
+
+    private void provideFeedback(int newRingerMode) {
+        VibrationEffect effect = null;
+        switch (newRingerMode) {
+            case RINGER_MODE_NORMAL:
+                scheduleTouchFeedback();
+                playTouchFeedback();
+                break;
+            case RINGER_MODE_SILENT:
+                effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
+                break;
+            case RINGER_MODE_VIBRATE:
+            default:
+                effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
         }
 
-        return true;
+        if (effect != null) {
+            vibrate(effect);
+        }
     }
 
     private void onSetRingerModeW(int mode, boolean external) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 6b322c7..2cff00c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -446,32 +446,12 @@
             }
             Events.writeEvent(mContext, Events.EVENT_RINGER_TOGGLE, newRingerMode);
             updateRingerH();
-            provideTouchFeedbackH(newRingerMode);
             mController.setRingerMode(newRingerMode, false);
             maybeShowToastH(newRingerMode);
         });
         updateRingerH();
     }
 
-
-    private void provideTouchFeedbackH(int newRingerMode) {
-        VibrationEffect effect = null;
-        switch (newRingerMode) {
-            case RINGER_MODE_NORMAL:
-                mController.scheduleTouchFeedback();
-                break;
-            case RINGER_MODE_SILENT:
-                effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
-                break;
-            case RINGER_MODE_VIBRATE:
-            default:
-                effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
-        }
-        if (effect != null) {
-            mController.vibrate(effect);
-        }
-    }
-
     private void maybeShowToastH(int newRingerMode) {
         int seenToastCount = Prefs.getInt(mContext, Prefs.Key.SEEN_RINGER_GUIDANCE_COUNT, 0);
 
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 95dc3ab..c22dac8 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -188,6 +188,23 @@
     ACCESS_METHOD_LINKING = 3; // never logged, included for completeness
   }
 
+  enum HardwareType {
+        HARDWARE_UNKNOWN = 0;
+        HARDWARE_MICROPHONE = 1;
+        HARDWARE_CODEC = 2;
+        HARDWARE_SPEAKER = 3;
+        HARDWARE_FINGERPRINT = 4;
+    }
+
+    enum HardwareFailureCode {
+        HARDWARE_FAILURE_UNKNOWN = 0;
+        HARDWARE_FAILURE_COMPLETE = 1;
+        HARDWARE_FAILURE_SPEAKER_HIGH_Z = 2;
+        HARDWARE_FAILURE_SPEAKER_SHORT = 3;
+        HARDWARE_FAILURE_FINGERPRINT_SENSOR_BROKEN = 4;
+        HARDWARE_FAILURE_FINGERPRINT_TOO_MANY_DEAD_PIXELS = 5;
+    }
+
   // Known visual elements: views or controls.
   enum View {
     // Unknown view
@@ -5296,11 +5313,11 @@
     // OS: P
     FIELD_DURATION_MILLIS = 1304;
 
-    // Battery level in uA (0 - ~3,000,000 depending on device) when the current "mode" started.
+    // Battery level in uAh (0 - ~3,000,000 depending on device) when the current "mode" started.
     // OS: P
     FIELD_START_BATTERY_UA = 1305;
 
-    // Battery level in uA (0 - ~3,000,000 depending on device) when this event was created.
+    // Battery level in uAh (0 - ~3,000,000 depending on device) when this event was created.
     // OS: P
     FIELD_END_BATTERY_UA = 1306;
 
@@ -5329,7 +5346,6 @@
     // OS: P
     FIELD_QS_MODE = 1311;
 
-
     // OPEN: Settings->Developer Options->Default USB
     // CATEGORY: SETTINGS
     // OS: P
@@ -5733,8 +5749,8 @@
     // OS: P
     FIELD_HIDDEN_API_SIGNATURE = 1394;
 
-    // This value should never appear in log outputs - it is reserved for
-    // internal platform metrics use.
+    // The number of items in the shade when this notification event was logged.
+    // OS: P
     NOTIFICATION_SHADE_COUNT = 1395;
 
     // ACTION: DND Settings > What to block
@@ -5852,6 +5868,107 @@
     // 3 = Wireless
     FIELD_PLUG_TYPE = 1421;
 
+    // ACTION: USB-C Connector connected.
+    // CATEGORY: OTHER
+    // OS: P
+    ACTION_USB_CONNECTOR_CONNECTED = 1422;
+
+    // ACTION: USB-C Connector disconnected.
+    // CATEGORY: OTHER
+    // OS: P
+    // uses FIELD_DURATION_MILLIS for connected duration
+    ACTION_USB_CONNECTOR_DISCONNECTED = 1423;
+
+    // ACTION: USB-C Audio device connected
+    // CATEGORY: OTHER
+    // OS: P
+    ACTION_USB_AUDIO_CONNECTED = 1424;
+
+    // FIELD: VIDPID of connected USB Audio device
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_USB_AUDIO_VIDPID = 1425;
+
+    // ACTION: USB-C Audio device disconnected
+    // CATEGORY: OTHER
+    // OS: P
+    // use FIELD_DURATION_MILLIS for time
+    ACTION_USB_AUDIO_DISCONNECTED = 1426;
+
+    // ACTION: Hardware failure event
+    // CATEGORY: OTHER
+    // OS: P
+    ACTION_HARDWARE_FAILED = 1427;
+
+    // FIELD: Hardware failure category
+    // CATEGORY: OTHER
+    // OS: P
+    // Uses enum HardwareType
+    FIELD_HARDWARE_TYPE = 1428;
+
+    // FIELD: Hardware failure category
+    // CATEGORY: OTHER
+    // OS: P
+    // Uses enum HardwareFailureCode
+    FIELD_HARDWARE_FAILURE_CODE = 1429;
+
+    // ACTION: Physical drop event
+    // CATEGORY: OTHER
+    // OS: P
+    // use FIELD_DURATION_MILLIS for time
+    ACTION_PHYSICAL_DROP = 1430;
+
+    // FIELD: Confidence in detection of drop, in integer percentage.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_CONFIDENCE_PERCENT = 1431;
+
+    // FIELD: Detected bounce acceleration, in 1/1000th of a G.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_ACCEL_MILLI_G = 1432;
+
+    // ACTION: Battery health snapshot
+    // CATEGORY: OTHER
+    // OS: P
+    // uses FIELD_END_BATTERY_PERCENT for batt %
+    // uses FIELD_END_BATTERY_UA for instantaneous current load
+    ACTION_BATTERY_HEALTH = 1433;
+
+    // FIELD: Battery health snapshot type - min daily voltage, resistance, etc.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_BATTERY_HEALTH_SNAPSHOT_TYPE = 1434;
+
+    // FIELD: Battery temperature at snapshop.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_BATTERY_TEMPERATURE = 1435;
+
+    // FIELD: Battery voltage at snapshot.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_BATTERY_VOLTAGE = 1436;
+
+    // FIELD: Battery open circuit voltage at snapshot.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_BATTERY_OPEN_CIRCUIT_VOLTAGE = 1437;
+
+    // ACTION: Battery charge cycles
+    //         Number of times the battery has charged beyond a
+    //         fractional threshold of full capacity.
+    // CATEGORY: OTHER
+    // OS: P
+    ACTION_BATTERY_CHARGE_CYCLES = 1438;
+
+    // FIELD: Battery charge cycles
+    //        Number of times the battery has charged beyond a
+    //        fractional threshold of full capacity.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_BATTERY_CHARGE_CYCLES = 1439;
+
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index f9af31c..a9a14ca 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -184,19 +184,19 @@
     NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED = 41;
 
     // Inform the user that a wrong password was detected while attempting to connect
-    // to a Wi-Fi network
+    // to a wifi network
     NOTE_WIFI_WRONG_PASSWORD = 42;
 
     // Inform the user that Wifi Wake will re-enable wifi when possible
     NOTE_WIFI_WAKE_ONBOARD = 43;
 
-    // Inform the user that Wifi Wake has automatically re-enabled Wifi
+    // Inform the user that Wifi Wake has automatically re-enabled wifi
     NOTE_WIFI_WAKE_TURNED_BACK_ON = 44;
 
     // Inform the user that unexpectedly rapid network usage is happening
     NOTE_NET_RAPID = 45;
 
-    // Notify the user that carrier Wi-Fi networks are available.
+    // Notify the user that carrier wifi networks are available.
     // Package: android
     NOTE_CARRIER_NETWORK_AVAILABLE = 46;
 
@@ -248,10 +248,10 @@
     // Package: com.android.systemui
     NOTE_TV_PIP = 1100;
 
-    // Extreme battery saver notifiaction.
+    // Extreme battery saver notification.
     NOTE_BATTERY_SAVER_WARNING = 1200;
 
-    // Notify the user that open Wi-Fi networks are available.
+    // Notify the user that open wifi networks are available.
     // Package: android
     NOTE_NETWORK_AVAILABLE = 17303299;
 
@@ -261,7 +261,6 @@
 
     // Notify the user about public volume state changes..
     // Package: com.android.systemui
-
     NOTE_STORAGE_PUBLIC = 0x53505542;  // 1397773634
 
     // Notify the user about private volume state changes.
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index f992049..db8ad12 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -20,6 +20,8 @@
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.AlarmManager;
@@ -50,6 +52,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
@@ -96,13 +99,13 @@
 import android.widget.RemoteViews;
 
 import com.android.internal.R;
+import com.android.internal.app.SuspendedAppActivity;
 import com.android.internal.app.UnlaunchableAppActivity;
 import com.android.internal.appwidget.IAppWidgetHost;
 import com.android.internal.appwidget.IAppWidgetService;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.widget.IRemoteViewsFactory;
@@ -110,7 +113,6 @@
 import com.android.server.WidgetBackupProvider;
 import com.android.server.policy.IconUtilities;
 
-import libcore.util.EmptyArray;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -228,6 +230,7 @@
     private AppOpsManager mAppOpsManager;
     private KeyguardManager mKeyguardManager;
     private DevicePolicyManagerInternal mDevicePolicyManagerInternal;
+    private PackageManagerInternal mPackageManagerInternal;
 
     private SecurityPolicy mSecurityPolicy;
 
@@ -254,6 +257,7 @@
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         mKeyguardManager = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
         mDevicePolicyManagerInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
+        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mSaveStateHandler = BackgroundThread.getHandler();
         mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
         mBackupRestoreController = new BackupRestoreController();
@@ -620,8 +624,17 @@
             if (provider.maskedBySuspendedPackage) {
                 UserInfo userInfo = mUserManager.getUserInfo(providerUserId);
                 showBadge = userInfo.isManagedProfile();
-                onClickIntent = mDevicePolicyManagerInternal.createShowAdminSupportIntent(
-                        providerUserId, true);
+                final String suspendingPackage = mPackageManagerInternal.getSuspendingPackage(
+                        providerPackage, providerUserId);
+                if (PLATFORM_PACKAGE_NAME.equals(suspendingPackage)) {
+                    onClickIntent = mDevicePolicyManagerInternal.createShowAdminSupportIntent(
+                            providerUserId, true);
+                } else {
+                    final String dialogMessage = mPackageManagerInternal.getSuspendedDialogMessage(
+                            providerPackage, providerUserId);
+                    onClickIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(
+                            providerPackage, suspendingPackage, dialogMessage, providerUserId);
+                }
             } else if (provider.maskedByQuietProfile) {
                 showBadge = true;
                 onClickIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(
@@ -824,6 +837,12 @@
         mSecurityPolicy.enforceCallFromPackage(callingPackage);
 
         synchronized (mLock) {
+            // Instant apps cannot host app widgets.
+            if (mSecurityPolicy.isInstantAppLocked(callingPackage, userId)) {
+                Slog.w(TAG, "Instant package " + callingPackage + " cannot host app widgets");
+                return ParceledListSlice.emptyList();
+            }
+
             ensureGroupStateLoadedLocked(userId);
 
             // NOTE: The lookup is enforcing security across users by making
@@ -890,6 +909,12 @@
         mSecurityPolicy.enforceCallFromPackage(callingPackage);
 
         synchronized (mLock) {
+            // Instant apps cannot host app widgets.
+            if (mSecurityPolicy.isInstantAppLocked(callingPackage, userId)) {
+                Slog.w(TAG, "Instant package " + callingPackage + " cannot host app widgets");
+                return AppWidgetManager.INVALID_APPWIDGET_ID;
+            }
+
             ensureGroupStateLoadedLocked(userId);
 
             if (mNextAppWidgetIds.indexOfKey(userId) < 0) {
@@ -1621,6 +1646,13 @@
 
     @Override
     public boolean isRequestPinAppWidgetSupported() {
+        synchronized (mLock) {
+            if (mSecurityPolicy.isCallerInstantAppLocked()) {
+                Slog.w(TAG, "Instant uid " + Binder.getCallingUid()
+                        + " query information about app widgets");
+                return false;
+            }
+        }
         return LocalServices.getService(ShortcutServiceInternal.class)
                 .isRequestPinItemSupported(UserHandle.getCallingUserId(),
                         LauncherApps.PinItemRequest.REQUEST_TYPE_APPWIDGET);
@@ -1671,6 +1703,12 @@
         }
 
         synchronized (mLock) {
+            if (mSecurityPolicy.isCallerInstantAppLocked()) {
+                Slog.w(TAG, "Instant uid " + Binder.getCallingUid()
+                        + " cannot access widget providers");
+                return ParceledListSlice.emptyList();
+            }
+
             ensureGroupStateLoadedLocked(userId);
 
             ArrayList<AppWidgetProviderInfo> result = new ArrayList<AppWidgetProviderInfo>();
@@ -3652,6 +3690,35 @@
                     "hasBindAppWidgetPermission packageName=" + packageName);
         }
 
+        public boolean isCallerInstantAppLocked() {
+            final int callingUid =  Binder.getCallingUid();
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                final String[] uidPackages = mPackageManager.getPackagesForUid(callingUid);
+                if (!ArrayUtils.isEmpty(uidPackages)) {
+                    return mPackageManager.isInstantApp(uidPackages[0],
+                            UserHandle.getCallingUserId());
+                }
+            } catch (RemoteException e) {
+                /* ignore - same process */
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            return false;
+        }
+
+        public boolean isInstantAppLocked(String packageName, int userId) {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                return mPackageManager.isInstantApp(packageName, userId);
+            } catch (RemoteException e) {
+                /* ignore - same process */
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            return false;
+        }
+
         public void enforceCallFromPackage(String packageName) {
             mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
         }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 9b833f7..21398e3 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -588,7 +588,7 @@
 
     private void addCompatibilityModeRequestsLocked(@NonNull AutofillManagerServiceImpl service
             , int userId) {
-        mAutofillCompatState.reset();
+        mAutofillCompatState.reset(userId);
         final ArrayMap<String, Long> compatPackages =
                 service.getCompatibilityPackagesLocked();
         if (compatPackages == null || compatPackages.isEmpty()) {
@@ -721,6 +721,9 @@
     static final class AutofillCompatState {
         private final Object mLock = new Object();
 
+        /**
+         * Map of app->compat_state per user.
+         */
         @GuardedBy("mLock")
         private SparseArray<ArrayMap<String, PackageCompatState>> mUserSpecs;
 
@@ -787,11 +790,17 @@
             }
         }
 
-        void reset() {
+        void reset(int userId) {
             synchronized (mLock) {
                 if (mUserSpecs != null) {
-                    mUserSpecs.clear();
-                    mUserSpecs = null;
+                    mUserSpecs.delete(userId);
+                    final int newSize = mUserSpecs.size();
+                    if (newSize == 0) {
+                        if (sVerbose) Slog.v(TAG, "reseting mUserSpecs");
+                        mUserSpecs = null;
+                    } else {
+                        if (sVerbose) Slog.v(TAG, "mUserSpecs down to " + newSize);
+                    }
                 }
             }
         }
@@ -806,7 +815,7 @@
              for (int i = 0; i < mUserSpecs.size(); i++) {
                  final int user = mUserSpecs.keyAt(i);
                  pw.print(prefix); pw.print("User: "); pw.println(user);
-                 final ArrayMap<String,PackageCompatState> perUser = mUserSpecs.get(i);
+                 final ArrayMap<String, PackageCompatState> perUser = mUserSpecs.valueAt(i);
                  for (int j = 0; j < perUser.size(); j++) {
                      final String packageName = perUser.keyAt(j);
                      final PackageCompatState state = perUser.valueAt(j);
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 169f2a8..4c914c2 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -21,6 +21,7 @@
 import android.app.ActivityThread;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.AppOpsManagerInternal;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -172,6 +173,9 @@
     final AtomicFile mFile;
     final Handler mHandler;
 
+    private final AppOpsManagerInternalImpl mAppOpsManagerInternal
+            = new AppOpsManagerInternalImpl();
+
     boolean mWriteScheduled;
     boolean mFastWriteScheduled;
     final Runnable mWriteRunner = new Runnable() {
@@ -200,6 +204,8 @@
      */
     private final ArrayMap<IBinder, ClientRestrictionState> mOpUserRestrictions = new ArrayMap<>();
 
+    SparseIntArray mProfileOwners;
+
     /**
      * All times are in milliseconds. These constants are kept synchronized with the system
      * global Settings. Any access to this class or its fields should be done while
@@ -551,6 +557,7 @@
     public void publish(Context context) {
         mContext = context;
         ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
+        LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal);
     }
 
     public void systemReady() {
@@ -921,12 +928,27 @@
         }
     }
 
+    void enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid) {
+        if (callingPid == Process.myPid()) {
+            return;
+        }
+        final int callingUser = UserHandle.getUserId(callingUid);
+        synchronized (this) {
+            if (mProfileOwners != null && mProfileOwners.get(callingUser, -1) == callingUid) {
+                if (targetUid >= 0 && callingUser == UserHandle.getUserId(targetUid)) {
+                    // Profile owners are allowed to change modes but only for apps
+                    // within their user.
+                    return;
+                }
+            }
+        }
+        mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
+                Binder.getCallingPid(), Binder.getCallingUid(), null);
+    }
+
     @Override
     public void setUidMode(int code, int uid, int mode) {
-        if (Binder.getCallingPid() != Process.myPid()) {
-            mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
-                    Binder.getCallingPid(), Binder.getCallingUid(), null);
-        }
+        enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
         verifyIncomingOp(code);
         code = AppOpsManager.opToSwitch(code);
 
@@ -1029,10 +1051,7 @@
 
     @Override
     public void setMode(int code, int uid, String packageName, int mode) {
-        if (Binder.getCallingPid() != Process.myPid()) {
-            mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
-                    Binder.getCallingPid(), Binder.getCallingUid(), null);
-        }
+        enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
         verifyIncomingOp(code);
         ArraySet<ModeCallback> repCbs = null;
         code = AppOpsManager.opToSwitch(code);
@@ -1151,8 +1170,6 @@
     public void resetAllModes(int reqUserId, String reqPackageName) {
         final int callingPid = Binder.getCallingPid();
         final int callingUid = Binder.getCallingUid();
-        mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
-                callingPid, callingUid, null);
         reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId,
                 true, true, "resetAllModes", null);
 
@@ -1166,6 +1183,8 @@
             }
         }
 
+        enforceManageAppOpsModes(callingPid, callingUid, reqUid);
+
         HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks = null;
         synchronized (this) {
             boolean changed = false;
@@ -1428,10 +1447,9 @@
     @Override
     public void setAudioRestriction(int code, int usage, int uid, int mode,
             String[] exceptionPackages) {
+        enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
-        mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
-                Binder.getCallingPid(), Binder.getCallingUid(), null);
         synchronized (this) {
             SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
             if (usageRestrictions == null) {
@@ -2809,9 +2827,8 @@
                     return 0;
                 }
                 case "write-settings": {
-                    shell.mInternal.mContext.enforcePermission(
-                            android.Manifest.permission.MANAGE_APP_OPS_MODES,
-                            Binder.getCallingPid(), Binder.getCallingUid(), null);
+                    shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(),
+                            Binder.getCallingUid(), -1);
                     long token = Binder.clearCallingIdentity();
                     try {
                         synchronized (shell.mInternal) {
@@ -2825,9 +2842,8 @@
                     return 0;
                 }
                 case "read-settings": {
-                    shell.mInternal.mContext.enforcePermission(
-                            android.Manifest.permission.MANAGE_APP_OPS_MODES,
-                            Binder.getCallingPid(), Binder.getCallingUid(), null);
+                    shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(),
+                            Binder.getCallingUid(), -1);
                     long token = Binder.clearCallingIdentity();
                     try {
                         shell.mInternal.readState();
@@ -2989,6 +3005,17 @@
             final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
             final Date date = new Date();
             boolean needSep = false;
+            if (dumpOp < 0 && dumpMode < 0 && dumpPackage == null && mProfileOwners != null) {
+                pw.println("  Profile owners:");
+                for (int poi = 0; poi < mProfileOwners.size(); poi++) {
+                    pw.print("    User #");
+                    pw.print(mProfileOwners.keyAt(poi));
+                    pw.print(": ");
+                    UserHandle.formatUid(pw, mProfileOwners.valueAt(poi));
+                    pw.println();
+                }
+                pw.println();
+            }
             if (mOpModeWatchers.size() > 0) {
                 boolean printedHeader = false;
                 for (int i=0; i<mOpModeWatchers.size(); i++) {
@@ -3702,4 +3729,12 @@
             return true;
         }
     }
+
+    private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal {
+        @Override public void setDeviceAndProfileOwners(SparseIntArray owners) {
+            synchronized (AppOpsService.this) {
+                mProfileOwners = owners;
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 27eae57..698b6f7 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -800,6 +800,20 @@
         }
     }
 
+    /**
+     * See {@link DisplayWindowController#deferUpdateImeTarget()}
+     */
+    public void deferUpdateImeTarget() {
+        mWindowContainerController.deferUpdateImeTarget();
+    }
+
+    /**
+     * See {@link DisplayWindowController#deferUpdateImeTarget()}
+     */
+    public void continueUpdateImeTarget() {
+        mWindowContainerController.continueUpdateImeTarget();
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size());
         final String myPrefix = prefix + " ";
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 87d3696..c182502 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4595,46 +4595,58 @@
             }
         }
 
-        // Shift all activities with this task up to the top
-        // of the stack, keeping them in the same internal order.
-        insertTaskAtTop(tr, null);
+        try {
+            // Defer updating the IME target since the new IME target will try to get computed
+            // before updating all closing and opening apps, which can cause the ime target to
+            // get calculated incorrectly.
+            getDisplay().deferUpdateImeTarget();
 
-        // Don't refocus if invisible to current user
-        final ActivityRecord top = tr.getTopActivity();
-        if (top == null || !top.okToShowLocked()) {
-            if (top != null) {
-                mStackSupervisor.mRecentTasks.add(top.getTask());
+            // Shift all activities with this task up to the top
+            // of the stack, keeping them in the same internal order.
+            insertTaskAtTop(tr, null);
+
+            // Don't refocus if invisible to current user
+            final ActivityRecord top = tr.getTopActivity();
+            if (top == null || !top.okToShowLocked()) {
+                if (top != null) {
+                    mStackSupervisor.mRecentTasks.add(top.getTask());
+                }
+                ActivityOptions.abort(options);
+                return;
             }
-            ActivityOptions.abort(options);
-            return;
-        }
 
-        // Set focus to the top running activity of this stack.
-        final ActivityRecord r = topRunningActivityLocked();
-        mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
+            // Set focus to the top running activity of this stack.
+            final ActivityRecord r = topRunningActivityLocked();
+            mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
 
-        if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
-        if (noAnimation) {
-            mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
-            if (r != null) {
-                mStackSupervisor.mNoAnimActivities.add(r);
+            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
+            if (noAnimation) {
+                mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
+                if (r != null) {
+                    mStackSupervisor.mNoAnimActivities.add(r);
+                }
+                ActivityOptions.abort(options);
+            } else {
+                updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
             }
-            ActivityOptions.abort(options);
-        } else {
-            updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
-        }
-        // If a new task is moved to the front, then mark the existing top activity as supporting
-        // picture-in-picture while paused only if the task would not be considered an oerlay on top
-        // of the current activity (eg. not fullscreen, or the assistant)
-        if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */,
-                options)) {
-            topActivity.supportsEnterPipOnTaskSwitch = true;
-        }
+            // If a new task is moved to the front, then mark the existing top activity as
+            // supporting
 
-        mStackSupervisor.resumeFocusedStackTopActivityLocked();
-        EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
+            // picture-in-picture while paused only if the task would not be considered an oerlay
+            // on top
+            // of the current activity (eg. not fullscreen, or the assistant)
+            if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */,
+                    options)) {
+                topActivity.supportsEnterPipOnTaskSwitch = true;
+            }
 
-        mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
+            mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
+
+            mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
+        } finally {
+            getDisplay().continueUpdateImeTarget();
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 8c3ff34..ff97db8 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -34,7 +34,6 @@
 
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
-import android.Manifest;
 import android.app.ActivityOptions;
 import android.app.KeyguardManager;
 import android.app.admin.DevicePolicyManagerInternal;
@@ -233,31 +232,6 @@
         return true;
     }
 
-    private Intent createSuspendedAppInterceptIntent(String suspendedPackage,
-            String suspendingPackage, String dialogMessage, int userId) {
-        final Intent interceptIntent = new Intent(mServiceContext, SuspendedAppActivity.class)
-                .putExtra(SuspendedAppActivity.EXTRA_SUSPENDED_PACKAGE, suspendedPackage)
-                .putExtra(SuspendedAppActivity.EXTRA_DIALOG_MESSAGE, dialogMessage)
-                .putExtra(SuspendedAppActivity.EXTRA_SUSPENDING_PACKAGE, suspendingPackage)
-                .putExtra(Intent.EXTRA_USER_ID, userId)
-                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-
-        final Intent moreDetailsIntent = new Intent(Intent.ACTION_SHOW_SUSPENDED_APP_DETAILS)
-                .setPackage(suspendingPackage);
-        final String requiredPermission = Manifest.permission.SEND_SHOW_SUSPENDED_APP_DETAILS;
-        final ResolveInfo resolvedInfo = mSupervisor.resolveIntent(moreDetailsIntent, null, userId,
-                0, mRealCallingUid);
-        if (resolvedInfo != null && resolvedInfo.activityInfo != null
-                && requiredPermission.equals(resolvedInfo.activityInfo.permission)) {
-            moreDetailsIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, suspendedPackage)
-                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            interceptIntent.putExtra(SuspendedAppActivity.EXTRA_MORE_DETAILS_INTENT,
-                    moreDetailsIntent);
-        }
-        return interceptIntent;
-    }
-
     private boolean interceptSuspendedPackageIfNeeded() {
         // Do not intercept if the package is not suspended
         if (mAInfo == null || mAInfo.applicationInfo == null ||
@@ -274,8 +248,8 @@
             return interceptSuspendedByAdminPackage();
         }
         final String dialogMessage = pmi.getSuspendedDialogMessage(suspendedPackage, mUserId);
-        mIntent = createSuspendedAppInterceptIntent(suspendedPackage, suspendingPackage,
-                dialogMessage, mUserId);
+        mIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(suspendedPackage,
+                suspendingPackage, dialogMessage, mUserId);
         mCallingPid = mRealCallingPid;
         mCallingUid = mRealCallingUid;
         mResolvedType = null;
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 0425844..ce25a9f 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -330,7 +330,11 @@
     }
 
     public boolean setBrightnessConfiguration(BrightnessConfiguration configuration) {
-        return mBrightnessMapper.setBrightnessConfiguration(configuration);
+        if (mBrightnessMapper.setBrightnessConfiguration(configuration)) {
+            resetShortTermModel();
+            return true;
+        }
+        return false;
     }
 
     public void dump(PrintWriter pw) {
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index f7439b9..5935829 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -341,7 +341,7 @@
         // Extreme edge cases: use a simpler heuristic, as proper gamma correction around the edges
         // affects the curve rather drastically.
         if (currentBrightness <= 0.1f || currentBrightness >= 0.9f) {
-            adjustment = (desiredBrightness - currentBrightness) * 2;
+            adjustment = (desiredBrightness - currentBrightness);
         // Edge case: darkest adjustment possible.
         } else if (desiredBrightness == 0) {
             adjustment = -1;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c0dc750..f3423c6 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -390,6 +390,11 @@
      */
     int mLayoutSeq = 0;
 
+    /**
+     * Specifies the count to determine whether to defer updating the IME target until ready.
+     */
+    private int mDeferUpdateImeTargetCount;
+
     /** Temporary float array to retrieve 3x3 matrix values. */
     private final float[] mTmpFloats = new float[9];
 
@@ -2454,6 +2459,12 @@
             return null;
         }
 
+        final WindowState curTarget = mService.mInputMethodTarget;
+        if (!canUpdateImeTarget()) {
+            if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
+            return curTarget;
+        }
+
         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
         // same display. Or even when the current IME/target are not on the same screen as the next
         // IME/target. For now only look for input windows on the main screen.
@@ -2477,16 +2488,13 @@
         if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
                 "Proposed new IME target: " + target);
 
-        // Now, a special case -- if the last target's window is in the process of exiting, and is
-        // above the new target, keep on the last target to avoid flicker. Consider for example a
-        // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it
-        // until it is completely gone so it doesn't drop behind the dialog or its full-screen
-        // scrim.
-        final WindowState curTarget = mService.mInputMethodTarget;
+        // Now, a special case -- if the last target's window is in the process of exiting, and the
+        // new target is home, keep on the last target to avoid flicker. Home is a special case
+        // since its above other stacks in the ordering list, but layed out below the others.
         if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing()
-                && (target == null
-                    || curTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer)) {
-            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
+                && (target == null || target.isActivityTypeHome())) {
+            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "New target is home while current target is"
+                    + "closing, not changing");
             return curTarget;
         }
 
@@ -3958,4 +3966,33 @@
     void assignStackOrdering() {
         mTaskStackContainers.assignStackOrdering(getPendingTransaction());
     }
+
+    /**
+     * Increment the deferral count to determine whether to update the IME target.
+     */
+    void deferUpdateImeTarget() {
+        mDeferUpdateImeTargetCount++;
+    }
+
+    /**
+     * Decrement the deferral count to determine whether to update the IME target. If the count
+     * reaches 0, a new ime target will get computed.
+     */
+    void continueUpdateImeTarget() {
+        if (mDeferUpdateImeTargetCount == 0) {
+            return;
+        }
+
+        mDeferUpdateImeTargetCount--;
+        if (mDeferUpdateImeTargetCount == 0) {
+            computeImeTarget(true /* updateImeTarget */);
+        }
+    }
+
+    /**
+     * @return Whether a new IME target should be computed.
+     */
+    private boolean canUpdateImeTarget() {
+        return mDeferUpdateImeTargetCount == 0;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index ba8ec69..a1639c2 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -94,6 +94,31 @@
         }
     }
 
+    /**
+     * Starts deferring the ability to update the IME target. This is needed when a call will
+     * attempt to update the IME target before all information about the Windows have been updated.
+     */
+    public void deferUpdateImeTarget() {
+        synchronized (mWindowMap) {
+            final DisplayContent dc = mRoot.getDisplayContent(mDisplayId);
+            if (dc != null) {
+                dc.deferUpdateImeTarget();
+            }
+        }
+    }
+
+    /**
+     * Resumes updating the IME target after deferring. See {@link #deferUpdateImeTarget()}
+     */
+    public void continueUpdateImeTarget() {
+        synchronized (mWindowMap) {
+            final DisplayContent dc = mRoot.getDisplayContent(mDisplayId);
+            if (dc != null) {
+                dc.continueUpdateImeTarget();
+            }
+        }
+    }
+
     @Override
     public String toString() {
         return "{DisplayWindowController displayId=" + mDisplayId + "}";
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 93d6ae8..16399008 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2697,12 +2697,7 @@
                     + " Callers=" + Debug.getCallers(5));
             if (mAppTransition.isTransitionSet()) {
                 mAppTransition.setReady();
-                final long origId = Binder.clearCallingIdentity();
-                try {
-                    mWindowPlacerLocked.performSurfacePlacement();
-                } finally {
-                    Binder.restoreCallingIdentity(origId);
-                }
+                mWindowPlacerLocked.requestTraversal();
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c710c97..91c449b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2726,7 +2726,8 @@
     }
 
     boolean isClosing() {
-        return mAnimatingExit || (mService.mClosingApps.contains(mAppToken));
+        return mAnimatingExit || (mAppToken != null && mAppToken.isAnimating()
+                && mAppToken.hiddenRequested);
     }
 
     void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 729dba5..c370a00 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3351,6 +3351,7 @@
             case SystemService.PHASE_LOCK_SETTINGS_READY:
                 onLockSettingsReady();
                 loadAdminDataAsync();
+                mOwners.systemReady();
                 break;
             case SystemService.PHASE_BOOT_COMPLETED:
                 ensureDeviceOwnerUserStarted(); // TODO Consider better place to do this.
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 8366114..632f0aa 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -17,11 +17,14 @@
 package com.android.server.devicepolicy;
 
 import android.annotation.Nullable;
+import android.app.AppOpsManagerInternal;
 import android.app.admin.SystemUpdateInfo;
 import android.app.admin.SystemUpdatePolicy;
 import android.content.ComponentName;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.UserInfo;
+import android.os.Binder;
 import android.os.Environment;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -32,10 +35,12 @@
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseIntArray;
 import android.util.Xml;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.server.LocalServices;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -99,6 +104,8 @@
     private final UserManagerInternal mUserManagerInternal;
     private final PackageManagerInternal mPackageManagerInternal;
 
+    private boolean mSystemReady;
+
     // Internal state for the device owner package.
     private OwnerInfo mDeviceOwner;
 
@@ -179,6 +186,7 @@
                         getDeviceOwnerUserId()));
             }
             pushToPackageManagerLocked();
+            pushToAppOpsLocked();
         }
     }
 
@@ -262,6 +270,7 @@
 
             mUserManagerInternal.setDeviceManaged(true);
             pushToPackageManagerLocked();
+            pushToAppOpsLocked();
         }
     }
 
@@ -272,6 +281,7 @@
 
             mUserManagerInternal.setDeviceManaged(false);
             pushToPackageManagerLocked();
+            pushToAppOpsLocked();
         }
     }
 
@@ -283,6 +293,7 @@
                     /* remoteBugreportHash =*/ null));
             mUserManagerInternal.setUserManaged(userId, true);
             pushToPackageManagerLocked();
+            pushToAppOpsLocked();
         }
     }
 
@@ -291,6 +302,7 @@
             mProfileOwners.remove(userId);
             mUserManagerInternal.setUserManaged(userId, false);
             pushToPackageManagerLocked();
+            pushToAppOpsLocked();
         }
     }
 
@@ -302,6 +314,7 @@
                     ownerInfo.remoteBugreportHash);
             mProfileOwners.put(userId, newOwnerInfo);
             pushToPackageManagerLocked();
+            pushToAppOpsLocked();
         }
     }
 
@@ -313,6 +326,7 @@
                     mDeviceOwner.userRestrictionsMigrated, mDeviceOwner.remoteBugreportUri,
                     mDeviceOwner.remoteBugreportHash);
             pushToPackageManagerLocked();
+            pushToAppOpsLocked();
         }
     }
 
@@ -581,6 +595,48 @@
         }
     }
 
+    void pushToAppOpsLocked() {
+        if (!mSystemReady) {
+            return;
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            final SparseIntArray owners = new SparseIntArray();
+            if (mDeviceOwner != null) {
+                final int uid = mPackageManagerInternal.getPackageUid(mDeviceOwner.packageName,
+                        PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES,
+                        mDeviceOwnerUserId);
+                if (uid >= 0) {
+                    owners.put(mDeviceOwnerUserId, uid);
+                }
+            }
+            if (mProfileOwners != null) {
+                for (int poi = mProfileOwners.size() - 1; poi >= 0; poi--) {
+                    final int uid = mPackageManagerInternal.getPackageUid(
+                            mProfileOwners.valueAt(poi).packageName,
+                            PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES,
+                            mProfileOwners.keyAt(poi));
+                    if (uid >= 0) {
+                        owners.put(mProfileOwners.keyAt(poi), uid);
+                    }
+                }
+            }
+            AppOpsManagerInternal appops = LocalServices.getService(AppOpsManagerInternal.class);
+            if (appops != null) {
+                appops.setDeviceAndProfileOwners(owners.size() > 0 ? owners : null);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    public void systemReady() {
+        synchronized (mLock) {
+            mSystemReady = true;
+            pushToAppOpsLocked();
+        }
+    }
+
     private abstract static class FileReadWriter {
         private final File mFile;
 
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 83a125d..dc55179b 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -18,8 +18,12 @@
 
 import static android.content.pm.PackageManager.GET_SERVICES;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+import static android.content.pm.PackageManager.MATCH_INSTANT;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SHELL_UID;
 
 import android.annotation.NonNull;
+import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.ComponentName;
@@ -36,6 +40,8 @@
 import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.print.IPrintDocumentAdapter;
@@ -122,6 +128,13 @@
         }
 
         @Override
+        public void onShellCommand(FileDescriptor in, FileDescriptor out,
+                FileDescriptor err, String[] args, ShellCallback callback,
+                ResultReceiver resultReceiver) {
+            new PrintShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver);
+        }
+
+        @Override
         public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
                 PrintAttributes attributes, String packageName, int appId, int userId) {
             adapter = Preconditions.checkNotNull(adapter);
@@ -717,6 +730,46 @@
             }
         }
 
+        @Override
+        public boolean getBindInstantServiceAllowed(@UserIdInt int userId) {
+            int callingUid = Binder.getCallingUid();
+            if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
+                throw new SecurityException("Can only be called by uid " + SHELL_UID
+                        + " or " + ROOT_UID);
+            }
+
+            final UserState userState;
+            synchronized (mLock) {
+                userState = getOrCreateUserStateLocked(userId, false);
+            }
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                return userState.getBindInstantServiceAllowed();
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void setBindInstantServiceAllowed(@UserIdInt int userId, boolean allowed) {
+            int callingUid = Binder.getCallingUid();
+            if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
+                throw new SecurityException("Can only be called by uid " + SHELL_UID
+                        + " or " + ROOT_UID);
+            }
+
+            final UserState userState;
+            synchronized (mLock) {
+                userState = getOrCreateUserStateLocked(userId, false);
+            }
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                userState.setBindInstantServiceAllowed(allowed);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
         private boolean isPrintingEnabled() {
             return !mUserManager.hasUserRestriction(UserManager.DISALLOW_PRINTING,
                     Binder.getCallingUserHandle());
@@ -773,7 +826,7 @@
 
                     List<ResolveInfo> installedServices = mContext.getPackageManager()
                             .queryIntentServicesAsUser(intent,
-                                    GET_SERVICES | MATCH_DEBUG_TRIAGED_MISSING,
+                                    GET_SERVICES | MATCH_DEBUG_TRIAGED_MISSING | MATCH_INSTANT,
                                     getChangingUserId());
 
                     return installedServices != null && !installedServices.isEmpty();
@@ -988,7 +1041,7 @@
                 return appId;
             }
             final int callingAppId = UserHandle.getAppId(callingUid);
-            if (appId == callingAppId || callingAppId == Process.SHELL_UID
+            if (appId == callingAppId || callingAppId == SHELL_UID
                     || callingAppId == Process.SYSTEM_UID) {
                 return appId;
             }
diff --git a/services/print/java/com/android/server/print/PrintShellCommand.java b/services/print/java/com/android/server/print/PrintShellCommand.java
new file mode 100644
index 0000000..11642e5
--- /dev/null
+++ b/services/print/java/com/android/server/print/PrintShellCommand.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 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.server.print;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+import android.print.IPrintManager;
+
+import java.io.PrintWriter;
+
+/**
+ * Shell command implementation for the print manager service
+ */
+final class PrintShellCommand extends ShellCommand {
+    final @NonNull IPrintManager mService;
+
+    PrintShellCommand(@NonNull IPrintManager service) {
+        mService = service;
+    }
+
+    @Override
+    public int onCommand(@Nullable String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
+        switch (cmd) {
+            case "get-bind-instant-service-allowed": {
+                return runGetBindInstantServiceAllowed();
+            }
+            case "set-bind-instant-service-allowed": {
+                return runSetBindInstantServiceAllowed();
+            }
+        }
+        return -1;
+    }
+
+    private int runGetBindInstantServiceAllowed() {
+        final Integer userId = parseUserId();
+        if (userId == null) {
+            return -1;
+        }
+        try {
+            getOutPrintWriter().println(
+                    Boolean.toString(mService.getBindInstantServiceAllowed(userId)));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return 0;
+    }
+
+    private int runSetBindInstantServiceAllowed() {
+        final Integer userId = parseUserId();
+        if (userId == null) {
+            return -1;
+        }
+        final String allowed = getNextArgRequired();
+        if (allowed == null) {
+            getErrPrintWriter().println("Error: no true/false specified");
+            return -1;
+        }
+        try {
+            mService.setBindInstantServiceAllowed(userId, Boolean.parseBoolean(allowed));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return 0;
+    }
+
+    private @Nullable Integer parseUserId() {
+        final String option = getNextOption();
+        if (option != null) {
+            if (option.equals("--user")) {
+                return UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                getErrPrintWriter().println("Unknown option: " + option);
+                return null;
+            }
+        }
+        return UserHandle.USER_SYSTEM;
+    }
+
+    @Override
+    public void onHelp() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("Print service commands:");
+        pw.println("  help");
+        pw.println("    Print this help text.");
+        pw.println("  set-bind-instant-service-allowed [--user <USER_ID>] true|false ");
+        pw.println("    Set whether binding to print services provided by instant apps is "
+                + "allowed.");
+        pw.println("  get-bind-instant-service-allowed [--user <USER_ID>]");
+        pw.println("    Get whether binding to print services provided by instant apps is "
+                + "allowed.");
+    }
+}
diff --git a/services/print/java/com/android/server/print/RemotePrintService.java b/services/print/java/com/android/server/print/RemotePrintService.java
index d4cbe7b..4f0d6f1 100644
--- a/services/print/java/com/android/server/print/RemotePrintService.java
+++ b/services/print/java/com/android/server/print/RemotePrintService.java
@@ -571,8 +571,8 @@
         mBinding = true;
 
         boolean wasBound = mContext.bindServiceAsUser(mIntent, mServiceConnection,
-                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
-                new UserHandle(mUserId));
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
+                        | Context.BIND_ALLOW_INSTANT, new UserHandle(mUserId));
 
         if (!wasBound) {
             if (DEBUG) {
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index 62185d7..4fbc14c 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.GET_META_DATA;
 import static android.content.pm.PackageManager.GET_SERVICES;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+import static android.content.pm.PackageManager.MATCH_INSTANT;
 
 import static com.android.internal.print.DumpUtils.writePrintJobInfo;
 import static com.android.internal.print.DumpUtils.writePrinterId;
@@ -155,6 +156,11 @@
      */
     private RemotePrintServiceRecommendationService mPrintServiceRecommendationsService;
 
+    /**
+     * Can services from instant apps be bound? (usually disabled, only used by testing)
+     */
+    private boolean mIsInstantServiceAllowed;
+
     public UserState(Context context, int userId, Object lock, boolean lowPriority) {
         mContext = context;
         mUserId = userId;
@@ -872,9 +878,14 @@
     private void readInstalledPrintServicesLocked() {
         Set<PrintServiceInfo> tempPrintServices = new HashSet<PrintServiceInfo>();
 
+        int queryIntentFlags = GET_SERVICES | GET_META_DATA | MATCH_DEBUG_TRIAGED_MISSING;
+
+        if (mIsInstantServiceAllowed) {
+            queryIntentFlags |= MATCH_INSTANT;
+        }
+
         List<ResolveInfo> installedServices = mContext.getPackageManager()
-                .queryIntentServicesAsUser(mQueryIntent,
-                        GET_SERVICES | GET_META_DATA | MATCH_DEBUG_TRIAGED_MISSING, mUserId);
+                .queryIntentServicesAsUser(mQueryIntent, queryIntentFlags, mUserId);
 
         final int installedCount = installedServices.size();
         for (int i = 0, count = installedCount; i < count; i++) {
@@ -1185,6 +1196,18 @@
         }
     }
 
+    public boolean getBindInstantServiceAllowed() {
+        return mIsInstantServiceAllowed;
+    }
+
+    public void setBindInstantServiceAllowed(boolean allowed) {
+        synchronized (mLock) {
+            mIsInstantServiceAllowed = allowed;
+
+            updateIfNeededLocked();
+        }
+    }
+
     private abstract class PrintJobStateChangeListenerRecord implements DeathRecipient {
         @NonNull final IPrintJobStateChangeListener listener;
         final int appId;
diff --git a/telecomm/java/android/telecom/CallAudioState.java b/telecomm/java/android/telecom/CallAudioState.java
index 4b827d2..e33ba7e 100644
--- a/telecomm/java/android/telecom/CallAudioState.java
+++ b/telecomm/java/android/telecom/CallAudioState.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.bluetooth.BluetoothDevice;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -100,6 +101,7 @@
     }
 
     /** @hide */
+    @TestApi
     public CallAudioState(boolean isMuted, @CallAudioRoute int route,
             @CallAudioRoute int supportedRouteMask,
             @Nullable BluetoothDevice activeBluetoothDevice,
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5a77a9f..487490c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3443,14 +3443,13 @@
      * to the TelephonyManager.
      * When the filter is enabled, {@link
      * VisualVoicemailService#onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)} will be
-     * called when a SMS matching the settings is received. The caller should have
-     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} and implement a
-     * VisualVoicemailService.
-     *
-     * <p>Requires Permission:
-     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * called when a SMS matching the settings is received. Caller must be the default dialer,
+     * system dialer, or carrier visual voicemail app.
      *
      * @param settings The settings for the filter, or {@code null} to disable the filter.
+     *
+     * @see {@link TelecomManager#getDefaultDialerPackage()}
+     * @see {@link CarrierConfigManager#KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY}
      */
     public void setVisualVoicemailSmsFilterSettings(VisualVoicemailSmsFilterSettings settings) {
         if (settings == null) {
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 4e202df..3689a8f 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -421,7 +421,7 @@
                 printf(" NULL),\n");
                 break;
             case SECTION_DUMPSYS:
-                printf("    new DumpsysSection(%d, \"%s\",", field->number(),
+                printf("    new DumpsysSection(%d, %s,", field->number(),
                        s.userdebug_and_eng_only() ? "true" : "false");
                 splitAndPrint(s.args());
                 printf(" NULL),\n");