Merge "Fix a memory leak" into sc-dev
diff --git a/go/OWNERS b/go/OWNERS
new file mode 100644
index 0000000..903b3c4
--- /dev/null
+++ b/go/OWNERS
@@ -0,0 +1,2 @@
+rajekumar@google.com
+spivack@google.com
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index 3a47344..872f168 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -96,7 +96,7 @@
             }
 
             getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
-            boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
+            boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot();
             getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
 
             mTaskId = task.key.id;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 3567c17..21a2d51 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -120,11 +120,6 @@
     }
 
     protected void init(int numHotseatIcons, int numRecentIcons) {
-        mLayoutTransition = new LayoutTransition();
-        addUpdateListenerForAllLayoutTransitions(
-                () -> mControllerCallbacks.onItemPositionsChanged(this));
-        setLayoutTransition(mLayoutTransition);
-
         mHotseatStartIndex = 0;
         mHotseatEndIndex = mHotseatStartIndex + numHotseatIcons - 1;
         updateHotseatItems(new ItemInfo[numHotseatIcons]);
@@ -135,6 +130,14 @@
         mRecentsStartIndex = dividerIndex + 1;
         mRecentsEndIndex = mRecentsStartIndex + numRecentIcons - 1;
         updateRecentTasks(new Task[numRecentIcons]);
+
+        mLayoutTransition = new LayoutTransition();
+        addUpdateListenerForAllLayoutTransitions(() -> {
+            if (getLayoutTransition() == mLayoutTransition) {
+                mControllerCallbacks.onItemPositionsChanged(this);
+            }
+        });
+        setLayoutTransition(mLayoutTransition);
     }
 
     private void addUpdateListenerForAllLayoutTransitions(Runnable onUpdate) {
@@ -159,10 +162,20 @@
     }
 
     protected void cleanup() {
+        endAllLayoutTransitionAnimators();
+        setLayoutTransition(null);
         removeAllViews();
         mHotseatRecentsDivider = null;
     }
 
