Merge "Add User group logging for Omnient" into main
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 042bc9a..0b850bd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -154,12 +154,6 @@
}
}
- @Override
- protected boolean isTaskbarTouchable() {
- return !(mTaskbarLauncherStateController.isAnimatingToLauncher()
- && mTaskbarLauncherStateController.isTaskbarAlignedWithHotseat());
- }
-
public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) {
mTaskbarLauncherStateController.setShouldDelayLauncherStateAnim(
shouldDelayLauncherStateAnim);
@@ -453,6 +447,16 @@
}
@Override
+ public boolean isHotseatVisibleForTaskBarAlignment() {
+ return mTaskbarLauncherStateController.isHotseatVisibleForTaskbarAlignment();
+ }
+
+ @Override
+ public boolean isAnimatingToLauncher() {
+ return mTaskbarLauncherStateController.isAnimatingToLauncher();
+ }
+
+ @Override
protected boolean isInOverviewUi() {
return mTaskbarLauncherStateController.isInOverviewUi();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 685c109..1141a01 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -47,6 +47,7 @@
import com.android.internal.policy.GestureNavigationSettingsObserver
import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
+import com.android.launcher3.Utilities
import com.android.launcher3.anim.AlphaUpdateListener
import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION
import com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate
@@ -82,7 +83,7 @@
context.mainThreadHandler,
Executors.UI_HELPER_EXECUTOR.handler,
context,
- this::onTaskbarOrBubblebarWindowHeightOrInsetsChanged
+ this::onTaskbarOrBubblebarWindowHeightOrInsetsChanged,
)
private val debugTouchableRegion = DebugTouchableRegion()
@@ -120,7 +121,7 @@
if (enableTaskbarNoRecreate() && controllers.sharedState != null) {
getProvidedInsets(
controllers.sharedState!!.insetsFrameProviders,
- insetsRoundedCornerFlag
+ insetsRoundedCornerFlag,
)
} else {
getProvidedInsets(insetsRoundedCornerFlag)
@@ -133,9 +134,6 @@
}
val bubbleControllers = controllers.bubbleControllers.getOrNull()
- val taskbarTouchableHeight = taskbarStashController.touchableHeight
- val bubblesTouchableHeight =
- bubbleControllers?.bubbleStashController?.getTouchableHeight() ?: 0
// reset touch bounds
defaultTouchableRegion.setEmpty()
if (bubbleControllers != null) {
@@ -147,16 +145,45 @@
defaultTouchableRegion.addBoundsToRegion(bubbleBarViewController.bubbleBarBounds)
}
}
+ val uiController = controllers.uiController
if (
- taskbarStashController.isInApp ||
- taskbarStashController.isInOverview ||
+ !uiController.isHotseatVisibleForTaskBarAlignment ||
DisplayController.showLockedTaskbarOnHome(context)
) {
- // only add the taskbar touch region if not on home
+ // adding the taskbar touch region
+ val touchableHeight: Int
+ var left = 0
+ var right = context.deviceProfile.widthPx
+ var bubbleBarAdjustment = 0
+ if (uiController.isAnimatingToLauncher) {
+ val dp = controllers.taskbarActivityContext.deviceProfile
+ touchableHeight = windowLayoutParams.height
+ if (dp.isQsbInline) {
+ // if Qsb is inline need to exclude search icon from touch region
+ val isRtl = Utilities.isRtl(context.resources)
+ bubbleControllers?.bubbleBarViewController?.let {
+ if (dp.shouldAdjustHotseatOnBubblesLocationUpdate(context)) {
+ val isBubblesOnLeft = it.bubbleBarLocation.isOnLeft(isRtl)
+ bubbleBarAdjustment =
+ dp.getHotseatTranslationXForBubbleBar(isBubblesOnLeft, isRtl)
+ }
+ }
+ val hotseatPadding: Rect = dp.getHotseatLayoutPadding(context)
+ val borderSpacing: Int = dp.hotseatBorderSpace
+ if (isRtl) {
+ right =
+ dp.widthPx - hotseatPadding.right + borderSpacing + bubbleBarAdjustment
+ } else {
+ left = hotseatPadding.left - borderSpacing + bubbleBarAdjustment
+ }
+ }
+ } else {
+ // if not animating to launcher use the taskbar touchanle height
+ touchableHeight = taskbarStashController.touchableHeight
+ }
val bottom = windowLayoutParams.height
- val top = bottom - taskbarTouchableHeight
- val right = context.deviceProfile.widthPx
- defaultTouchableRegion.addBoundsToRegion(Rect(/* left= */ 0, top, right, bottom))
+ val top = bottom - touchableHeight
+ defaultTouchableRegion.addBoundsToRegion(Rect(left, top, right, bottom))
}
// Pre-calculate insets for different providers across different rotations for this gravity
@@ -181,7 +208,7 @@
*/
private fun getProvidedInsets(
providedInsets: Array<InsetsFrameProvider>,
- insetsRoundedCornerFlag: Int
+ insetsRoundedCornerFlag: Int,
): Array<InsetsFrameProvider> {
val navBarsFlag =
(if (context.isGestureNav) FLAG_SUPPRESS_SCRIM else 0) or insetsRoundedCornerFlag
@@ -207,14 +234,14 @@
InsetsFrameProvider(insetsOwner, 0, navigationBars())
.setFlags(
navBarsFlag,
- FLAG_SUPPRESS_SCRIM or FLAG_ANIMATE_RESIZING or FLAG_INSETS_ROUNDED_CORNER
+ FLAG_SUPPRESS_SCRIM or FLAG_ANIMATE_RESIZING or FLAG_INSETS_ROUNDED_CORNER,
),
InsetsFrameProvider(insetsOwner, 0, tappableElement()),
InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()),
InsetsFrameProvider(insetsOwner, INDEX_LEFT, systemGestures())
.setSource(SOURCE_DISPLAY),
InsetsFrameProvider(insetsOwner, INDEX_RIGHT, systemGestures())
- .setSource(SOURCE_DISPLAY)
+ .setSource(SOURCE_DISPLAY),
)
}
@@ -232,7 +259,7 @@
val gestureHeight =
ResourceUtils.getNavbarSize(
ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
- context.resources
+ context.resources,
)
val isPinnedTaskbar =
context.deviceProfile.isTaskbarPresent &&
@@ -272,8 +299,8 @@
// override below (insetsSizeOverrides must have the same length and
// types after the window is added according to
// WindowManagerService#relayoutWindow)
- provider.insetsSize
- )
+ provider.insetsSize,
+ ),
)
// Use 0 tappableElement insets for the VoiceInteractionWindow when gesture nav is enabled.
val visInsetsSizeForTappableElement =
@@ -284,7 +311,7 @@
InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize),
InsetsFrameProvider.InsetsSizeOverride(
TYPE_VOICE_INTERACTION,
- visInsetsSizeForTappableElement
+ visInsetsSizeForTappableElement,
),
)
if (
@@ -368,10 +395,6 @@
// Let touches pass through us.
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
debugTouchableRegion.lastSetTouchableReason = "Stashed over IME"
- } else if (!controllers.uiController.isTaskbarTouchable) {
- // Let touches pass through us.
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
- debugTouchableRegion.lastSetTouchableReason = "Taskbar is not touchable"
} else if (controllers.taskbarDragController.isSystemDragInProgress) {
// Let touches pass through us.
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
@@ -427,7 +450,7 @@
// Always have nav buttons be touchable
controllers.navbarButtonsViewController.addVisibleButtonsRegion(
context.dragLayer,
- insetsInfo.touchableRegion
+ insetsInfo.touchableRegion,
)
debugTouchableRegion.lastSetTouchableBounds.set(insetsInfo.touchableRegion.bounds)
context.excludeFromMagnificationRegion(insetsIsTouchableRegion)
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 707d4b3..39aef28 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -192,6 +192,8 @@
private boolean mIsQsbInline;
+ private boolean mIsHotseatVisibleForTaskbarAlignment;
+
private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
new DeviceProfile.OnDeviceProfileChangeListener() {
@Override
@@ -738,6 +740,7 @@
boolean committed) {
boolean isInStashedState = mLauncherState.isTaskbarStashed(mLauncher);
TaskbarStashController stashController = mControllers.taskbarStashController;
+ TaskbarInsetsController insetsController = mControllers.taskbarInsetsController;
stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE, isInStashedState);
Animator stashAnimator = stashController.createApplyStateAnimator(duration);
if (stashAnimator != null) {
@@ -746,7 +749,11 @@
public void onAnimationEnd(Animator animation) {
if (isInStashedState && committed) {
// Reset hotseat alpha to default
- mLauncher.getHotseat().setIconsAlpha(1, ALPHA_CHANNEL_TASKBAR_ALIGNMENT);
+ updateIconAlphaForHome(
+ /* taskbarAlpha = */ 0,
+ ALPHA_CHANNEL_TASKBAR_ALIGNMENT,
+ /* updateTaskbarAlpha = */ false
+ );
}
}
@@ -871,6 +878,14 @@
if (mIsQsbInline) {
mLauncher.getHotseat().setQsbAlpha(targetAlpha, alphaChannel);
}
+ if (alphaChannel == ALPHA_CHANNEL_TASKBAR_ALIGNMENT) {
+ boolean isHotseatVisibleForTaskbarAlignment = isHotseatVisibleForTaskbarAlignment();
+ if (mIsHotseatVisibleForTaskbarAlignment != isHotseatVisibleForTaskbarAlignment) {
+ mIsHotseatVisibleForTaskbarAlignment = isHotseatVisibleForTaskbarAlignment;
+ mControllers.taskbarInsetsController
+ .onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
+ }
+ }
}
/** Updates launcher home screen appearance accordingly to the bubble bar location. */
@@ -932,6 +947,13 @@
translationXAnimation.start();
}
+ /** Returns true if hotseat icons visible for the taskbar alignment */
+ public boolean isHotseatVisibleForTaskbarAlignment() {
+ return mLauncher.getHotseat()
+ .getIconsAlpha(ALPHA_CHANNEL_TASKBAR_ALIGNMENT).getValue() == 1;
+ }
+
+
private final class TaskBarRecentsAnimationListener implements
RecentsAnimationCallbacks.RecentsAnimationListener {
private final RecentsAnimationCallbacks mCallbacks;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 7030088..db69e8f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -75,8 +75,14 @@
mControllers = null;
}
- protected boolean isTaskbarTouchable() {
- return true;
+ /** Returns true if transition animation to launcher home is being played. */
+ public boolean isAnimatingToLauncher() {
+ return false;
+ }
+
+ /** Returns true if hotseat icons visible for the taskbar alignment. */
+ public boolean isHotseatVisibleForTaskBarAlignment() {
+ return false;
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 70dcfe8..f8adf8e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -185,7 +185,6 @@
resources.getDrawable(R.drawable.taskbar_overflow_icon));
mTaskbarOverflowView.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
}
- // TODO: Disable touch events on QSB otherwise it can crash.
mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
mMaxNumIcons = calculateMaxNumIcons();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index c4d9e50..c275536 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -23,7 +23,6 @@
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
-import static com.android.launcher3.Utilities.isRtl;
import static com.android.launcher3.Utilities.mapRange;
import static com.android.launcher3.anim.AnimatedFloat.VALUE;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
@@ -938,10 +937,12 @@
mTaskbarView.isDividerForRecents(), recentTaskIndex);
if (positionInHotseat == ERROR_POSITION_IN_HOTSEAT_NOT_FOUND) continue;
- float hotseatAdjustedBorderSpace =
- launcherDp.getHotseatAdjustedBorderSpaceForBubbleBar(child.getContext());
+
float hotseatIconCenter;
- if (bubbleBarHasBubbles() && hotseatAdjustedBorderSpace != 0) {
+ if (launcherDp.shouldAdjustHotseatForBubbleBar(child.getContext(),
+ bubbleBarHasBubbles())) {
+ float hotseatAdjustedBorderSpace =
+ launcherDp.getHotseatAdjustedBorderSpaceForBubbleBar(child.getContext());
hotseatIconCenter = hotseatPadding.left + hotseatCellSize
+ (hotseatCellSize + hotseatAdjustedBorderSpace) * positionInHotseat
+ hotseatCellSize / 2f;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index ce4e980..acdff71 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -1106,15 +1106,10 @@
translationX += mDeviceProfile
.getHotseatTranslationXForBubbleBar(isBubblesOnLeft, isRtl);
}
- if (isBubbleBarEnabled() && hasBubbles()) {
- // TODO(368379159) : create a class to reuse computation logic
- float adjustedBorderSpace =
- mDeviceProfile.getHotseatAdjustedBorderSpaceForBubbleBar(this);
- if (Float.compare(adjustedBorderSpace, 0f) != 0) {
- float borderSpaceDelta = adjustedBorderSpace - mDeviceProfile.hotseatBorderSpace;
- translationX +=
- (int) (mDeviceProfile.iconSizePx + itemInfo.cellX * borderSpaceDelta);
- }
+ if (isBubbleBarEnabled()
+ && mDeviceProfile.shouldAdjustHotseatForBubbleBar(getContext(), hasBubbles())) {
+ translationX += (int) mDeviceProfile
+ .getHotseatAdjustedTranslation(getContext(), itemInfo.cellX);
}
return translationX;
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java
index c18f604..98a3607 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java
@@ -92,14 +92,15 @@
when(mTopTaskTracker.getCachedTopTask(anyBoolean())).thenReturn(mTaskInfo);
when(mDeviceState.getSquaredTouchSlop()).thenReturn(SQUARED_TOUCH_SLOP);
when(mDelegate.allowInterceptByParent()).thenReturn(true);
- MAIN_EXECUTOR.getHandler().removeCallbacks(mLongPressRunnable);
mLongPressTriggered.set(false);
when(mNavHandleLongPressHandler.getLongPressRunnable(any())).thenReturn(mLongPressRunnable);
initializeObjectUnderTest();
}
@After
- public void tearDown() {
+ public void tearDown() throws Exception {
+ MAIN_EXECUTOR.getHandler().removeCallbacks(mLongPressRunnable);
+ MAIN_EXECUTOR.submit(() -> null).get();
mContext.onDestroy();
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 1e7fd7f..afe0ee1 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -1829,19 +1829,14 @@
* Returns the new border space that should be used between hotseat icons after adjusting it to
* the bubble bar.
*
+ * <p>Does not check for visible bubbles persistence, so caller should call
+ * {@link #shouldAdjustHotseatForBubbleBar} first.
+ *
* <p>If there's no adjustment needed, this method returns {@code 0}.
+ * @see #shouldAdjustHotseatForBubbleBar(Context, boolean)
*/
public float getHotseatAdjustedBorderSpaceForBubbleBar(Context context) {
- // only need to adjust when QSB is on top of the hotseat.
- if (isQsbInline) {
- return 0;
- }
-
- // no need to adjust if there's enough space for the bubble bar to the right of the hotseat.
- if (getHotseatLayoutPadding(context).right > mBubbleBarSpaceThresholdPx) {
- return 0;
- }
-
+ if (!shouldAdjustHotseatForBubbleBar(context)) return 0;
// The adjustment is shrinking the hotseat's width by 1 icon on either side.
int iconsWidth =
iconSizePx * numShownHotseatIcons + hotseatBorderSpace * (numShownHotseatIcons - 1);
@@ -1851,6 +1846,33 @@
}
/**
+ * Returns the hotseat icon translation X for the cellX index.
+ *
+ * <p>Does not check for visible bubbles persistence, so caller should call
+ * {@link #shouldAdjustHotseatForBubbleBar} first.
+ *
+ * <p>If there's no adjustment needed, this method returns {@code 0}.
+ * @see #shouldAdjustHotseatForBubbleBar(Context, boolean)
+ */
+ public float getHotseatAdjustedTranslation(Context context, int cellX) {
+ if (!shouldAdjustHotseatForBubbleBar(context)) return 0;
+ float borderSpace = getHotseatAdjustedBorderSpaceForBubbleBar(context);
+ float borderSpaceDelta = borderSpace - hotseatBorderSpace;
+ return iconSizePx + cellX * borderSpaceDelta;
+ }
+
+ /** Returns whether hotseat should be adjusted for the bubble bar. */
+ public boolean shouldAdjustHotseatForBubbleBar(Context context, boolean hasBubbles) {
+ return hasBubbles && shouldAdjustHotseatForBubbleBar(context);
+ }
+
+ private boolean shouldAdjustHotseatForBubbleBar(Context context) {
+ // only need to adjust if bubble bar is enabled, when QSB is on top of the hotseat and
+ // there's not enough space for the bubble bar to the right of the hotseat.
+ return !isQsbInline && getHotseatLayoutPadding(context).right <= mBubbleBarSpaceThresholdPx;
+ }
+
+ /**
* Returns the padding for hotseat view
*/
public Rect getHotseatLayoutPadding(Context context) {
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index ae4c122..6b478be 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -149,12 +149,9 @@
DeviceProfile dp = mActivity.getDeviceProfile();
if (bubbleBarEnabled) {
- float adjustedBorderSpace = dp.getHotseatAdjustedBorderSpaceForBubbleBar(getContext());
- if (hasBubbles && Float.compare(adjustedBorderSpace, 0f) != 0) {
- getShortcutsAndWidgets().setTranslationProvider(cellX -> {
- float borderSpaceDelta = adjustedBorderSpace - dp.hotseatBorderSpace;
- return dp.iconSizePx + cellX * borderSpaceDelta;
- });
+ if (dp.shouldAdjustHotseatForBubbleBar(getContext(), hasBubbles)) {
+ getShortcutsAndWidgets().setTranslationProvider(
+ cellX -> dp.getHotseatAdjustedTranslation(getContext(), cellX));
if (mQsb instanceof HorizontalInsettableView) {
HorizontalInsettableView insettableQsb = (HorizontalInsettableView) mQsb;
final float insetFraction = (float) dp.iconSizePx / dp.hotseatQsbWidth;
@@ -189,25 +186,24 @@
*/
public void adjustForBubbleBar(boolean isBubbleBarVisible) {
DeviceProfile dp = mActivity.getDeviceProfile();
- float adjustedBorderSpace = dp.getHotseatAdjustedBorderSpaceForBubbleBar(getContext());
- if (Float.compare(adjustedBorderSpace, 0f) == 0) {
+ if (!dp.shouldAdjustHotseatForBubbleBar(getContext(), isBubbleBarVisible)) {
return;
}
ShortcutAndWidgetContainer icons = getShortcutsAndWidgets();
AnimatorSet animatorSet = new AnimatorSet();
- float borderSpaceDelta = adjustedBorderSpace - dp.hotseatBorderSpace;
// update the translation provider for future layout passes of hotseat icons.
if (isBubbleBarVisible) {
- icons.setTranslationProvider(cellX -> dp.iconSizePx + cellX * borderSpaceDelta);
+ icons.setTranslationProvider(
+ cellX -> dp.getHotseatAdjustedTranslation(getContext(), cellX));
} else {
icons.setTranslationProvider(null);
}
for (int i = 0; i < icons.getChildCount(); i++) {
View child = icons.getChildAt(i);
- float tx = isBubbleBarVisible ? dp.iconSizePx + i * borderSpaceDelta : 0;
+ float tx = isBubbleBarVisible ? dp.getHotseatAdjustedTranslation(getContext(), i) : 0;
if (child instanceof Reorderable) {
MultiTranslateDelegate mtd = ((Reorderable) child).getTranslateDelegate();
animatorSet.play(
diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
index 088277b..c3508b7 100644
--- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
+++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
@@ -22,6 +22,7 @@
import com.android.launcher3.util.DaggerSingletonTracker;
import com.android.launcher3.util.ScreenOnTracker;
import com.android.launcher3.util.SettingsCache;
+import com.android.launcher3.widget.custom.CustomWidgetManager;
import dagger.BindsInstance;
@@ -38,6 +39,7 @@
InstallSessionHelper getInstallSessionHelper();
ScreenOnTracker getScreenOnTracker();
SettingsCache getSettingsCache();
+ CustomWidgetManager getCustomWidgetManager();
/** Builder for LauncherBaseAppComponent. */
interface Builder {
diff --git a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
index faa5d12..0778172 100644
--- a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
+++ b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
@@ -33,7 +33,12 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.R;
-import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.dagger.ApplicationContext;
+import com.android.launcher3.dagger.LauncherAppSingleton;
+import com.android.launcher3.dagger.LauncherBaseAppComponent;
+import com.android.launcher3.util.DaggerSingletonObject;
+import com.android.launcher3.util.DaggerSingletonTracker;
+import com.android.launcher3.util.ExecutorUtil;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.PluginManagerWrapper;
import com.android.launcher3.util.SafeCloseable;
@@ -50,13 +55,16 @@
import java.util.function.Consumer;
import java.util.stream.Stream;
+import javax.inject.Inject;
+
/**
* CustomWidgetManager handles custom widgets implemented as a plugin.
*/
+@LauncherAppSingleton
public class CustomWidgetManager implements PluginListener<CustomWidgetPlugin>, SafeCloseable {
- public static final MainThreadInitializedObject<CustomWidgetManager> INSTANCE =
- new MainThreadInitializedObject<>(CustomWidgetManager::new);
+ public static final DaggerSingletonObject<CustomWidgetManager> INSTANCE =
+ new DaggerSingletonObject<>(LauncherBaseAppComponent::getCustomWidgetManager);
private static final String TAG = "CustomWidgetManager";
private static final String PLUGIN_PKG = "android";
@@ -66,34 +74,44 @@
private Consumer<PackageUserKey> mWidgetRefreshCallback;
private final @NonNull AppWidgetManager mAppWidgetManager;
- private CustomWidgetManager(Context context) {
- this(context, AppWidgetManager.getInstance(context));
+ @Inject
+ CustomWidgetManager(@ApplicationContext Context context, DaggerSingletonTracker tracker) {
+ this(context, AppWidgetManager.getInstance(context), tracker);
}
@VisibleForTesting
- CustomWidgetManager(Context context, @NonNull AppWidgetManager widgetManager) {
+ CustomWidgetManager(@ApplicationContext Context context,
+ @NonNull AppWidgetManager widgetManager,
+ DaggerSingletonTracker tracker) {
mContext = context;
mAppWidgetManager = widgetManager;
mPlugins = new HashMap<>();
mCustomWidgets = new ArrayList<>();
- PluginManagerWrapper.INSTANCE.get(context)
- .addPluginListener(this, CustomWidgetPlugin.class, true);
- if (enableSmartspaceAsAWidget()) {
- for (String s: context.getResources()
- .getStringArray(R.array.custom_widget_providers)) {
- try {
- Class<?> cls = Class.forName(s);
- CustomWidgetPlugin plugin = (CustomWidgetPlugin)
- cls.getDeclaredConstructor(Context.class).newInstance(context);
- onPluginConnected(plugin, context);
- } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
- | ClassCastException | NoSuchMethodException
- | InvocationTargetException e) {
- Log.e(TAG, "Exception found when trying to add custom widgets: " + e);
+
+ ExecutorUtil.executeSyncOnMainOrFail(() -> {
+ PluginManagerWrapper.INSTANCE.get(context)
+ .addPluginListener(this, CustomWidgetPlugin.class, true);
+
+ if (enableSmartspaceAsAWidget()) {
+ for (String s: context.getResources()
+ .getStringArray(R.array.custom_widget_providers)) {
+ try {
+ Class<?> cls = Class.forName(s);
+ CustomWidgetPlugin plugin = (CustomWidgetPlugin)
+ cls.getDeclaredConstructor(Context.class).newInstance(context);
+ onPluginConnected(plugin, context);
+ } catch (ClassNotFoundException | InstantiationException
+ | IllegalAccessException
+ | ClassCastException | NoSuchMethodException
+ | InvocationTargetException e) {
+ Log.e(TAG, "Exception found when trying to add custom widgets: " + e);
+ }
}
}
- }
+
+ tracker.addCloseable(this);
+ });
}
@Override
diff --git a/tests/multivalentTests/src/com/android/launcher3/widget/custom/CustomWidgetManagerTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/custom/CustomWidgetManagerTest.kt
index 4b5710d..82f56b8 100644
--- a/tests/multivalentTests/src/com/android/launcher3/widget/custom/CustomWidgetManagerTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/custom/CustomWidgetManagerTest.kt
@@ -23,6 +23,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import com.android.launcher3.util.DaggerSingletonTracker
import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext
import com.android.launcher3.util.PluginManagerWrapper
import com.android.launcher3.util.WidgetUtils
@@ -57,12 +58,13 @@
@Mock private lateinit var pluginManager: PluginManagerWrapper
@Mock private lateinit var mockAppWidgetManager: AppWidgetManager
+ @Mock private lateinit var tracker: DaggerSingletonTracker
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
context.putObject(PluginManagerWrapper.INSTANCE, pluginManager)
- underTest = CustomWidgetManager(context, mockAppWidgetManager)
+ underTest = CustomWidgetManager(context, mockAppWidgetManager, tracker)
}
@After