From cbfbc7493bcd064eb087c3b20696c2e5ffefac95 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 18 Mar 2021 22:44:14 -0700 Subject: [PATCH 1/9] Expose the full task info with the remote animation target Bug: 129067201 Test: Manual Change-Id: Ife60b31a5798f43b55634dbb0f75dbc0c9795560 --- .../src/com/android/quickstep/AbsSwipeUpHandler.java | 9 +++++---- src/com/android/launcher3/BaseDraggingActivity.java | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 6da2201dc9..fde43f20ee 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -1076,9 +1076,9 @@ public abstract class AbsSwipeUpHandler, HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(duration); mIsSwipingPipToHome = homeAnimFactory.supportSwipePipToHome() && runningTaskTarget != null - && runningTaskTarget.pictureInPictureParams != null + && runningTaskTarget.taskInfo.pictureInPictureParams != null && TaskInfoCompat.isAutoEnterPipEnabled( - runningTaskTarget.pictureInPictureParams); + runningTaskTarget.taskInfo.pictureInPictureParams); if (mIsSwipingPipToHome) { mSwipePipToHomeAnimator = getSwipePipToHomeAnimator( homeAnimFactory, runningTaskTarget, start); @@ -1168,7 +1168,7 @@ public abstract class AbsSwipeUpHandler, final Rect destinationBounds = SystemUiProxy.INSTANCE.get(mContext) .startSwipePipToHome(taskInfo.topActivity, TaskInfoCompat.getTopActivityInfo(taskInfo), - runningTaskTarget.pictureInPictureParams, + runningTaskTarget.taskInfo.pictureInPictureParams, homeRotation, mDp.hotseatBarSizePx); final Rect startBounds = new Rect(); @@ -1177,7 +1177,8 @@ public abstract class AbsSwipeUpHandler, runningTaskTarget.taskId, taskInfo.topActivity, runningTaskTarget.leash.getSurfaceControl(), - TaskInfoCompat.getPipSourceRectHint(runningTaskTarget.pictureInPictureParams), + TaskInfoCompat.getPipSourceRectHint( + runningTaskTarget.taskInfo.pictureInPictureParams), TaskInfoCompat.getWindowConfigurationBounds(taskInfo), startBounds, destinationBounds, diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index e38ab74ee7..4ba762ac7b 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -28,6 +28,7 @@ import android.graphics.Insets; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.os.Binder; import android.os.Bundle; import android.os.Process; import android.os.StrictMode; From 941375eda4bb4ae06a85306b7fed24f1b4d9fd82 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Wed, 31 Mar 2021 13:10:45 -0400 Subject: [PATCH 2/9] Only hide workspace labels if there is not enough space for it in the cell. - Also increases the spacing in all apps to reduce visual clitter. Bug: 175329686 Test: manual, change grid to mw, smaller grid, and verify labels Change-Id: I75c7fa9c69b8446ce0e48f4353fb225004e2a2fc --- src/com/android/launcher3/DeviceProfile.java | 42 ++++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 1ce5f4dba6..a207731472 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -404,12 +404,7 @@ public class DeviceProfile { .setMultiWindowMode(true) .build(); - // If there isn't enough vertical cell padding with the labels displayed, hide the labels. - float workspaceCellPaddingY = profile.getCellSize().y - profile.iconSizePx - - iconDrawablePaddingPx - profile.iconTextSizePx; - if (workspaceCellPaddingY < profile.iconDrawablePaddingPx * 2) { - profile.adjustToHideWorkspaceLabels(); - } + profile.hideWorkspaceLabelsIfNotEnoughSpace(); // We use these scales to measure and layout the widgets using their full invariant profile // sizes and then draw them scaled and centered to fit in their multi-window mode cellspans. @@ -430,24 +425,32 @@ public class DeviceProfile { } /** - * Adjusts the profile so that the labels on the Workspace are hidden. + * Checks if there is enough space for labels on the workspace. + * If there is not, labels on the Workspace are hidden. * It is important to call this method after the All Apps variables have been set. */ - private void adjustToHideWorkspaceLabels() { - iconTextSizePx = 0; - iconDrawablePaddingPx = 0; - cellHeightPx = iconSizePx; - autoResizeAllAppsCells(); + private void hideWorkspaceLabelsIfNotEnoughSpace() { + float iconTextHeight = Utilities.calculateTextHeight(iconTextSizePx); + float workspaceCellPaddingY = getCellSize().y - iconSizePx - iconDrawablePaddingPx + - iconTextHeight; + + // We want enough space so that the text is closer to its corresponding icon. + if (workspaceCellPaddingY < iconTextHeight) { + iconTextSizePx = 0; + iconDrawablePaddingPx = 0; + cellHeightPx = iconSizePx; + autoResizeAllAppsCells(); + } } /** * Re-computes the all-apps cell size to be independent of workspace */ public void autoResizeAllAppsCells() { - int topBottomPadding = allAppsIconDrawablePaddingPx * (isVerticalBarLayout() ? 2 : 1); + int textHeight = Utilities.calculateTextHeight(allAppsIconTextSizePx); + int topBottomPadding = textHeight; allAppsCellHeightPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx - + Utilities.calculateTextHeight(allAppsIconTextSizePx) - + topBottomPadding * 2; + + textHeight + (topBottomPadding * 2); } /** @@ -536,9 +539,7 @@ public class DeviceProfile { allAppsIconSizePx = pxFromDp(inv.allAppsIconSize, mInfo.metrics); allAppsIconTextSizePx = Utilities.pxFromSp(inv.allAppsIconTextSize, mInfo.metrics); allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx; - // We use 4 below to ensure labels are closer to their corresponding icon. - allAppsCellHeightPx = Math.round(allAppsIconSizePx + allAppsIconTextSizePx - + (4 * allAppsIconDrawablePaddingPx)); + autoResizeAllAppsCells(); } else { allAppsIconSizePx = iconSizePx; allAppsIconTextSizePx = iconTextSizePx; @@ -547,9 +548,8 @@ public class DeviceProfile { } allAppsCellWidthPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx; - if (isVerticalBarLayout()) { - // Always hide the Workspace text with vertical bar layout. - adjustToHideWorkspaceLabels(); + if (isVerticalLayout) { + hideWorkspaceLabelsIfNotEnoughSpace(); } // Hotseat From 157a9ee7dd3b9a8a2440d32614b2c37f7ec2ac85 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 31 Mar 2021 12:58:39 -0700 Subject: [PATCH 3/9] Removing some unused classes Bug: 184183801 Test: Manual Change-Id: I946b4b4d486d52e467bb3df7dcac65e534803b7d --- ...ButtonNavbarToOverviewTouchController.java | 17 --- .../graphics/NinePatchDrawHelper.java | 100 ------------------ 2 files changed, 117 deletions(-) delete mode 100644 src/com/android/launcher3/graphics/NinePatchDrawHelper.java diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java index e70450d6b4..0921ad31ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java @@ -38,7 +38,6 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.graphics.PointF; import android.view.MotionEvent; -import android.view.View; import android.view.ViewConfiguration; import com.android.launcher3.Launcher; @@ -155,11 +154,6 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch super.onDragEnd(velocity); } - View searchView = mLauncher.getHotseat().getQsb(); - if (searchView instanceof FeedbackHandler) { - ((FeedbackHandler) searchView).resetFeedback(); - } - mMotionPauseDetector.clear(); mNormalToHintOverviewScrimAnimator = null; if (mLauncher.isInState(OVERVIEW)) { @@ -314,15 +308,4 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch } return super.getConfigForStates(fromState, toState); } - - /** - * Interface for views with feedback animation requiring reset - */ - public interface FeedbackHandler { - - /** - * reset searchWidget feedback - */ - void resetFeedback(); - } } diff --git a/src/com/android/launcher3/graphics/NinePatchDrawHelper.java b/src/com/android/launcher3/graphics/NinePatchDrawHelper.java deleted file mode 100644 index 587268968b..0000000000 --- a/src/com/android/launcher3/graphics/NinePatchDrawHelper.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.launcher3.graphics; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.RectF; - -/** - * Utility class which draws a bitmap by dissecting it into 3 segments and stretching - * the middle segment. - */ -public class NinePatchDrawHelper { - - // The extra width used for the bitmap. This portion of the bitmap is stretched to match the - // width of the draw region. Randomly chosen, any value > 4 will be sufficient. - public static final int EXTENSION_PX = 20; - - private final Rect mSrc = new Rect(); - private final RectF mDst = new RectF(); - // Enable filtering to always get a nice edge. This avoids jagged line, when bitmap is - // translated by half pixel. - public final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); - - /** - * Draws the bitmap split into three parts horizontally, with the middle part having width - * as {@link #EXTENSION_PX} in the center of the bitmap. - */ - public void draw(Bitmap bitmap, Canvas canvas, float left, float top, float right) { - int height = bitmap.getHeight(); - - mSrc.top = 0; - mSrc.bottom = height; - mDst.top = top; - mDst.bottom = top + height; - draw3Patch(bitmap, canvas, left, right); - } - - - /** - * Draws the bitmap split horizontally into 3 parts (same as {@link #draw}) and split - * vertically into two parts, bottom part of size {@link #EXTENSION_PX} / 2 which is - * stretched vertically. - */ - public void drawVerticallyStretched(Bitmap bitmap, Canvas canvas, float left, float top, - float right, float bottom) { - draw(bitmap, canvas, left, top, right); - - // Draw bottom stretched region. - int height = bitmap.getHeight(); - mSrc.top = height - EXTENSION_PX / 4; - mSrc.bottom = height; - mDst.top = top + height; - mDst.bottom = bottom; - draw3Patch(bitmap, canvas, left, right); - } - - - - private void draw3Patch(Bitmap bitmap, Canvas canvas, float left, float right) { - int width = bitmap.getWidth(); - int halfWidth = width / 2; - - // Draw left edge - drawRegion(bitmap, canvas, 0, halfWidth, left, left + halfWidth); - - // Draw right edge - drawRegion(bitmap, canvas, halfWidth, width, right - halfWidth, right); - - // Draw middle stretched region - int halfExt = EXTENSION_PX / 4; - drawRegion(bitmap, canvas, halfWidth - halfExt, halfWidth + halfExt, - left + halfWidth, right - halfWidth); - } - - private void drawRegion(Bitmap bitmap, Canvas c, - int srcLeft, int srcRight, float dstLeft, float dstRight) { - mSrc.left = srcLeft; - mSrc.right = srcRight; - - mDst.left = dstLeft; - mDst.right = dstRight; - c.drawBitmap(bitmap, mSrc, mDst, paint); - } -} From 0b5b8d4969d09c76d87f16d66724da2aeb9ebd4f Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 31 Mar 2021 14:56:47 -0700 Subject: [PATCH 4/9] Fixing all-apps appearing as blank Since all-apps and homescreen do not share any QSB, we can change the alpha for hotseat QSB directly Bug: 184122599 Test: Manual Change-Id: Ifa610fe75ad22cfe8a7d816ed2b48e2b9411c4c1 --- src/com/android/launcher3/Hotseat.java | 13 ------- src/com/android/launcher3/Launcher.java | 35 +------------------ .../allapps/AllAppsContainerView.java | 11 ------ .../allapps/AllAppsTransitionController.java | 1 - 4 files changed, 1 insertion(+), 59 deletions(-) diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index 15e12d697c..5429806ede 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -29,7 +29,6 @@ import android.widget.FrameLayout; import androidx.annotation.Nullable; -import java.util.Arrays; import java.util.function.Consumer; /** @@ -97,7 +96,6 @@ public class Hotseat extends CellLayout implements Insettable { } else { setGridSize(idp.numHotseatIcons, 1); } - showInlineQsb(); } @Override @@ -182,10 +180,6 @@ public class Hotseat extends CellLayout implements Insettable { mOnVisibilityAggregatedCallback = callback; } - protected void showInlineQsb() { - //Does nothing - } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -223,13 +217,6 @@ public class Hotseat extends CellLayout implements Insettable { mTaskbarView.layout(left, top, right, bottom); } - /** - * Returns the first View for which the given itemOperator returns true, or null. - */ - public View getFirstItemMatch(Workspace.ItemOperator itemOperator) { - return mWorkspace.getFirstMatch(Arrays.asList(this), itemOperator); - } - /** * Sets the alpha value of just our ShortcutAndWidgetContainer. */ diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 5eba39927f..f7cf66bf6a 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -34,7 +34,6 @@ import static com.android.launcher3.LauncherState.FLAG_NON_INTERACTIVE; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.NO_OFFSET; import static com.android.launcher3.LauncherState.NO_SCALE; -import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.SPRING_LOADED; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions; @@ -149,7 +148,6 @@ import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.qsb.QsbContainerView; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.statemanager.StateManager.StateHandler; -import com.android.launcher3.statemanager.StateManager.StateListener; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.states.RotationHelper; import com.android.launcher3.testing.TestLogging; @@ -269,9 +267,6 @@ public class Launcher extends StatefulActivity implements Launche private static final int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5; @Thunk @VisibleForTesting public static final int NEW_APPS_ANIMATION_DELAY = 500; - private static final int APPS_VIEW_ALPHA_CHANNEL_INDEX = 1; - private static final int SCRIM_VIEW_ALPHA_CHANNEL_INDEX = 0; - private static final int THEME_CROSS_FADE_ANIMATION_DURATION = 375; private Configuration mOldConfig; @@ -342,8 +337,6 @@ public class Launcher extends StatefulActivity implements Launche private RotationHelper mRotationHelper; - private float mCurrentAssistantVisibility = 0f; - protected LauncherOverlayManager mOverlayManager; // If true, overlay callbacks are deferred private boolean mDeferOverlayCallbacks; @@ -457,24 +450,6 @@ public class Launcher extends StatefulActivity implements Launche OverlayPlugin.class, false /* allowedMultiple */); mRotationHelper.initialize(); - - mStateManager.addStateListener(new StateListener() { - - @Override - public void onStateTransitionComplete(LauncherState finalState) { - float alpha = 1f - mCurrentAssistantVisibility; - if (finalState == NORMAL) { - mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha); - } else if (finalState == OVERVIEW) { - mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha); - mScrimView.setAlpha(alpha); - } else { - mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(1f); - mScrimView.setAlpha(1f); - } - } - }); - TraceHelper.INSTANCE.endSection(traceToken); mUserChangedCallbackCloseable = UserCache.INSTANCE.get(this).addUserChangeListener( @@ -563,15 +538,7 @@ public class Launcher extends StatefulActivity implements Launche } public void onAssistantVisibilityChanged(float visibility) { - mCurrentAssistantVisibility = visibility; - float alpha = 1f - visibility; - LauncherState state = mStateManager.getState(); - if (state == NORMAL) { - mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha); - } else if (state == OVERVIEW) { - mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha); - mScrimView.setAlpha(alpha); - } + mHotseat.getQsb().setAlpha(1f - visibility); } private void initDeviceProfile(InvariantDeviceProfile idp) { diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 225e1c1440..406e785ad5 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -64,8 +64,6 @@ import com.android.launcher3.keyboard.FocusedItemDecorator; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.ItemInfoMatcher; -import com.android.launcher3.util.MultiValueAlpha; -import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.Themes; import com.android.launcher3.views.RecyclerViewFastScroller; import com.android.launcher3.views.SpringRelativeLayout; @@ -80,7 +78,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo private static final float FLING_VELOCITY_MULTIPLIER = 1000 * .8f; // Starts the springs after at least 55% of the animation has passed. private static final float FLING_ANIMATION_THRESHOLD = 0.55f; - private static final int ALPHA_CHANNEL_COUNT = 2; protected final BaseDraggingActivity mLauncher; protected final AdapterHolder[] mAH; @@ -107,8 +104,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo protected RecyclerViewFastScroller mTouchHandler; protected final Point mFastScrollerOffset = new Point(); - private final MultiValueAlpha mMultiValueAlpha; - private Rect mInsets = new Rect(); SearchAdapterProvider mSearchAdapterProvider; @@ -139,8 +134,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor)); mAllAppsStore.addUpdateListener(this::onAppsUpdated); - - mMultiValueAlpha = new MultiValueAlpha(this, ALPHA_CHANNEL_COUNT); } /** @@ -156,10 +149,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo return mAllAppsStore; } - public AlphaProperty getAlphaProperty(int index) { - return mMultiValueAlpha.getProperty(index); - } - public WorkModeSwitch getWorkModeSwitch() { return mWorkModeSwitch; } diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index 8c5b0fe0c4..f031136309 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -110,7 +110,6 @@ public class AllAppsTransitionController setScrollRangeDelta(mScrollRangeDelta); if (mIsVerticalLayout) { - mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(1); mLauncher.getHotseat().setTranslationY(0); mLauncher.getWorkspace().getPageIndicator().setTranslationY(0); } From b391ebf79813e0ec18d549f1d4e3fc363fddafa6 Mon Sep 17 00:00:00 2001 From: Zak Cohen Date: Wed, 31 Mar 2021 15:09:34 -0700 Subject: [PATCH 5/9] TAPL Increase size of Background to Overview swipe gesture The instrumentation is using the swipe height, not width, for when in landscape. Ideally this should be plumbed through but it isn't yet so fix with a bigger gesture. Test: TaplTestNexus#testBackground Bug: 184059820 Change-Id: Id19f65f51468af707baea0a1b31569bb84f7fcb8 --- tests/tapl/com/android/launcher3/tapl/Background.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java index d3177837d2..4a666b17f3 100644 --- a/tests/tapl/com/android/launcher3/tapl/Background.java +++ b/tests/tapl/com/android/launcher3/tapl/Background.java @@ -122,7 +122,9 @@ public class Background extends LauncherInstrumentation.VisibleContainer { endY = startY - swipeLength; } else { startX = getSwipeStartX(); - endX = startX - swipeLength; + // TODO(b/184059820) make horizontal swipe use swipe width not height, for the + // moment just double the swipe length. + endX = startX - swipeLength * 2; startY = endY = mLauncher.getDevice().getDisplayHeight() / 2; } From 58530bd64b51419a9d6dbd9c13ec80153c4e6b95 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 31 Mar 2021 15:56:11 -0700 Subject: [PATCH 6/9] Fixing notification dots settings not updated properly Also avoiding settings cache reset whenever someone registers a new listener Bug: 184200027 Test: Manual Change-Id: I0c8b7084b6b4656102e9041b779b80a98624ddd8 --- .../RecentsAnimationDeviceState.java | 4 +-- .../logging/SettingsChangeLogger.java | 2 +- .../android/launcher3/LauncherAppState.java | 2 +- .../notification/NotificationListener.java | 6 ++-- .../settings/NotificationDotsPreference.java | 34 +++++++++++++++++++ .../launcher3/settings/SettingsActivity.java | 34 +------------------ .../android/launcher3/util/SettingsCache.java | 22 +++++------- 7 files changed, 51 insertions(+), 53 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index 458f45a75d..23e35f6307 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -187,7 +187,7 @@ public class RecentsAnimationDeviceState implements SettingsCache.OnChangeListener onChangeListener = enabled -> mIsOneHandedModeEnabled = enabled; settingsCache.register(oneHandedUri, onChangeListener); - settingsCache.dispatchOnChange(oneHandedUri); + mIsOneHandedModeEnabled = settingsCache.getValue(oneHandedUri); runOnDestroy(() -> settingsCache.unregister(oneHandedUri, onChangeListener)); } else { mIsOneHandedModeEnabled = false; @@ -199,7 +199,7 @@ public class RecentsAnimationDeviceState implements SettingsCache.OnChangeListener onChangeListener = enabled -> mIsSwipeToNotificationEnabled = enabled; settingsCache.register(swipeBottomNotificationUri, onChangeListener); - settingsCache.dispatchOnChange(swipeBottomNotificationUri); + mIsSwipeToNotificationEnabled = settingsCache.getValue(swipeBottomNotificationUri); runOnDestroy(() -> settingsCache.unregister(swipeBottomNotificationUri, onChangeListener)); Uri setupCompleteUri = Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE); diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java index f336bf5260..b336d2fcea 100644 --- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java +++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java @@ -80,7 +80,7 @@ public class SettingsChangeLogger implements SettingsCache mSettingsCache = SettingsCache.INSTANCE.get(context); mSettingsCache.register(NOTIFICATION_BADGING_URI, this::onNotificationDotsChanged); - mSettingsCache.dispatchOnChange(NOTIFICATION_BADGING_URI); + onNotificationDotsChanged(mSettingsCache.getValue(NOTIFICATION_BADGING_URI)); } private static ArrayMap loadPrefKeys(Context context) { diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index ccc023ab76..4754558aa1 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -116,7 +116,7 @@ public class LauncherAppState { mNotificationSettingsChangedListener = this::onNotificationSettingsChanged; mSettingsCache.register(NOTIFICATION_BADGING_URI, mNotificationSettingsChangedListener); - mSettingsCache.dispatchOnChange(NOTIFICATION_BADGING_URI); + onNotificationSettingsChanged(mSettingsCache.getValue(NOTIFICATION_BADGING_URI)); } public LauncherAppState(Context context, @Nullable String iconCacheFileName) { diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java index 2905dc322a..e58f5fa2d5 100644 --- a/src/com/android/launcher3/notification/NotificationListener.java +++ b/src/com/android/launcher3/notification/NotificationListener.java @@ -16,9 +16,9 @@ package com.android.launcher3.notification; -import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; +import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI; import android.annotation.TargetApi; import android.app.Notification; @@ -37,8 +37,8 @@ import androidx.annotation.AnyThread; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; -import com.android.launcher3.util.SettingsCache; import com.android.launcher3.util.PackageUserKey; +import com.android.launcher3.util.SettingsCache; import java.util.ArrayList; import java.util.Arrays; @@ -213,7 +213,7 @@ public class NotificationListener extends NotificationListenerService { mNotificationSettingsChangedListener = this::onNotificationSettingsChanged; mSettingsCache.register(NOTIFICATION_BADGING_URI, mNotificationSettingsChangedListener); - mSettingsCache.dispatchOnChange(NOTIFICATION_BADGING_URI); + onNotificationSettingsChanged(mSettingsCache.getValue(NOTIFICATION_BADGING_URI)); onNotificationFullRefresh(); } diff --git a/src/com/android/launcher3/settings/NotificationDotsPreference.java b/src/com/android/launcher3/settings/NotificationDotsPreference.java index a35416915f..afcf882e7d 100644 --- a/src/com/android/launcher3/settings/NotificationDotsPreference.java +++ b/src/com/android/launcher3/settings/NotificationDotsPreference.java @@ -17,6 +17,8 @@ package com.android.launcher3.settings; import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY; import static com.android.launcher3.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGS; +import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; +import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI; import android.app.AlertDialog; import android.app.Dialog; @@ -24,6 +26,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.database.ContentObserver; import android.os.Bundle; import android.provider.Settings; import android.util.AttributeSet; @@ -49,6 +52,14 @@ public class NotificationDotsPreference extends Preference /** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */ private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners"; + private final ContentObserver mListenerListObserver = + new ContentObserver(MAIN_EXECUTOR.getHandler()) { + @Override + public void onChange(boolean selfChange) { + updateUI(); + } + }; + public NotificationDotsPreference( Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); @@ -66,6 +77,29 @@ public class NotificationDotsPreference extends Preference super(context); } + @Override + public void onAttached() { + super.onAttached(); + SettingsCache.INSTANCE.get(getContext()).register(NOTIFICATION_BADGING_URI, this); + getContext().getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(NOTIFICATION_ENABLED_LISTENERS), + false, mListenerListObserver); + updateUI(); + } + + private void updateUI() { + onSettingsChanged(SettingsCache.INSTANCE.get(getContext()) + .getValue(NOTIFICATION_BADGING_URI)); + } + + @Override + public void onDetached() { + super.onDetached(); + SettingsCache.INSTANCE.get(getContext()).unregister(NOTIFICATION_BADGING_URI, this); + getContext().getContentResolver().unregisterContentObserver(mListenerListObserver); + + } + private void setWidgetFrameVisible(boolean isVisible) { if (mWidgetFrameVisible != isVisible) { mWidgetFrameVisible = isVisible; diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java index f03065c7f8..5b42ac70eb 100644 --- a/src/com/android/launcher3/settings/SettingsActivity.java +++ b/src/com/android/launcher3/settings/SettingsActivity.java @@ -18,8 +18,6 @@ package com.android.launcher3.settings; import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS; -import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI; -import static com.android.launcher3.util.SettingsCache.NOTIFICATION_ENABLED_LISTENERS; import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY; import static com.android.launcher3.states.RotationHelper.getAllowRotationDefaultValue; @@ -45,7 +43,6 @@ import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.WidgetsModel; -import com.android.launcher3.util.SettingsCache; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; /** @@ -124,11 +121,8 @@ public class SettingsActivity extends FragmentActivity */ public static class LauncherSettingsFragment extends PreferenceFragmentCompat { - private SettingsCache mSettingsCache; - private String mHighLightKey; private boolean mPreferenceHighlighted = false; - private NotificationDotsPreference mNotificationSettingsChangedListener; private Preference mDeveloperOptionPref; @Override @@ -172,22 +166,7 @@ public class SettingsActivity extends FragmentActivity protected boolean initPreference(Preference preference) { switch (preference.getKey()) { case NOTIFICATION_DOTS_PREFERENCE_KEY: - if (WidgetsModel.GO_DISABLE_NOTIFICATION_DOTS) { - return false; - } - - // Listen to system notification dot settings while this UI is active. - mSettingsCache = SettingsCache.INSTANCE.get(getActivity()); - mNotificationSettingsChangedListener = - ((NotificationDotsPreference) preference); - mSettingsCache.register(NOTIFICATION_BADGING_URI, - (NotificationDotsPreference) mNotificationSettingsChangedListener); - // Also listen if notification permission changes - mSettingsCache.register(NOTIFICATION_ENABLED_LISTENERS, - mNotificationSettingsChangedListener); - mSettingsCache.dispatchOnChange(NOTIFICATION_BADGING_URI); - mSettingsCache.dispatchOnChange(NOTIFICATION_ENABLED_LISTENERS); - return true; + return !WidgetsModel.GO_DISABLE_NOTIFICATION_DOTS; case ALLOW_ROTATION_PREFERENCE_KEY: if (getResources().getBoolean(R.bool.allow_rotation)) { @@ -269,16 +248,5 @@ public class SettingsActivity extends FragmentActivity } }); } - - @Override - public void onDestroy() { - if (mSettingsCache != null) { - mSettingsCache.unregister(NOTIFICATION_BADGING_URI, - mNotificationSettingsChangedListener); - mSettingsCache.unregister(NOTIFICATION_ENABLED_LISTENERS, - mNotificationSettingsChangedListener); - } - super.onDestroy(); - } } } diff --git a/src/com/android/launcher3/util/SettingsCache.java b/src/com/android/launcher3/util/SettingsCache.java index 22b4d38891..10611c7211 100644 --- a/src/com/android/launcher3/util/SettingsCache.java +++ b/src/com/android/launcher3/util/SettingsCache.java @@ -39,12 +39,11 @@ import java.util.concurrent.CopyOnWriteArrayList; * {@link #unregister(Uri, OnChangeListener)} methods. * * This can be used as a normal cache without any listeners as well via the - * {@link #getValue(Uri, int)} and {@link #dispatchOnChange(Uri)} to update (and subsequently call + * {@link #getValue(Uri, int)} and {@link #onChange)} to update (and subsequently call * get) * * The cache will be invalidated/updated through the normal * {@link ContentObserver#onChange(boolean)} calls - * or can be force updated by calling {@link #dispatchOnChange(Uri)}. * * Cache will also be updated if a key queried is missing (even if it has no listeners registered). */ @@ -58,9 +57,6 @@ public class SettingsCache extends ContentObserver { /** Hidden field Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED */ public static final String ONE_HANDED_SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED = "swipe_bottom_to_notification_enabled"; - /** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */ - public static final Uri NOTIFICATION_ENABLED_LISTENERS = - Settings.Secure.getUriFor("enabled_notification_listeners"); public static final Uri ROTATION_SETTING_URI = Settings.System.getUriFor(ACCELEROMETER_ROTATION); @@ -99,6 +95,14 @@ public class SettingsCache extends ContentObserver { } } + /** + * Returns the value for this classes key from the cache. If not in cache, will call + * {@link #updateValue(Uri, int)} to fetch. + */ + public boolean getValue(Uri keySetting) { + return getValue(keySetting, 1); + } + /** * Returns the value for this classes key from the cache. If not in cache, will call * {@link #updateValue(Uri, int)} to fetch. @@ -139,14 +143,6 @@ public class SettingsCache extends ContentObserver { return newVal; } - /** - * Force update a change for a given URI and have all listeners for that URI receive callbacks - * even if the value is unchanged. - */ - public void dispatchOnChange(Uri uri) { - onChange(true, uri); - } - /** * Call to stop receiving updates on the given {@param listener}. * This Uri/Listener pair must correspond to the same pair called with for From 063e350fa319d77cf2d2787814be6c851a6695fa Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 30 Mar 2021 21:47:38 -0700 Subject: [PATCH 7/9] Move disabled test out Bug: 182844465 Test: presubmit Change-Id: I543c43db3fb27e671eea00d112bab2a4f485dbc9 --- .../com/android/launcher3/ui => src_disabled}/WorkTabTest.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{src/com/android/launcher3/ui => src_disabled}/WorkTabTest.java (100%) diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src_disabled/WorkTabTest.java similarity index 100% rename from tests/src/com/android/launcher3/ui/WorkTabTest.java rename to tests/src_disabled/WorkTabTest.java From 712a8bf0041dde1ee1611d2c107db1ce9fb11a47 Mon Sep 17 00:00:00 2001 From: Pierre Barbier de Reuille Date: Thu, 1 Apr 2021 11:19:20 +0100 Subject: [PATCH 8/9] Prevent launcher crash when an App Widget is removed. If an App Widget with a scrollable element is removed, we may end up in a situation where we try to draw the view directly on a canvas while the it has already been detached from the workspace. This can crash as some of the drawing the scroll indicators require the view to be attached. In general, we should never draw a view by calling the draw method directly, even more so when the view is detached: the behavior is undefined as the method expects the canvas to be properly set up, and it is not. A crash can therefore be expected. This patch should avoid crashing the launcher until we stop doing that altogether. Fix: 183386115 Test: Manally add a view with a preview layout Test: Manually remove an app widget with a list view Change-Id: I8e1aa581700a08d6747eab085199c2b293e0e3fb --- .../dragndrop/AppWidgetHostViewDrawable.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java b/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java index 5cd95dc413..7b32bbf02e 100644 --- a/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java +++ b/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java @@ -27,15 +27,21 @@ import android.graphics.drawable.Drawable; import com.android.launcher3.widget.LauncherAppWidgetHostView; -/** A drawable which renders {@link LauncherAppWidgetHostView} to a canvas. */ +/** + * A drawable which renders {@link LauncherAppWidgetHostView} to a canvas. + * + * TODO(b/183609936) Stop using that class and remove it. + */ public final class AppWidgetHostViewDrawable extends Drawable { private final LauncherAppWidgetHostView mAppWidgetHostView; private Paint mPaint = new Paint(); private final Path mClipPath; + private final boolean mWasAttached; public AppWidgetHostViewDrawable(LauncherAppWidgetHostView appWidgetHostView) { mAppWidgetHostView = appWidgetHostView; + mWasAttached = appWidgetHostView.isAttachedToWindow(); Path clipPath = null; if (appWidgetHostView.getClipToOutline()) { Outline outline = new Outline(); @@ -56,7 +62,12 @@ public final class AppWidgetHostViewDrawable extends Drawable { if (mClipPath != null) { canvas.clipPath(mClipPath); } - mAppWidgetHostView.draw(canvas); + // If the view was never attached, or is current attached, then draw. Otherwise do not try + // to draw, or we might trigger bugs with items that get drawn while requiring the view to + // be attached. + if (!mWasAttached || mAppWidgetHostView.isAttachedToWindow()) { + mAppWidgetHostView.draw(canvas); + } canvas.restoreToCount(saveCount); } From b62fba0d0199d719ac63761846e09b4b28e1dc2c Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Thu, 1 Apr 2021 13:14:23 -0400 Subject: [PATCH 9/9] Set FLAG_IMMUTABLE flag on FirstScreenBroadcast PendingIntent. Bug: 183927137 Test: restore phone and ensure broadcast is sent Change-Id: I8d8e38a1aa6bdf13879d460cfa84cabe6c6bb1f2 --- src/com/android/launcher3/model/FirstScreenBroadcast.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/model/FirstScreenBroadcast.java b/src/com/android/launcher3/model/FirstScreenBroadcast.java index 70d1b481e6..e391d37938 100644 --- a/src/com/android/launcher3/model/FirstScreenBroadcast.java +++ b/src/com/android/launcher3/model/FirstScreenBroadcast.java @@ -15,6 +15,8 @@ */ package com.android.launcher3.model; +import static android.app.PendingIntent.FLAG_IMMUTABLE; +import static android.app.PendingIntent.FLAG_ONE_SHOT; import static android.os.Process.myUserHandle; import static com.android.launcher3.pm.InstallSessionHelper.getUserHandle; @@ -140,7 +142,7 @@ public class FirstScreenBroadcast { .putStringArrayListExtra(HOTSEAT_ITEM_EXTRA, new ArrayList<>(hotseatItems)) .putStringArrayListExtra(WIDGET_ITEM_EXTRA, new ArrayList<>(widgetItems)) .putExtra(VERIFICATION_TOKEN_EXTRA, PendingIntent.getActivity(context, 0, - new Intent(), PendingIntent.FLAG_ONE_SHOT))); + new Intent(), FLAG_ONE_SHOT | FLAG_IMMUTABLE))); } private static String getPackageName(ItemInfo info) {