Merge changes from topic 'multinetwork_vndk' into oc-dev

* changes:
  Allow vendor code to link to libandroid_net.
  Move libandroid_net from Android.mk to Android.bp.
diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp
index c13d318..524db14 100644
--- a/cmds/idmap/create.cpp
+++ b/cmds/idmap/create.cpp
@@ -221,3 +221,9 @@
     return create_and_write_idmap(target_apk_path, overlay_apk_path, fd, true) == 0 ?
         EXIT_SUCCESS : EXIT_FAILURE;
 }
+
+int idmap_verify_fd(const char *target_apk_path, const char *overlay_apk_path, int fd)
+{
+    return !is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd) ?
+            EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/cmds/idmap/idmap.cpp b/cmds/idmap/idmap.cpp
index 3a237ff..8f86ed8 100644
--- a/cmds/idmap/idmap.cpp
+++ b/cmds/idmap/idmap.cpp
@@ -16,6 +16,7 @@
       idmap --scan target-package-name-to-look-for path-to-target-apk dir-to-hold-idmaps \\\
                    dir-to-scan [additional-dir-to-scan [additional-dir-to-scan [...]]]\n\
       idmap --inspect idmap \n\
+      idmap --verify target overlay fd \n\
 \n\
 DESCRIPTION \n\
       Idmap files play an integral part in the runtime resource overlay framework. An idmap \n\
@@ -57,6 +58,9 @@
       --inspect: decode the binary format of 'idmap' (path) and display the contents in a \n\
                  debug-friendly format. \n\
 \n\
+      --verify: verify if idmap corresponding to file descriptor 'fd' (integer) is made from \n\
+                target package 'target' (path to apk) and overlay package 'overlay'. \n\
+\n\
 EXAMPLES \n\
       Create an idmap file: \n\
 \n\
@@ -167,6 +171,29 @@
         return idmap_create_path(target_apk_path, overlay_apk_path, idmap_path);
     }
 
+    int maybe_verify_fd(const char *target_apk_path, const char *overlay_apk_path,
+            const char *idmap_str)
+    {
+        char *endptr;
+        int idmap_fd = strtol(idmap_str, &endptr, 10);
+        if (*endptr != '\0') {
+            fprintf(stderr, "error: failed to parse file descriptor argument %s\n", idmap_str);
+            return -1;
+        }
+
+        if (!verify_file_readable(target_apk_path)) {
+            ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno));
+            return -1;
+        }
+
+        if (!verify_file_readable(overlay_apk_path)) {
+            ALOGD("error: failed to read apk %s: %s\n", overlay_apk_path, strerror(errno));
+            return -1;
+        }
+
+        return idmap_verify_fd(target_apk_path, overlay_apk_path, idmap_fd);
+    }
+
     int maybe_scan(const char *target_package_name, const char *target_apk_path,
             const char *idmap_dir, const android::Vector<const char *> *overlay_dirs)
     {
@@ -235,6 +262,10 @@
         return maybe_create_path(argv[2], argv[3], argv[4]);
     }
 
+    if (argc == 5 && !strcmp(argv[1], "--verify")) {
+        return maybe_verify_fd(argv[2], argv[3], argv[4]);
+    }
+
     if (argc >= 6 && !strcmp(argv[1], "--scan")) {
         android::Vector<const char *> v;
         for (int i = 5; i < argc; i++) {
diff --git a/cmds/idmap/idmap.h b/cmds/idmap/idmap.h
index 8d4210b..5962108 100644
--- a/cmds/idmap/idmap.h
+++ b/cmds/idmap/idmap.h
@@ -25,6 +25,8 @@
 
 int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, int fd);
 
+int idmap_verify_fd(const char *target_apk_path, const char *overlay_apk_path, int fd);
+
 // Regarding target_package_name: the idmap_scan implementation should
 // be able to extract this from the manifest in target_apk_path,
 // simplifying the external API.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 50593f2..09464eec4 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -57,6 +57,7 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.LayoutAnimationController;
 import android.view.animation.Transformation;
+
 import com.android.internal.R;
 
 import java.util.ArrayList;
@@ -7715,14 +7716,15 @@
                         mMarginFlags |= RIGHT_MARGIN_UNDEFINED_MASK;
                         rightMargin = DEFAULT_MARGIN_RESOLVED;
                     }
-                    startMargin = a.getDimensionPixelSize(
-                            R.styleable.ViewGroup_MarginLayout_layout_marginStart,
-                            DEFAULT_MARGIN_RELATIVE);
-                    endMargin = a.getDimensionPixelSize(
-                            R.styleable.ViewGroup_MarginLayout_layout_marginEnd,
-                            DEFAULT_MARGIN_RELATIVE);
                 }
 