+    private void endAllLayoutTransitionAnimators() {
+        mLayoutTransition.getAnimator(LayoutTransition.CHANGE_APPEARING).end();
+        mLayoutTransition.getAnimator(LayoutTransition.CHANGE_DISAPPEARING).end();
+        mLayoutTransition.getAnimator(LayoutTransition.CHANGING).end();
+        mLayoutTransition.getAnimator(LayoutTransition.APPEARING).end();
+        mLayoutTransition.getAnimator(LayoutTransition.DISAPPEARING).end();
+    }
+
     /**
      * Sets the alpha of the background color behind all the Taskbar contents.
      * @param alpha 0 is fully transparent, 1 is fully opaque.
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index cd13200..1ad5f2c 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -176,7 +176,7 @@
 
             if (thumbnail != null) {
                 getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
-                boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
+                boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot();
                 getActionsView().setCallbacks(new OverlayUICallbacksImpl(isAllowedByPolicy, task));
             }
         }
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index 2b54f95..af62582 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -440,13 +440,14 @@
     }
 
     /**
-     * Returns whether the snapshot is real.
+     * Returns whether the snapshot is real. If the device is locked for the user of the task,
+     * the snapshot used will be an app-theme generated snapshot instead of a real snapshot.
      */
     public boolean isRealSnapshot() {
         if (mThumbnailData == null) {
             return false;
         }
-        return mThumbnailData.isRealSnapshot;
+        return mThumbnailData.isRealSnapshot && !mTask.isLocked;
     }
 
     /**
diff --git a/res/layout/all_apps_tabs.xml b/res/layout/all_apps_tabs.xml
index c684881..2accd2d 100644
--- a/res/layout/all_apps_tabs.xml
+++ b/res/layout/all_apps_tabs.xml
@@ -26,6 +26,7 @@
     android:clipChildren="true"
     android:clipToPadding="false"
     android:descendantFocusability="afterDescendants"
+    android:paddingTop="@dimen/all_apps_header_top_padding"
     launcher:pageIndicator="@+id/tabs" >
 
     <include layout="@layout/all_apps_rv_layout" />
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index f4a729f..c1c8f01 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -129,8 +129,6 @@
         <!-- numHotseatIcons defaults to numColumns, if not specified -->
         <attr name="numHotseatIcons" format="integer" />
         <attr name="dbFile" format="string" />
-        <!-- numAllAppsColumns defaults to numColumns, if not specified -->
-        <attr name="numAllAppsColumns" format="integer" />
         <attr name="defaultLayoutId" format="reference" />
         <attr name="demoModeLayoutId" format="reference" />
         <attr name="isScalable" format="boolean" />
@@ -171,6 +169,9 @@
         <attr name="allAppsIconSize" format="float" />
         <!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
         <attr name="allAppsIconTextSize" format="float" />
+
+        <!-- numAllAppsColumns defaults to GridDisplayOption.numColumns, if not specified -->
+        <attr name="numAllAppsColumns" format="integer" />
     </declare-styleable>
 
     <declare-styleable name="CellLayout">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e5e5db3..1371e91 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -380,9 +380,18 @@
     <!--- heading shown when user opens work apps tab while work apps are paused -->
     <string name="work_apps_paused_title">Work profile is paused</string>
     <!--- body shown when user opens work apps tab while work apps are paused -->
-    <string name="work_apps_paused_body">Work apps can\'t send you notifications, use your battery, or access your location</string>
+    <string name="work_apps_paused_body">Work apps can’t send you notifications, use your battery, or access your location</string>
     <!-- content description for paused work apps list -->
-    <string name="work_apps_paused_content_description">Work profile is paused. Work apps can\’t send you notifications, use your battery, or access your location</string>
+    <string name="work_apps_paused_content_description">Work profile is paused. Work apps can’t send you notifications, use your battery, or access your location</string>
+    <!-- string shown in educational banner about work profile -->
+    <string name="work_apps_paused_edu_banner">Work apps are badged and visible to your IT admin</string>
+    <!-- button string shown to dismiss work tab education -->
+    <string name="work_apps_paused_edu_accept">Got it</string>
+
+    <!-- button string shown pause work profile -->
+    <string name="work_apps_pause_btn_text">Pause work apps</string>
+    <!-- button string shown enable work profile -->
+    <string name="work_apps_enable_btn_text">Turn on</string>
 
     <!-- A hint shown in launcher settings develop options filter box -->
     <string name="developer_options_filter_hint">Filter</string>
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index b1fe4a2..0027a50 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -28,6 +28,7 @@
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Paint;
+import android.graphics.Path;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -61,6 +62,8 @@
     private boolean mIsPressed;
     private boolean mIsDisabled;
     private float mDisabledAlpha = 1f;
+    private float mRoundedCornersRadius = 0f;
+    private final Path mClipPath = new Path();
 
     // Animator and properties for the fast bitmap drawable's scale
     private static final Property<FastBitmapDrawable, Float> SCALE
@@ -102,6 +105,13 @@
 
     @Override
     public final void draw(Canvas canvas) {
+        if (mRoundedCornersRadius > 0) {
+            float radius = mRoundedCornersRadius * mScale;
+            mClipPath.reset();
+            mClipPath.addRoundRect(0, 0, getIntrinsicWidth(), getIntrinsicHeight(),
+                    radius, radius, Path.Direction.CCW);
+            canvas.clipPath(mClipPath);
+        }
         if (mScale != 1f) {
             int count = canvas.save();
             Rect bounds = getBounds();
@@ -164,6 +174,14 @@
         return mScale;
     }
 
+    public void setRoundedCornersRadius(float radius) {
+        mRoundedCornersRadius = radius;
+    }
+
+    public float getRoundedCornersRadius() {
+        return mRoundedCornersRadius;
+    }
+
     @Override
     public int getIntrinsicWidth() {
         return mBitmap.getWidth();
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 3dbd479..b0c3bb4 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -227,8 +227,13 @@
                 .add(myDisplayOption);
         result.iconSize = defaultDisplayOption.iconSize;
         result.landscapeIconSize = defaultDisplayOption.landscapeIconSize;
-        result.allAppsIconSize = Math.min(
-                defaultDisplayOption.allAppsIconSize, myDisplayOption.allAppsIconSize);
+        if (defaultDisplayOption.allAppsIconSize < myDisplayOption.allAppsIconSize) {
+            result.allAppsIconSize = defaultDisplayOption.allAppsIconSize;
+            result.numAllAppsColumns = defaultDisplayOption.numAllAppsColumns;
+        } else {
+            result.allAppsIconSize = myDisplayOption.allAppsIconSize;
+            result.numAllAppsColumns = myDisplayOption.numAllAppsColumns;
+        }
         result.minCellHeight = defaultDisplayOption.minCellHeight;
         result.minCellWidth = defaultDisplayOption.minCellWidth;
         result.borderSpacing = defaultDisplayOption.borderSpacing;
@@ -278,7 +283,6 @@
         demoModeLayoutId = closestProfile.demoModeLayoutId;
         numFolderRows = closestProfile.numFolderRows;
         numFolderColumns = closestProfile.numFolderColumns;
-        numAllAppsColumns = closestProfile.numAllAppsColumns;
         isScalable = closestProfile.isScalable;
         devicePaddingId = closestProfile.devicePaddingId;
 
@@ -294,6 +298,7 @@
         minCellHeight = displayOption.minCellHeight;
         minCellWidth = displayOption.minCellWidth;
         borderSpacing = displayOption.borderSpacing;
+        numAllAppsColumns = Math.round(displayOption.numAllAppsColumns);
 
         if (Utilities.isGridOptionsEnabled(context)) {
             allAppsIconSize = displayOption.allAppsIconSize;
@@ -614,7 +619,6 @@
         private final int numHotseatIcons;
 
         private final String dbFile;
-        private final int numAllAppsColumns;
 
         private final int defaultLayoutId;
         private final int demoModeLayoutId;
@@ -642,8 +646,6 @@
                     R.styleable.GridDisplayOption_numFolderRows, numRows);
             numFolderColumns = a.getInt(
                     R.styleable.GridDisplayOption_numFolderColumns, numColumns);
-            numAllAppsColumns = a.getInt(
-                    R.styleable.GridDisplayOption_numAllAppsColumns, numColumns);
 
             isScalable = a.getBoolean(
                     R.styleable.GridDisplayOption_isScalable, false);
@@ -664,6 +666,7 @@
         private final float minHeightDps;
         private final boolean canBeDefault;
 
+        private float numAllAppsColumns;
         private float minCellHeight;
         private float minCellWidth;
         private float borderSpacing;
@@ -684,6 +687,8 @@
             minHeightDps = a.getFloat(R.styleable.ProfileDisplayOption_minHeightDps, 0);
             canBeDefault = a.getBoolean(
                     R.styleable.ProfileDisplayOption_canBeDefault, false);
+            numAllAppsColumns = a.getInt(R.styleable.ProfileDisplayOption_numAllAppsColumns,
+                    grid.numColumns);
 
             minCellHeight = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0);
             minCellWidth = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0);
@@ -710,12 +715,14 @@
             minWidthDps = 0;
             minHeightDps = 0;
             canBeDefault = false;
+            numAllAppsColumns = 0;
             minCellHeight = 0;
             minCellWidth = 0;
             borderSpacing = 0;
         }
 
         private DisplayOption multiply(float w) {
+            numAllAppsColumns *= w;
             iconSize *= w;
             landscapeIconSize *= w;
             allAppsIconSize *= w;
@@ -728,6 +735,7 @@
         }
 
         private DisplayOption add(DisplayOption p) {
+            numAllAppsColumns += p.numAllAppsColumns;
             iconSize += p.iconSize;
             landscapeIconSize += p.landscapeIconSize;
             allAppsIconSize += p.allAppsIconSize;
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 591de04..bf0a88f 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -583,10 +583,6 @@
         int padding = mHeader.getMaxTranslation();
         for (int i = 0; i < mAH.length; i++) {
             mAH[i].padding.top = padding;
-            if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mUsingTabs) {
-                //add extra space between tabs and recycler view
-                mAH[i].padding.top += mLauncher.getDeviceProfile().edgeMarginPx;
-            }
             mAH[i].applyPadding();
         }
     }
diff --git a/src/com/android/launcher3/allapps/AllAppsPagedView.java b/src/com/android/launcher3/allapps/AllAppsPagedView.java
index 14e3b51..3cc9ce6 100644
--- a/src/com/android/launcher3/allapps/AllAppsPagedView.java
+++ b/src/com/android/launcher3/allapps/AllAppsPagedView.java
@@ -23,8 +23,6 @@
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.PagedView;
-import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.workprofile.PersonalWorkPagedView;
 
 /**
@@ -43,10 +41,6 @@
 
     public AllAppsPagedView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-        int topPadding = FeatureFlags.ENABLE_DEVICE_SEARCH.get() ? 0
-                : context.getResources().getDimensionPixelOffset(
-                        R.dimen.all_apps_header_top_padding);
-        setPadding(0, topPadding, 0, 0);
     }
 
     @Override
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 86f330c..733d867 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -106,8 +106,8 @@
 
     public FloatingHeaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
-        mHeaderTopPadding = FeatureFlags.ENABLE_DEVICE_SEARCH.get() ? 0 :
-                context.getResources().getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
+        mHeaderTopPadding = context.getResources()
+                .getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
     }
 
     @Override
@@ -125,7 +125,6 @@
             }
         }
         mFixedRows = rows.toArray(new FloatingHeaderRow[rows.size()]);
-        setPadding(0, mHeaderTopPadding, 0, 0);
         mAllRows = mFixedRows;
     }
 
@@ -243,9 +242,7 @@
 
     public int getMaxTranslation() {
         if (mMaxTranslation == 0 && mTabsHidden) {
-            int paddingOffset = getResources().getDimensionPixelSize(
-                    R.dimen.all_apps_search_bar_bottom_padding);
-            return FeatureFlags.ENABLE_DEVICE_SEARCH.get() ? 0 : paddingOffset;
+            return getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_bottom_padding);
         } else if (mMaxTranslation > 0 && mTabsHidden) {
             return mMaxTranslation + getPaddingTop();
         } else {
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 2e542ed..687318f 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -497,12 +497,13 @@
 
     @UiThread
     private void enforceRoundedCorners() {
-        if (mEnforcedCornerRadius <= 0 || !RoundedCornerEnforcement.isRoundedCornerEnabled(this)) {
+        if (mEnforcedCornerRadius <= 0 || !RoundedCornerEnforcement.isRoundedCornerEnabled()) {
             resetRoundedCorners();
             return;
         }
         View background = RoundedCornerEnforcement.findBackground(this);
-        if (RoundedCornerEnforcement.hasAppWidgetOptedOut(this, background)) {
+        if (background == null
+                || RoundedCornerEnforcement.hasAppWidgetOptedOut(this, background)) {
             resetRoundedCorners();
             return;
         }
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index 247a748..08bb662 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -54,10 +54,13 @@
 
     @Nullable private RemoteViews mRemoteViewsPreview;
     @Nullable private LauncherAppWidgetHostView mAppWidgetHostViewPreview;
+    private final float mEnforcedRoundedCornersForWidget;
 
     public PendingItemDragHelper(View view) {
         super(view);
         mAddInfo = (PendingAddItemInfo) view.getTag();
+        mEnforcedRoundedCornersForWidget = RoundedCornerEnforcement.computeEnforcedRadius(
+                view.getContext());
     }
 
     /**
@@ -115,10 +118,14 @@
                         .addDragListener(new AppWidgetHostViewDragListener(launcher));
             }
             if (preview == null) {
-                preview = new FastBitmapDrawable(
+                FastBitmapDrawable p = new FastBitmapDrawable(
                         app.getWidgetCache().generateWidgetPreview(launcher,
                                 createWidgetInfo.info, maxWidth, null,
                                 previewSizeBeforeScale).first);
+                if (RoundedCornerEnforcement.isRoundedCornerEnabled()) {
+                    p.setRoundedCornersRadius(mEnforcedRoundedCornersForWidget);
+                }
+                preview = p;
             }
 
             if (previewSizeBeforeScale[0] < previewBitmapWidth) {
diff --git a/src/com/android/launcher3/widget/RoundedCornerEnforcement.java b/src/com/android/launcher3/widget/RoundedCornerEnforcement.java
index 99eccd1..1e46ffd 100644
--- a/src/com/android/launcher3/widget/RoundedCornerEnforcement.java
+++ b/src/com/android/launcher3/widget/RoundedCornerEnforcement.java
@@ -72,12 +72,8 @@
     }
 
     /** Check if the app widget is in the deny list. */