+                startMargin = a.getDimensionPixelSize(
+                        R.styleable.ViewGroup_MarginLayout_layout_marginStart,
+                        DEFAULT_MARGIN_RELATIVE);
+                endMargin = a.getDimensionPixelSize(
+                        R.styleable.ViewGroup_MarginLayout_layout_marginEnd,
+                        DEFAULT_MARGIN_RELATIVE);
+
                 if (verticalMargin >= 0) {
                     topMargin = verticalMargin;
                     bottomMargin = verticalMargin;
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index cfe25b3..79bb109 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2290,8 +2290,9 @@
 
         <!-- Sets the padding, in pixels, of all four edges. Padding is defined as
              space between the edges of the view and the view's content. This value will take
-             precedence over any of the edge-specific values, including
-             paddingHorizontal and paddingVertical, if set. A view's size
+             precedence over any of the edge-specific values (paddingLeft, paddingTop,
+             paddingRight, paddingBottom, paddingHorizontal and paddingVertical), but will
+             not override paddingStart or paddingEnd, if set. A view's size
              will include its padding. If a {@link android.R.attr#background}
              is provided, the padding will initially be set to that (0 if the
              drawable does not have padding). Explicitly setting a padding value
@@ -2299,7 +2300,7 @@
         <attr name="padding" format="dimension" />
         <!-- Sets the padding, in pixels, of the left and right edges; see
              {@link android.R.attr#padding}. This value will take precedence over
-             paddingLeft, paddingRight, paddingStart, and paddingEnd, if set. -->
+             paddingLeft and paddingRight, but not paddingStart or paddingEnd (if set). -->
         <attr name="paddingHorizontal" format="dimension" />
         <!-- Sets the padding, in pixels, of the top and bottom edges; see
              {@link android.R.attr#padding}. This value will take precedence over
@@ -3203,11 +3204,10 @@
         <attr name="layout_marginEnd" format="dimension"  />
         <!--  Specifies extra space on the left and right sides of this view.
               Specifying layout_marginHorizontal is equivalent to specifying
-              either layout_marginLeft and layout_marginRight or
-              layout_marginStart and layout_marginEnd with that same value.
-              If both layout_marginHorizontal and any of layout_marginLeft,
-              layout_marginRight, layout_marginStart, and layout_marginEnd are
-              also specified, the layout_marginHorizontal value will take precedence over the
+              layout_marginLeft and layout_marginRight.
+              If both layout_marginHorizontal and either/both of layout_marginLeft
+              and layout_marginRight are also specified, the layout_marginHorizontal
+              value will take precedence over the
               edge-specific values. Also, layout_margin will always take precedence over
               any of these values, including layout_marginHorizontal.
               This space is outside this view's bounds.
@@ -3216,7 +3216,7 @@
         <!--  Specifies extra space on the top and bottom sides of this view.
               Specifying layout_marginVertical is equivalent to specifying
               layout_marginTop and layout_marginBottom with that same value.
-              If both layout_marginVertical and either/both layout_marginTop and
+              If both layout_marginVertical and either/both of layout_marginTop and
               layout_marginBottom are also specified, the layout_marginVertical value
               will take precedence over the edge-specific values.
               Also, layout_margin will always take precedence over
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index ab10e97..8616d58 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -84,7 +84,7 @@
     /**
      * Launcher icons design guideline
      */
-    private static final float SAFEZONE_SCALE = 72f/66f;
+    private static final float SAFEZONE_SCALE = 66f/72f;
 
     /**
      * All four sides of the layers are padded with extra inset so as to provide
@@ -676,12 +676,7 @@
 
     @Override
     public int getAlpha() {
-        final Drawable dr = getFirstNonNullDrawable();
-        if (dr != null) {
-            return dr.getAlpha();
-        } else {
-            return super.getAlpha();
-        }
+        return PixelFormat.TRANSLUCENT;
     }
 
     @Override
@@ -719,17 +714,6 @@
         }
     }
 
-    private Drawable getFirstNonNullDrawable() {
-        final ChildDrawable[] array = mLayerState.mChildren;
-        for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
-            final Drawable dr = array[i].mDrawable;
-            if (dr != null) {
-                return dr;
-            }
-        }
-        return null;
-    }
-
     public void setOpacity(int opacity) {
         mLayerState.mOpacityOverride = opacity;
     }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
index 4a5a681..d571243 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
@@ -62,6 +62,9 @@
 
     View getHeader();
 
+    default void setHasNotifications(boolean hasNotifications) {
+    }
+
     @ProvidesInterface(version = HeightListener.VERSION)
     public interface HeightListener {
         public static final int VERSION = 1;
diff --git a/packages/SystemUI/res/layout/qs_footer.xml b/packages/SystemUI/res/layout/qs_footer.xml
index c92c811..577be2f 100644
--- a/packages/SystemUI/res/layout/qs_footer.xml
+++ b/packages/SystemUI/res/layout/qs_footer.xml
@@ -27,20 +27,22 @@
     android:clipChildren="false"
     android:clipToPadding="false"
     android:paddingTop="0dp"
-    android:paddingEnd="8dp"
-    android:paddingStart="16dp"
     android:gravity="center_vertical"
     android:orientation="horizontal">
 
     <include
         android:id="@+id/date_time_alarm_group"
         layout="@layout/status_bar_alarm_group"
+        android:layout_marginStart="16dp"
+        android:layout_marginEnd="8dp"
         android:layout_width="wrap_content"
         android:layout_height="match_parent" />
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginEnd="8dp"
         android:gravity="end">
 
         <com.android.systemui.statusbar.phone.MultiUserSwitch
@@ -113,4 +115,9 @@
             android:padding="14dp" />
     </LinearLayout>
 
+    <include layout="@layout/qs_divider"
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:layout_gravity="bottom" />
+
 </com.android.systemui.qs.QSFooter>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 2502d41..005e955 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -41,8 +41,8 @@
         android:clipChildren="false"
         android:clipToPadding="false"
         android:gravity="center"
-        android:paddingStart="8dp"
-        android:paddingEnd="8dp"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
         android:orientation="horizontal">
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 189c04c..149b5cc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -17,14 +17,11 @@
 package com.android.systemui.qs;
 
 import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
 import android.graphics.Point;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.FrameLayout;
 
-import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.qs.customize.QSCustomizer;
 
@@ -44,6 +41,7 @@
     private QSFooter mQSFooter;
     private int mGutterHeight;
     private View mBackground;
+    private float mFullElevation;
 
     public QSContainerImpl(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -59,6 +57,7 @@
         mQSFooter = findViewById(R.id.qs_footer);
         mBackground = findViewById(R.id.qs_background);
         mGutterHeight = getContext().getResources().getDimensionPixelSize(R.dimen.qs_gutter_height);
+        mFullElevation = mQSPanel.getElevation();
     }
 
     @Override
@@ -85,7 +84,7 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        updateBottom();
+        updateExpansion();
     }
 
     /**
@@ -96,27 +95,47 @@
      */
     public void setHeightOverride(int heightOverride) {
         mHeightOverride = heightOverride;
-        updateBottom();
+        updateExpansion();
     }
 
-    public void updateBottom() {
+    public void updateExpansion() {
         int height = calculateContainerHeight();
-        setBottom(getTop() + height + mGutterHeight);
+        int gutterHeight = Math.round(mQsExpansion * mGutterHeight);
+        setBottom(getTop() + height + gutterHeight);
         mQSDetail.setBottom(getTop() + height);
-        mBackground.setBottom(mQSDetail.getBottom());
+        mBackground.setBottom(getTop() + height);
         // Pin QS Footer to the bottom of the panel.
         mQSFooter.setTranslationY(height - mQSFooter.getHeight());
+
+        float elevation = mQsExpansion * mFullElevation;
+        mQSDetail.setElevation(elevation);
+        mBackground.setElevation(elevation);
+        mQSFooter.setElevation(elevation);
+        mQSPanel.setElevation(elevation);
     }
 
     protected int calculateContainerHeight() {
         int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
         return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
-                : (int) (mQsExpansion * (heightOverride - mHeader.getHeight()))
+                : Math.round(mQsExpansion * (heightOverride - mHeader.getHeight()))
                 + mHeader.getHeight();
     }
 
     public void setExpansion(float expansion) {
         mQsExpansion = expansion;
-        updateBottom();
+        updateExpansion();
+    }
+
+    public void setGutterEnabled(boolean gutterEnabled) {
+        if (gutterEnabled == (mGutterHeight != 0)) {
+            return;
+        }
+        if (gutterEnabled) {
+            mGutterHeight = getContext().getResources().getDimensionPixelSize(
+                    R.dimen.qs_gutter_height);
+        } else {
+            mGutterHeight = 0;
+        }
+        updateExpansion();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 063f5df..87b042d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -235,6 +235,7 @@
         }
 
         TouchAnimator.Builder animatorBuilder = new TouchAnimator.Builder();
+        animatorBuilder.setStartDelay(QSAnimator.EXPANDED_TILE_DELAY);
 
         if (mShowEditIcon) {
             animatorBuilder.addFloat(mEdit, "alpha", 0, 1);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 3f090f8..61fd624 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -34,7 +34,6 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.R.id;
-import com.android.systemui.R.style;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
@@ -130,6 +129,11 @@
         return mHeader;
     }
 
+    @Override
+    public void setHasNotifications(boolean hasNotifications) {
+        mContainer.setGutterEnabled(hasNotifications);
+    }
+
     public void setPanelView(HeightListener panelView) {
         mPanelView = panelView;
     }
@@ -307,7 +311,7 @@
 
     public void notifyCustomizeChanged() {
         // The customize state changed, so our height changed.
-        mContainer.updateBottom();
+        mContainer.updateExpansion();
         mQSPanel.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
         mHeader.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
         mFooter.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
@@ -340,7 +344,7 @@
     }
 
     public int getQsMinExpansionHeight() {
-        return mHeader.getHeight() + mGutterHeight;
+        return mHeader.getHeight();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InflationTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/InflationTask.java
new file mode 100644
index 0000000..22fd37c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/InflationTask.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 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.statusbar;
+
+/**
+ * An interface for running inflation tasks that allows aborting and superseding existing
+ * operations.
+ */
+public interface InflationTask {
+    void abort();
+
+    /**
+     * Supersedes an existing task. i.e another task was superceeded by this.
+     *
+     * @param task the task that was previously running
+     */
+    default void supersedeTask(InflationTask task) {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index f8bad05..1844946 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -24,7 +24,6 @@
 import android.content.pm.PackageManager;
 import android.content.Context;
 import android.graphics.drawable.Icon;
-import android.os.AsyncTask;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.service.notification.NotificationListenerService;
@@ -84,7 +83,7 @@
         public List<SnoozeCriterion> snoozeCriteria;
         private int mCachedContrastColor = COLOR_INVALID;
         private int mCachedContrastColorIsFor = COLOR_INVALID;
-        private Abortable mRunningTask = null;
+        private InflationTask mRunningTask = null;
 
         public Entry(StatusBarNotification n) {
             this.key = n.getKey();
@@ -225,10 +224,14 @@
             }
         }
 
-        public void setInflationTask(Abortable abortableTask) {
+        public void setInflationTask(InflationTask abortableTask) {
             // abort any existing inflation
+            InflationTask existing = mRunningTask;
             abortTask();
             mRunningTask = abortableTask;
+            if (existing != null && mRunningTask != null) {
+                mRunningTask.supersedeTask(existing);
+            }
         }
 
         public void onInflationTaskFinished() {
@@ -236,7 +239,7 @@
         }
 
         @VisibleForTesting
-        public Abortable getRunningTask() {
+        public InflationTask getRunningTask() {
             return mRunningTask;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
index f1c26cd..4b08f2b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
@@ -28,7 +28,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.Abortable;
+import com.android.systemui.statusbar.InflationTask;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationContentView;
 import com.android.systemui.statusbar.NotificationData;
@@ -36,6 +36,13 @@
 import com.android.systemui.util.Assert;
 
 import java.util.HashMap;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * A utility that inflates the right kind of contentView based on the state
@@ -50,6 +57,7 @@
     private static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1<<2;
     private static final int FLAG_REINFLATE_PUBLIC_VIEW = 1<<3;
     private static final int FLAG_REINFLATE_AMBIENT_VIEW = 1<<4;
+    private static final InflationExecutor EXECUTOR = new InflationExecutor();
 
     private final ExpandableNotificationRow mRow;
     private boolean mIsLowPriority;
@@ -122,6 +130,12 @@
      */
     @VisibleForTesting
     void inflateNotificationViews(int reInflateFlags) {
+        if (mRow.isRemoved()) {
+            // We don't want to reinflate anything for removed notifications. Otherwise views might
+            // be readded to the stack, leading to leaks. This may happen with low-priority groups
+            // where the removal of already removed children can lead to a reinflation.
+            return;
+        }
         StatusBarNotification sbn = mRow.getEntry().notification;
         new AsyncInflationTask(sbn, reInflateFlags, mRow, mIsLowPriority,
                 mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
@@ -330,14 +344,14 @@
             cancellationSignal = newContentView.applyAsync(
                     result.packageContext,
                     parentLayout,
-                    null /* executor */,
+                    EXECUTOR,
                     listener,
                     remoteViewClickHandler);
         } else {
             cancellationSignal = newContentView.reapplyAsync(
                     result.packageContext,
                     existingView,
-                    null /* executor */,
+                    EXECUTOR,
                     listener,
                     remoteViewClickHandler);
         }
@@ -477,17 +491,17 @@
     }
 
     public static class AsyncInflationTask extends AsyncTask<Void, Void, InflationProgress>
-            implements InflationCallback, Abortable {
+            implements InflationCallback, InflationTask {
 
         private final StatusBarNotification mSbn;
         private final Context mContext;
-        private final int mReInflateFlags;
         private final boolean mIsLowPriority;
         private final boolean mIsChildInGroup;
         private final boolean mUsesIncreasedHeight;
         private final InflationCallback mCallback;
         private final boolean mUsesIncreasedHeadsUpHeight;
         private final boolean mRedactAmbient;
+        private int mReInflateFlags;
         private ExpandableNotificationRow mRow;
         private Exception mError;
         private RemoteViews.OnClickHandler mRemoteViewClickHandler;
@@ -500,8 +514,6 @@
                 InflationCallback callback,
                 RemoteViews.OnClickHandler remoteViewClickHandler) {
             mRow = row;
-            NotificationData.Entry entry = row.getEntry();
-            entry.setInflationTask(this);
             mSbn = notification;
             mReInflateFlags = reInflateFlags;
             mContext = mRow.getContext();
@@ -512,6 +524,13 @@
             mRedactAmbient = redactAmbient;
             mRemoteViewClickHandler = remoteViewClickHandler;
             mCallback = callback;
+            NotificationData.Entry entry = row.getEntry();
+            entry.setInflationTask(this);
+        }
+
+        @VisibleForTesting
+        public int getReInflateFlags() {
+            return mReInflateFlags;
         }
 
         @Override
@@ -572,6 +591,14 @@
         }
 
         @Override
+        public void supersedeTask(InflationTask task) {
+            if (task instanceof AsyncInflationTask) {
+                // We want to inflate all flags of the previous task as well
+                mReInflateFlags |= ((AsyncInflationTask) task).mReInflateFlags;
+            }
+        }
+
+        @Override
         public void handleInflationException(StatusBarNotification notification, Exception e) {
             handleError(e);
         }
@@ -604,4 +631,40 @@
         public abstract void setResultView(View v);
         public abstract RemoteViews getRemoteView();
     }
+
+    /**
+     * A custom executor that allows more tasks to be queued. Default values are copied from
+     * AsyncTask
+      */
+    private static class InflationExecutor implements Executor {
+        private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
+        // We want at least 2 threads and at most 4 threads in the core pool,
+        // preferring to have 1 less than the CPU count to avoid saturating
+        // the CPU with background work
+        private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
+        private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
+        private static final int KEEP_ALIVE_SECONDS = 30;
+
+        private static final ThreadFactory sThreadFactory = new ThreadFactory() {
+            private final AtomicInteger mCount = new AtomicInteger(1);
+
+            public Thread newThread(Runnable r) {
+                return new Thread(r, "InflaterThread #" + mCount.getAndIncrement());
+            }
+        };
+
+        private final ThreadPoolExecutor mExecutor;
+
+        private InflationExecutor() {
+            mExecutor = new ThreadPoolExecutor(
+                    CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
+                    new LinkedBlockingQueue<>(), sThreadFactory);
+            mExecutor.allowCoreThreadTimeOut(true);
+        }
+
+        @Override
+        public void execute(Runnable runnable) {
+            mExecutor.execute(runnable);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
index 1bfc0cc..3491f81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
@@ -22,14 +22,14 @@
 import android.view.ViewGroup;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.Abortable;
+import com.android.systemui.statusbar.InflationTask;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationData;
 
 /**
  * An inflater task that asynchronously inflates a ExpandableNotificationRow
  */
-public class RowInflaterTask implements Abortable, AsyncLayoutInflater.OnInflateFinishedListener {
+public class RowInflaterTask implements InflationTask, AsyncLayoutInflater.OnInflateFinishedListener {
     private RowInflationFinishedListener mListener;
     private NotificationData.Entry mEntry;
     private boolean mCancelled;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 41a60e2..6fe8827 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -330,7 +330,7 @@
 
     private void updateRightAffordanceIcon() {
         IconState state = mRightButton.getIcon();
-        mRightAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE);
+        mRightAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE);
         mRightAffordanceView.setImageDrawable(state.drawable, state.tint);
         mRightAffordanceView.setContentDescription(state.contentDescription);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index af2f7e9..6aab8e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2535,6 +2535,9 @@
 
     public void setNoVisibleNotifications(boolean noNotifications) {
         mNoVisibleNotifications = noNotifications;
+        if (mQs != null) {
+            mQs.setHasNotifications(!noNotifications);
+        }
     }
 
     public void setPulsing(boolean pulsing) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 699d367..d2ab823 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1612,7 +1612,9 @@
     @Override
     public void onAsyncInflationFinished(Entry entry) {
         mPendingNotifications.remove(entry.key);
-        if (mNotificationData.get(entry.key) == null) {
+        // If there was an async task started after the removal, we don't want to add it back to
+        // the list, otherwise we might get leaks.
+        if (mNotificationData.get(entry.key) == null && !entry.row.isRemoved()) {
             addEntry(entry);
         }
     }
@@ -1762,10 +1764,10 @@
                     continue;
                 }
                 toRemove.add(row);
-                toRemove.get(i).setKeepInParent(true);
+                row.setKeepInParent(true);
                 // we need to set this state earlier as otherwise we might generate some weird
                 // animations
-                toRemove.get(i).setRemoved();
+                row.setRemoved();
             }
         }
     }
diff --git a/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java b/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
new file mode 100644
index 0000000..b597868
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2017 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;
+
+import static org.junit.Assert.assertFalse;
+
+import android.support.test.filters.LargeTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.internal.runner.ClassPathScanner;
+import android.support.test.internal.runner.ClassPathScanner.ChainedClassNameFilter;
+import android.support.test.internal.runner.ClassPathScanner.ExternalClassNameFilter;
+import android.support.test.internal.runner.TestLoader;
+import android.testing.AndroidTestingRunner;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.systemui.SysuiBaseFragmentTest;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * This is named AAAPlusPlusVerifySysuiRequiredTestPropertiesTest for two reasons.
+ * a) Its so awesome it deserves an AAA++
+ * b) It should run first to draw attention to itself.
+ *
+ * For trues though: this test verifies that all the sysui tests extend the right classes.
+ * This matters because including tests with different context implementations in the same
+ * test suite causes errors, such as the incorrect settings provider being cached.
+ * For an example, see {@link com.android.systemui.DependencyTest}.
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class AAAPlusPlusVerifySysuiRequiredTestPropertiesTest extends SysuiTestCase {
+
+    private static final String TAG = "AAA++VerifyTest";
+
+    private static final Class[] BASE_CLS_WHITELIST = {
+            SysuiTestCase.class,
+            SysuiBaseFragmentTest.class,
+    };
+
+    private static final Class[] SUPPORTED_SIZES = {
+            SmallTest.class,
+            MediumTest.class,
+            LargeTest.class,
+            android.test.suitebuilder.annotation.SmallTest.class,
+            android.test.suitebuilder.annotation.MediumTest.class,
+            android.test.suitebuilder.annotation.LargeTest.class,
+    };
+
+    @Test
+    public void testAllClassInheritance() {
+        boolean anyClassWrong = false;
+        TestLoader loader = new TestLoader();
+        for (String className : getClassNamesFromClassPath()) {
+            Class<?> cls = loader.loadIfTest(className);
+            if (cls == null) continue;
+
+            boolean hasParent = false;
+            for (Class<?> parent : BASE_CLS_WHITELIST) {
+                if (parent.isAssignableFrom(cls)) {
+                    hasParent = true;
+                    break;
+                }
+            }
+            boolean hasSize = hasSize(cls);
+            if (!hasSize) {
+                anyClassWrong = true;
+                Log.e(TAG, cls.getName() + " does not have size annotation, such as @SmallTest");
+            }
+            if (!hasParent) {
+                anyClassWrong = true;
+                Log.e(TAG, cls.getName() + " does not extend any of " + getClsStr());
+            }
+        }
+
+        assertFalse("All sysui test classes must have size and extend one of " + getClsStr(),
+                anyClassWrong);
+    }
+
+    private boolean hasSize(Class<?> cls) {
+        for (int i = 0; i < SUPPORTED_SIZES.length; i++) {
+            if (cls.getDeclaredAnnotation(SUPPORTED_SIZES[i]) != null) return true;
+        }
+        return false;
+    }
+
+    private Collection<String> getClassNamesFromClassPath() {
+        ClassPathScanner scanner = new ClassPathScanner(mContext.getPackageCodePath());
+
+        ChainedClassNameFilter filter = new ChainedClassNameFilter();
+
+        filter.add(new ExternalClassNameFilter());
+        filter.add(s -> s.startsWith("com.android.systemui")
+                || s.startsWith("com.android.keyguard"));
+        try {
+            return scanner.getClassPathEntries(filter);
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to scan classes", e);
+        }
+        return Collections.emptyList();
+    }
+
+    private String getClsStr() {
+        return TextUtils.join(",", Arrays.asList(BASE_CLS_WHITELIST)
+                .stream().map(cls -> cls.getSimpleName()).toArray());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
index 1c9f813..855adb4 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
@@ -19,26 +19,26 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
 import android.text.TextUtils;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.TextView;
 
+import com.android.systemui.SysuiTestCase;
+
 import org.junit.Before;
 import org.junit.Test;
 
 import java.util.List;
 
-public class KeyguardClockAccessibilityDelegateTest {
+@SmallTest
+public class KeyguardClockAccessibilityDelegateTest extends SysuiTestCase {
 
-    private Context mContext;
     private TextView mView;
 
     @Before
     public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getContext();
         mView = new TextView(mContext);
         mView.setText(R.string.keyguard_widget_12_hours_format);
         mView.setContentDescription(mContext.getString(R.string.keyguard_widget_12_hours_format));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
index c297ae8..3426e11 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.os.Looper;
+import android.support.test.filters.SmallTest;
 
 import com.android.systemui.Dependency.DependencyKey;
 import com.android.systemui.statusbar.policy.FlashlightController;
@@ -30,6 +31,7 @@
 
 import java.io.PrintWriter;
 
+@SmallTest
 public class DependencyTest extends SysuiTestCase {
 
     public static final DependencyKey<Dumpable> DUMPABLE = new DependencyKey<>("dumpable");
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 0aac1c0..9b67529 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -20,6 +20,7 @@
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
 import android.testing.LeakCheck;
 import android.util.Log;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index d203602..7519b2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -43,6 +43,7 @@
 import android.view.Display;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.wakelock.WakeLockFake;
 
 import android.testing.UiThreadTest;
@@ -54,7 +55,7 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @UiThreadTest
-public class DozeMachineTest {
+public class DozeMachineTest extends SysuiTestCase {
 
     DozeMachine mMachine;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
index ada8ac0..720e9f0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
@@ -25,13 +25,14 @@
 import android.support.test.filters.SmallTest;
 import android.view.Display;
 
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 import org.junit.Before;
 import org.junit.Test;
 
 @SmallTest
-public class DozeScreenStatePreventingAdapterTest {
+public class DozeScreenStatePreventingAdapterTest extends SysuiTestCase {
 
     private DozeMachine.Service mInner;
     private DozeScreenStatePreventingAdapter mWrapper;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 8934460..97d9080 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -32,6 +32,7 @@
 import android.support.test.runner.AndroidJUnit4;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.wakelock.WakeLock;
 import com.android.systemui.util.wakelock.WakeLockFake;
@@ -44,8 +45,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class DozeTriggersTest {
-    private Context mContext;
+public class DozeTriggersTest extends SysuiTestCase {
     private DozeTriggers mTriggers;
     private DozeMachine mMachine;
     private DozeHostFake mHost;
@@ -65,7 +65,6 @@
     @Before
     public void setUp() throws Exception {
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
-        mContext = InstrumentationRegistry.getContext();
         mMachine = mock(DozeMachine.class);
         mHost = new DozeHostFake();
         mConfig = DozeConfigurationUtil.createMockConfig();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
index 0f2878b..5fb0a3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
@@ -40,6 +40,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.keyguard.WorkLockActivity;
 import com.android.systemui.keyguard.WorkLockActivityController;
 import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -58,7 +59,7 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class WorkLockActivityControllerTest {
+public class WorkLockActivityControllerTest extends SysuiTestCase {
     private static final int USER_ID = 333;
     private static final int TASK_ID = 444;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
index 9b868db..9f3573f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
@@ -33,6 +33,7 @@
 import android.graphics.Color;
 import android.os.Looper;
 
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.keyguard.WorkLockActivity;
 
 import org.junit.Before;
@@ -46,7 +47,7 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class WorkLockActivityTest {
+public class WorkLockActivityTest extends SysuiTestCase {
     private static final @UserIdInt int USER_ID = 270;
     private static final String TASK_LABEL = "task label";
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
index 9849800..0b4d9b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
@@ -17,6 +17,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.support.test.filters.SmallTest;
+
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.VersionInfo.InvalidVersionException;
 import com.android.systemui.plugins.annotations.Requires;
@@ -28,6 +30,7 @@
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 
+@SmallTest
 public class VersionInfoTest extends SysuiTestCase {
 
     @Rule
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
index 0a945ab..7cbe985 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
@@ -23,7 +23,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -45,7 +45,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
-@FlakyTest
+@SmallTest
 public class QSDetailTest extends SysuiTestCase {
 
     private MetricsLogger mMetricsLogger;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
index 09c5725..402b12d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
@@ -20,7 +20,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -40,7 +40,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
-@FlakyTest
+@SmallTest
 public class QSFooterTest extends LeakCheckedTest {
 
     private QSFooter mFooter;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 601d4e2..0b7da1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -29,6 +29,7 @@
 import com.android.systemui.R;
 
 import android.os.Parcelable;
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 
 import com.android.systemui.SysuiBaseFragmentTest;
@@ -50,7 +51,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
-@FlakyTest
+@SmallTest
 public class QSFragmentTest extends SysuiBaseFragmentTest {
 
     private MetricsLogger mMockMetricsLogger;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
index 5f6fc33..e5ff866 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
@@ -16,10 +16,10 @@
 
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
-import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -38,7 +38,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
-@FlakyTest
+@SmallTest
 public class QSPanelTest extends SysuiTestCase {
 
     private MetricsLogger mMetricsLogger;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
index 6e7d99e..0239ab0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
@@ -18,6 +18,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -33,6 +34,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
+@SmallTest
 public class TileAdapterTest extends SysuiTestCase {
 
     private TileAdapter mTileAdapter;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java
index 59483f2..f9f4f497 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java
@@ -24,6 +24,7 @@
 import android.content.res.ColorStateList;
 import android.graphics.drawable.Drawable;
 import android.service.quicksettings.Tile;
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.UiThreadTest;
 import android.widget.ImageView;
@@ -39,6 +40,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @UiThreadTest
+@SmallTest
 public class QSIconViewImplTest extends SysuiTestCase {
 
     private QSIconViewImpl mIconView;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 9ed9d28c..0500a54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -30,6 +30,7 @@
 
 import android.content.Intent;
 import android.metrics.LogMaker;
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -48,6 +49,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
+@SmallTest
 public class QSTileImplTest extends SysuiTestCase {
 
     public static final int POSITION = 14;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java
index 9e15a05..17d7a41 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.settings;
 
 import android.content.Intent;
+import android.support.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
 
@@ -26,6 +27,7 @@
 /**
  * Testing functionality of the current user tracker
  */
+@SmallTest
 public class CurrentUserTrackerTest extends SysuiTestCase {
 
     private CurrentUserTracker mTracker;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index c13d13b..8cacb4b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -22,6 +22,7 @@
 import android.content.ComponentName;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.support.test.filters.SmallTest;
 
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.SysuiTestCase;
@@ -31,6 +32,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
+@SmallTest
 public class CommandQueueTest extends SysuiTestCase {
 
     private CommandQueue mCommandQueue;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index a3a0a6f..1161987 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -29,6 +29,7 @@
 import android.view.View;
 
 import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
+import com.android.systemui.SysuiTestCase;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -38,16 +39,13 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-@FlakyTest
-public class ExpandableNotificationRowTest {
+public class ExpandableNotificationRowTest extends SysuiTestCase {
 
-    private Context mContext;
     private ExpandableNotificationRow mGroup;
     private NotificationTestHelper mNotificationTestHelper;
 
     @Before
     public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getTargetContext();
         mNotificationTestHelper = new NotificationTestHelper(mContext);
         mGroup = mNotificationTestHelper.createGroup();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
index fecf901..8dcc408 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
@@ -35,18 +35,17 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
+import com.android.systemui.SysuiTestCase;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-@FlakyTest
-public class NotificationContentViewTest {
+public class NotificationContentViewTest extends SysuiTestCase {
 
     NotificationContentView mView;
-    Context mContext;
 
     @Before
     @UiThreadTest
     public void setup() {
-        mContext = InstrumentationRegistry.getTargetContext();
         mView = new NotificationContentView(mContext, null);
         ExpandableNotificationRow row = new ExpandableNotificationRow(mContext, null);
         ExpandableNotificationRow mockRow = spy(row);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
index 00f2b18..fc9b608 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
@@ -26,6 +26,7 @@
 import android.widget.RemoteViews;
 
 import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.notification.NotificationCustomViewWrapper;
 import com.android.systemui.statusbar.notification.NotificationViewWrapper;
 
@@ -37,16 +38,13 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-@FlakyTest
-public class NotificationCustomViewWrapperTest {
+public class NotificationCustomViewWrapperTest extends SysuiTestCase {
 
-    private Context mContext;
     private ExpandableNotificationRow mRow;
 
     @Before
     @UiThreadTest
     public void setUp() {
-        mContext = InstrumentationRegistry.getTargetContext();
         mRow = new ExpandableNotificationRow(mContext, null);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
index 9249df6..e0d8042 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
@@ -16,6 +16,7 @@
 
 import static junit.framework.Assert.assertTrue;
 
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -30,6 +31,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
+@SmallTest
 public class NotificationMenuRowTest extends LeakCheckedTest {
 
     @Before
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
index f9f40a6..ee8db88 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
@@ -33,9 +33,11 @@
 import android.widget.RemoteViews;
 
 import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.InflationTask;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -47,17 +49,14 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-@FlakyTest
-public class NotificationInflaterTest {
+public class NotificationInflaterTest extends SysuiTestCase {
 
-    private Context mContext;
     private NotificationInflater mNotificationInflater;
     private Notification.Builder mBuilder;
     private ExpandableNotificationRow mRow;
 
     @Before
     public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getTargetContext();
         mBuilder = new Notification.Builder(mContext).setSmallIcon(
                 R.drawable.ic_person)
                 .setContentTitle("Title")
@@ -132,7 +131,29 @@
         mRow.getEntry().abortTask();
         runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
                 mNotificationInflater);
-        Assert.assertNull(mRow.getEntry().getRunningTask() );
+        verify(mRow).onNotificationUpdated();
+    }
+
+    @Test
+    public void testRemovedNotInflated() throws Exception {
+        mRow.setRemoved();
+        mNotificationInflater.inflateNotificationViews();
+        Assert.assertNull(mRow.getEntry().getRunningTask());
+    }
+
+
+    @Test
+    public void testSupersedesExistingTask() throws Exception {
+        mNotificationInflater.inflateNotificationViews();
+        mNotificationInflater.setIsLowPriority(true);
+        mNotificationInflater.setIsChildInGroup(true);
+        InflationTask runningTask = mRow.getEntry().getRunningTask();
+        NotificationInflater.AsyncInflationTask asyncInflationTask =
+                (NotificationInflater.AsyncInflationTask) runningTask;
+        Assert.assertSame("Successive inflations don't inherit the previous flags!",
+                asyncInflationTask.getReInflateFlags(),
+                NotificationInflater.FLAG_REINFLATE_ALL);
+        runningTask.abort();
     }
 
     public static void runThenWaitForInflation(Runnable block,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
index 7a72afd..ebeb24c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
@@ -18,9 +18,11 @@
 
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
 
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 
 import org.junit.Before;
@@ -28,14 +30,8 @@
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
-public class NotificationViewWrapperTest {
-
-    private Context mContext;
-
-    @Before
-    public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getTargetContext();
-    }
+@SmallTest
+public class NotificationViewWrapperTest extends SysuiTestCase {
 
     @Test
     public void constructor_doesntUseViewContext() throws Exception {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
index e4c43735..95ce0d8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
@@ -20,6 +20,7 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
@@ -37,7 +38,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class VisualStabilityManagerTest {
+public class VisualStabilityManagerTest extends SysuiTestCase {
 
     private VisualStabilityManager mVisualStabilityManager = new VisualStabilityManager();
     private VisualStabilityManager.Callback mCallback = mock(VisualStabilityManager.Callback.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index e41a827..0937ce2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -22,6 +22,8 @@
 import com.android.internal.app.NightDisplayController;
 import com.android.systemui.Prefs;
 import com.android.systemui.Prefs.Key;
+
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.qs.QSTileHost;
@@ -33,6 +35,7 @@
 import org.mockito.Mockito;
 
 @RunWith(AndroidTestingRunner.class)
+@SmallTest
 public class AutoTileManagerTest extends SysuiTestCase {
 
     private QSTileHost mQsTileHost;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
index 6ddbffc..66524cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.StatusBarManager;
+import android.support.test.filters.SmallTest;
 import android.view.View;
 import android.view.ViewPropertyAnimator;
 
@@ -39,6 +40,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
+@SmallTest
 public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
 
     private NotificationIconAreaController mMockNotificiationAreaController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index ee10440..e89ff97 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -18,6 +18,8 @@
 
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.phone.DozeParameters.IntInOutMatcher;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,7 +30,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class DozeParametersTest {
+public class DozeParametersTest extends SysuiTestCase {
 
     @Test
     public void test_inOutMatcher_defaultIn() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 53d842a..a120cec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -20,6 +20,7 @@
 
 import android.content.Context;
 import android.os.Looper;
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.LeakCheck.Tracker;
 import android.view.Display;
@@ -46,6 +47,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
+@SmallTest
 public class NavigationBarFragmentTest extends SysuiBaseFragmentTest {
 
     public NavigationBarFragmentTest() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
index ecae39a..5db7792 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -18,6 +18,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.ViewGroup;
@@ -36,6 +37,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
+@SmallTest
 public class StatusBarIconControllerTest extends LeakCheckedTest {
 
     @Before
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
index f516d74..2eb9560 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
@@ -20,6 +20,7 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothProfile;
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -40,6 +41,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
+@SmallTest
 public class BluetoothControllerImplTest extends SysuiTestCase {
 
     private LocalBluetoothManager mMockBluetoothManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index 3ed1681..cb20639 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -20,6 +20,7 @@
 import android.telephony.SubscriptionInfo;
 import android.test.suitebuilder.annotation.SmallTest;
 import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
@@ -40,7 +41,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class CallbackHandlerTest {
+public class CallbackHandlerTest extends SysuiTestCase {
 
     private CallbackHandler mHandler;
     private HandlerThread mHandlerThread;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
index 3e79a04..3d79d5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
@@ -20,6 +20,8 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
+import android.support.test.filters.SmallTest;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.OverlayPlugin;
@@ -34,6 +36,7 @@
 import java.util.Map;
 import java.util.function.Consumer;
 
+@SmallTest
 public class ExtensionControllerTest extends SysuiTestCase {
 
     private PluginManager mPluginManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
index 21fddf2..f859235 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.ArgumentMatchers.argThat;
 
 import android.metrics.LogMaker;
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -40,6 +41,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
+@SmallTest
 public class KeyButtonViewTest extends SysuiTestCase {
 
     private KeyButtonView mKeyButtonView;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
index 4932ba1..e6c8815 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
@@ -25,6 +25,7 @@
 import android.view.NotificationHeaderView;
 import android.view.View;
 
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationTestHelper;
 
@@ -36,17 +37,14 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-@FlakyTest
-public class NotificationChildrenContainerTest {
+public class NotificationChildrenContainerTest extends SysuiTestCase {
 
-    private Context mContext;
     private ExpandableNotificationRow mGroup;
     private int mId;
     private NotificationTestHelper mNotificationTestHelper;
 
     @Before
     public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getTargetContext();
         mNotificationTestHelper = new NotificationTestHelper(mContext);
         mGroup = mNotificationTestHelper.createGroup();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java
index 9a825c1..a3b258f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java
@@ -27,13 +27,15 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.systemui.SysuiTestCase;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class GarbageMonitorTest {
+public class GarbageMonitorTest extends SysuiTestCase {
 
     private LeakReporter mLeakReporter;
     private TrackedGarbage mTrackedGarbage;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java
index 11722fe..f1965a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java
@@ -20,6 +20,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.leak.ReferenceTestUtils.CollectionWaiter;
 
 import org.junit.Before;
@@ -35,7 +36,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class LeakDetectorTest {
+public class LeakDetectorTest extends SysuiTestCase {
 
     private LeakDetector mLeakDetector;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakReporterTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakReporterTest.java
index 1194849..6711ce8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakReporterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakReporterTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.NotificationManager;
+import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
@@ -38,6 +39,7 @@
 import java.io.PrintWriter;
 
 @RunWith(AndroidJUnit4.class)
+@MediumTest
 public class LeakReporterTest extends SysuiTestCase {
 
     private LeakDetector mLeakDetector;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/ReferenceTestUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/leak/ReferenceTestUtilsTest.java
index 9da67b7..b8a3e39 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/leak/ReferenceTestUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/leak/ReferenceTestUtilsTest.java
@@ -21,12 +21,14 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.systemui.SysuiTestCase;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class ReferenceTestUtilsTest {
+public class ReferenceTestUtilsTest extends SysuiTestCase {
 
     @Test
     public void testCollectionWaiter_doesntBlockIndefinitely() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/WeakIdentityHashMapTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/leak/WeakIdentityHashMapTest.java
index fb1c1aa..9787df9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/leak/WeakIdentityHashMapTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/leak/WeakIdentityHashMapTest.java
@@ -23,6 +23,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.leak.ReferenceTestUtils.CollectionWaiter;
 
 import org.junit.Before;
@@ -31,7 +32,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class WeakIdentityHashMapTest {
+public class WeakIdentityHashMapTest extends SysuiTestCase {
 
     WeakIdentityHashMap<Object, Object> mMap;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
index f6692eb..39316ed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
@@ -24,13 +24,15 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.systemui.SysuiTestCase;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class SettableWakeLockTest {
+public class SettableWakeLockTest extends SysuiTestCase {
 
     private WakeLockFake mFake;
     private SettableWakeLock mSettable;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
index 5394499..9b7c597 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
@@ -25,6 +25,8 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.systemui.SysuiTestCase;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -32,7 +34,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class WakeLockTest {
+public class WakeLockTest extends SysuiTestCase {
 
     WakeLock mWakeLock;
     PowerManager.WakeLock mInner;
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index e07156e..a94ed60 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -129,10 +129,11 @@
                 brightnessMode = mLastBrightnessMode;
             }
 
-            if ((color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||
-                    mBrightnessMode != brightnessMode)) {
+            if (!mInitialized || color != mColor || mode != mMode || onMS != mOnMS ||
+                    offMS != mOffMS || mBrightnessMode != brightnessMode) {
                 if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
                         + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
+                mInitialized = true;
                 mLastColor = mColor;
                 mColor = color;
                 mMode = mode;
@@ -164,6 +165,7 @@
         private int mLastColor;
         private boolean mVrModeEnabled;
         private boolean mUseLowPersistenceForVR;
+        private boolean mInitialized;
     }
 
     public LightsService(Context context) {
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 3dea783..7a7bced 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -564,7 +564,7 @@
             updateConfig();
             return;
         }
-        if (channel.getImportance() < NotificationManager.IMPORTANCE_MIN
+        if (channel.getImportance() < NotificationManager.IMPORTANCE_NONE
                 || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
             throw new IllegalArgumentException("Invalid importance level");
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3ff91ef..782325a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4852,9 +4852,17 @@
                 if (filterAppAccessLPr(ps, callingUid, userId)) {
                     return PackageManager.PERMISSION_DENIED;
                 }
+                final boolean instantApp = ps.getInstantApp(userId);
                 final PermissionsState permissionsState = ps.getPermissionsState();
                 if (permissionsState.hasPermission(permName, userId)) {
-                    return PackageManager.PERMISSION_GRANTED;
+                    if (instantApp) {
+                        BasePermission bp = mSettings.mPermissions.get(permName);
+                        if (bp != null && bp.isInstant()) {
+                            return PackageManager.PERMISSION_GRANTED;
+                        }
+                    } else {
+                        return PackageManager.PERMISSION_GRANTED;
+                    }
                 }
                 // Special case: ACCESS_FINE_LOCATION permission includes ACCESS_COARSE_LOCATION
                 if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && permissionsState
@@ -4872,6 +4880,7 @@
         final int callingUid = Binder.getCallingUid();
         final int callingUserId = UserHandle.getUserId(callingUid);
         final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
+        final boolean isUidInstantApp = getInstantAppPackageName(uid) != null;
         final int userId = UserHandle.getUserId(uid);
         if (!sUserManager.exists(userId)) {
             return PackageManager.PERMISSION_DENIED;
@@ -4893,7 +4902,14 @@
                 final SettingBase settingBase = (SettingBase) obj;
                 final PermissionsState permissionsState = settingBase.getPermissionsState();
                 if (permissionsState.hasPermission(permName, userId)) {
-                    return PackageManager.PERMISSION_GRANTED;
+                    if (isUidInstantApp) {
+                        BasePermission bp = mSettings.mPermissions.get(permName);
+                        if (bp != null && bp.isInstant()) {
+                            return PackageManager.PERMISSION_GRANTED;
+                        }
+                    } else {
+                        return PackageManager.PERMISSION_GRANTED;
+                    }
                 }
                 // Special case: ACCESS_FINE_LOCATION permission includes ACCESS_COARSE_LOCATION
                 if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && permissionsState
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 9f7c515..41da88f 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -18,6 +18,7 @@
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_MAX;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 
@@ -570,14 +571,32 @@
     }
 
     @Test
-    public void testCreateChannel_ImportanceNone() throws Exception {
+    public void testCreateChannel_badImportance() throws Exception {
         try {
             mHelper.createNotificationChannel(PKG, UID,
-                    new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true);
-            fail("Was allowed to create a blocked channel");
+                    new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE - 1), true);
+            fail("Was allowed to create a channel with invalid importance");
         } catch (IllegalArgumentException e) {
             // yay
         }
+        try {
+            mHelper.createNotificationChannel(PKG, UID,
+                    new NotificationChannel("bananas", "bananas", IMPORTANCE_UNSPECIFIED), true);
+            fail("Was allowed to create a channel with invalid importance");
+        } catch (IllegalArgumentException e) {
+            // yay
+        }
+        try {
+            mHelper.createNotificationChannel(PKG, UID,
+                    new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX + 1), true);
+            fail("Was allowed to create a channel with invalid importance");
+        } catch (IllegalArgumentException e) {
+            // yay
+        }
+        mHelper.createNotificationChannel(PKG, UID,
+                new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true);
+        mHelper.createNotificationChannel(PKG, UID,
+                new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true);
     }