-    public static boolean isRoundedCornerEnabled(@NonNull View view) {
-        if (!Utilities.ATLEAST_S || !FeatureFlags.ENABLE_ENFORCED_ROUNDED_CORNERS.get()) {
-            return false;
-        }
-        // Here we need to test if the view's component is in the (to be created) deny list.
-        return true;
+    public static boolean isRoundedCornerEnabled() {
+        return Utilities.ATLEAST_S && FeatureFlags.ENABLE_ENFORCED_ROUNDED_CORNERS.get();
     }
 
     /**
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 1b0e1ce..2b4b9ea 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -94,6 +94,7 @@
     protected final BaseActivity mActivity;
     protected final DeviceProfile mDeviceProfile;
     private final CheckLongPressHelper mLongPressHelper;
+    private final float mEnforcedCornerRadius;
 
     private RemoteViews mPreview;
     private LauncherAppWidgetHostView mAppWidgetHostViewPreview;
@@ -118,6 +119,7 @@
         setWillNotDraw(false);
         setClipToPadding(false);
         setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
+        mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(context);
     }
 
     private void setContainerWidth() {
@@ -245,7 +247,9 @@
     }
 
     public void applyPreview(Bitmap bitmap) {
-        applyPreview(new FastBitmapDrawable(bitmap));
+        FastBitmapDrawable drawable = new FastBitmapDrawable(bitmap);
+        drawable.setRoundedCornersRadius(mEnforcedCornerRadius);
+        applyPreview(drawable);
     }
 
     private void applyPreview(Drawable drawable) {