Merge "Simplifying some test utility methods" into udc-qpr-dev
diff --git a/quickstep/res/layout/taskbar_all_apps.xml b/quickstep/res/layout/taskbar_all_apps.xml
index 976cd9e..e234165 100644
--- a/quickstep/res/layout/taskbar_all_apps.xml
+++ b/quickstep/res/layout/taskbar_all_apps.xml
@@ -14,18 +14,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView
+<com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:accessibilityPaneTitle="@string/all_apps_label">
-
- <com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView
- android:id="@+id/apps_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="true"
- android:clipToPadding="false"
- android:focusable="false"
- android:saveEnabled="false" />
-</com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView>
+ android:clipChildren="true"
+ android:clipToPadding="false"
+ android:focusable="false"
+ android:saveEnabled="false" />
diff --git a/quickstep/res/layout/taskbar_all_apps_sheet.xml b/quickstep/res/layout/taskbar_all_apps_sheet.xml
new file mode 100644
index 0000000..a1d5fa6
--- /dev/null
+++ b/quickstep/res/layout/taskbar_all_apps_sheet.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 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.
+-->
+<com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:accessibilityPaneTitle="@string/all_apps_label">
+
+ <include
+ android:id="@+id/apps_view"
+ layout="@layout/taskbar_all_apps" />
+</com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView>
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
index b052deb..7283a18 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
@@ -61,7 +61,14 @@
mDesktopTaskListener = new IDesktopTaskListener.Stub() {
@Override
public void onVisibilityChanged(int displayId, boolean visible) {
- // TODO(b/261234402): move visibility from sysui state to listener
+ MAIN_EXECUTOR.execute(() -> {
+ if (displayId == mLauncher.getDisplayId()) {
+ if (DEBUG) {
+ Log.d(TAG, "desktop visibility changed value=" + visible);
+ }
+ setFreeformTasksVisible(visible);
+ }
+ });
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index a1c9f05..9a61c61 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -217,7 +217,7 @@
// If Bubble bar is present, TaskbarControllers depends on it so build it first.
Optional<BubbleControllers> bubbleControllersOptional = Optional.empty();
- if (BubbleBarController.BUBBLE_BAR_ENABLED) {
+ if (BubbleBarController.BUBBLE_BAR_ENABLED && bubbleBarView != null) {
bubbleControllersOptional = Optional.of(new BubbleControllers(
new BubbleBarController(this, bubbleBarView),
new BubbleBarViewController(this, bubbleBarView),
@@ -449,6 +449,11 @@
return mControllers.taskbarDragController;
}
+ @Nullable
+ public BubbleControllers getBubbleControllers() {
+ return mControllers.bubbleControllers.orElse(null);
+ }
+
@Override
public ViewCache getViewCache() {
return mViewCache;
@@ -641,8 +646,12 @@
mControllers.taskbarForceVisibleImmersiveController.updateSysuiFlags(systemUiStateFlags);
mControllers.voiceInteractionWindowController.setIsVoiceInteractionWindowVisible(
(systemUiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0, fromInit);
-
mControllers.uiController.updateStateForSysuiFlags(systemUiStateFlags);
+ mControllers.bubbleControllers.ifPresent(controllers -> {
+ controllers.bubbleBarController.updateStateForSysuiFlags(systemUiStateFlags);
+ controllers.bubbleStashedHandleViewController.setIsHomeButtonDisabled(
+ mControllers.navbarButtonsViewController.isHomeDisabled());
+ });
}
/**
@@ -738,7 +747,7 @@
}
}
mWindowLayoutParams.height = height;
- mControllers.taskbarInsetsController.onTaskbarWindowHeightOrInsetsChanged();
+ mControllers.taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
}
@@ -996,10 +1005,19 @@
* Called when we want to unstash taskbar when user performs swipes up gesture.
*/
public void onSwipeToUnstashTaskbar() {
- mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(false);
+ mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(/* stash= */ false);
mControllers.taskbarEduTooltipController.hide();
}
+ /**
+ * Called when we want to open bubblebar when user performs swipes up gesture.
+ */
+ public void onSwipeToOpenBubblebar() {
+ mControllers.bubbleControllers.ifPresent(controllers -> {
+ controllers.bubbleStashController.showBubbleBar(/* expandBubbles= */ true);
+ });
+ }
+
/** Returns {@code true} if Taskbar All Apps is open. */
public boolean isTaskbarAllAppsOpen() {
return mControllers.taskbarAllAppsController.isOpen();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 66c2eb3..3cd151d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -226,6 +226,7 @@
taskbarPopupController.onDestroy();
taskbarForceVisibleImmersiveController.onDestroy();
taskbarOverlayController.onDestroy();
+ taskbarAllAppsController.onDestroy();
navButtonController.onDestroy();
taskbarInsetsController.onDestroy();
voiceInteractionWindowController.onDestroy();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 4f9b1e4..07cd8ff 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -56,13 +56,13 @@
private val touchableRegion: Region = Region()
private val insetsOwner: IBinder = Binder()
private val deviceProfileChangeListener = { _: DeviceProfile ->
- onTaskbarWindowHeightOrInsetsChanged()
+ onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
}
private val gestureNavSettingsObserver =
GestureNavigationSettingsObserver(
context.mainThreadHandler,
context,
- this::onTaskbarWindowHeightOrInsetsChanged
+ this::onTaskbarOrBubblebarWindowHeightOrInsetsChanged
)
// Initialized in init.
@@ -72,7 +72,7 @@
fun init(controllers: TaskbarControllers) {
this.controllers = controllers
windowLayoutParams = context.windowLayoutParams
- onTaskbarWindowHeightOrInsetsChanged()
+ onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
context.addOnDeviceProfileChangeListener(deviceProfileChangeListener)
gestureNavSettingsObserver.registerForCallingUser()
@@ -83,7 +83,7 @@
gestureNavSettingsObserver.unregister()
}
- fun onTaskbarWindowHeightOrInsetsChanged() {
+ fun onTaskbarOrBubblebarWindowHeightOrInsetsChanged() {
val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
// We only report tappableElement height for unstashed, persistent taskbar,
// which is also when we draw the rounded corners above taskbar.
@@ -121,13 +121,33 @@
)
}
- val touchableHeight = controllers.taskbarStashController.touchableHeight
- touchableRegion.set(
- 0,
- windowLayoutParams.height - touchableHeight,
- context.deviceProfile.widthPx,
- windowLayoutParams.height
- )
+ val taskbarTouchableHeight = controllers.taskbarStashController.touchableHeight
+ val bubblesTouchableHeight =
+ if (controllers.bubbleControllers.isPresent)
+ controllers.bubbleControllers.get().bubbleStashController.touchableHeight
+ else 0
+ val touchableHeight = Math.max(taskbarTouchableHeight, bubblesTouchableHeight)
+
+ if (
+ controllers.bubbleControllers.isPresent &&
+ controllers.bubbleControllers.get().bubbleStashController.isBubblesShowingOnHome
+ ) {
+ val iconBounds =
+ controllers.bubbleControllers.get().bubbleBarViewController.bubbleBarBounds
+ touchableRegion.set(
+ iconBounds.left,
+ iconBounds.top,
+ iconBounds.right,
+ iconBounds.bottom
+ )
+ } else {
+ touchableRegion.set(
+ 0,
+ windowLayoutParams.height - touchableHeight,
+ context.deviceProfile.widthPx,
+ windowLayoutParams.height
+ )
+ }
val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps
val res = context.resources
for (provider in windowLayoutParams.providedInsets) {
@@ -211,6 +231,9 @@
context.dragLayer,
insetsInfo.touchableRegion
)
+ val bubbleBarVisible =
+ controllers.bubbleControllers.isPresent &&
+ controllers.bubbleControllers.get().bubbleBarViewController.isBubbleBarVisible()
var insetsIsTouchableRegion = true
if (context.dragLayer.alpha < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
// Let touches pass through us.
@@ -231,7 +254,9 @@
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME)
insetsIsTouchableRegion = false
} else if (
- controllers.taskbarViewController.areIconsVisible() || context.isNavBarKidsModeActive
+ controllers.taskbarViewController.areIconsVisible() ||
+ context.isNavBarKidsModeActive ||
+ bubbleBarVisible
) {
// Taskbar has some touchable elements, take over the full taskbar area
if (
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 008f5f6..122745c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -404,6 +404,14 @@
+ ", mLauncherState: " + mLauncherState
+ ", toAlignment: " + toAlignment);
}
+ mControllers.bubbleControllers.ifPresent(controllers -> {
+ // Show the bubble bar when on launcher home or in overview.
+ boolean onHome = isInLauncher && mLauncherState == LauncherState.NORMAL;
+ boolean onOverview = mLauncherState == LauncherState.OVERVIEW;
+ controllers.bubbleStashController.setBubblesShowingOnHome(onHome);
+ controllers.bubbleStashController.setBubblesShowingOnOverview(onOverview);
+ });
+
AnimatorSet animatorSet = new AnimatorSet();
if (hasAnyFlag(changedFlags, FLAG_LAUNCHER_IN_STATE_TRANSITION)) {
@@ -474,7 +482,8 @@
public void onAnimationEnd(Animator animation) {
TaskbarStashController stashController =
mControllers.taskbarStashController;
- stashController.updateAndAnimateTransientTaskbar(/* stash */ true);
+ stashController.updateAndAnimateTransientTaskbar(
+ /* stash */ true, /* bubblesShouldFollow */ true);
}
});
} else {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 5ea00cf..1c250bf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.launcher3.taskbar.bubbles.BubbleBarController.BUBBLE_BAR_ENABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED;
@@ -23,6 +24,7 @@
import android.view.animation.PathInterpolator;
import com.android.launcher3.anim.AnimatedFloat;
+import com.android.launcher3.util.DisplayController;
import com.android.quickstep.SystemUiProxy;
import java.io.PrintWriter;
@@ -63,6 +65,10 @@
* Updates the scrim state based on the flags.
*/
public void updateStateForSysuiFlags(int stateFlags, boolean skipAnim) {
+ if (BUBBLE_BAR_ENABLED && DisplayController.isTransientTaskbar(mActivity)) {
+ // These scrims aren't used if bubble bar & transient taskbar are active.
+ return;
+ }
final boolean bubblesExpanded = (stateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0;
final boolean manageMenuExpanded =
(stateFlags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 85d10b4..24d2b0b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -255,14 +255,15 @@
private boolean mEnableBlockingTimeoutDuringTests = false;
// Evaluate whether the handle should be stashed
+ private final IntPredicate mIsStashedPredicate = flags -> {
+ boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
+ boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
+ boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
+ boolean forceStashed = hasAnyFlag(flags, FLAGS_FORCE_STASHED);
+ return (inApp && stashedInApp) || (!inApp && stashedLauncherState) || forceStashed;
+ };
private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
- flags -> {
- boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
- boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
- boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
- boolean forceStashed = hasAnyFlag(flags, FLAGS_FORCE_STASHED);
- return (inApp && stashedInApp) || (!inApp && stashedLauncherState) || forceStashed;
- });
+ mIsStashedPredicate);
private boolean mIsTaskbarSystemActionRegistered = false;
private TaskbarSharedState mTaskbarSharedState;
@@ -501,9 +502,19 @@
}
/**
- * Stash or unstashes the transient taskbar.
+ * Stash or unstashes the transient taskbar, using the default TASKBAR_STASH_DURATION.
+ * If bubble bar exists, it will match taskbars stashing behavior.
*/
public void updateAndAnimateTransientTaskbar(boolean stash) {
+ updateAndAnimateTransientTaskbar(stash, /* shouldBubblesFollow= */ true);
+ }
+
+ /**
+ * Stash or unstashes the transient taskbar.
+ * @param stash whether transient taskbar should be stashed.
+ * @param shouldBubblesFollow whether bubbles should match taskbars behavior.
+ */
+ public void updateAndAnimateTransientTaskbar(boolean stash, boolean shouldBubblesFollow) {
if (!DisplayController.isTransientTaskbar(mActivity)) {
return;
}
@@ -519,6 +530,34 @@
updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, stash);
applyState();
}
+
+ mControllers.bubbleControllers.ifPresent(controllers -> {
+ if (shouldBubblesFollow) {
+ final boolean willStash = mIsStashedPredicate.test(mState);
+ if (willStash != controllers.bubbleStashController.isStashed()) {
+ // Typically bubbles gets stashed / unstashed along with Taskbar, however, if
+ // taskbar is becoming stashed because bubbles is being expanded, we don't want
+ // to stash bubbles.
+ if (willStash) {
+ controllers.bubbleStashController.stashBubbleBar();
+ } else {
+ controllers.bubbleStashController.showBubbleBar(false /* expandBubbles */);
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Stashes transient taskbar after it has timed out.
+ */
+ private void updateAndAnimateTransientTaskbarForTimeout() {
+ // If bubbles are expanded we shouldn't stash them when taskbar is hidden
+ // for the timeout.
+ boolean bubbleBarExpanded = mControllers.bubbleControllers.isPresent()
+ && mControllers.bubbleControllers.get().bubbleBarViewController.isExpanded();
+ updateAndAnimateTransientTaskbar(/* stash= */ true,
+ /* shouldBubblesFollow= */ !bubbleBarExpanded);
}
/**
@@ -889,7 +928,7 @@
private void onIsStashedChanged(boolean isStashed) {
mControllers.runAfterInit(() -> {
mControllers.stashedHandleViewController.onIsStashedChanged(isStashed);
- mControllers.taskbarInsetsController.onTaskbarWindowHeightOrInsetsChanged();
+ mControllers.taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
});
}
@@ -1136,7 +1175,7 @@
if (mControllers.taskbarAutohideSuspendController.isSuspended()) {
return;
}
- updateAndAnimateTransientTaskbar(true);
+ updateAndAnimateTransientTaskbarForTimeout();
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
index ec93846..deaf024 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
@@ -108,7 +108,17 @@
}
override fun onControllerInterceptTouchEvent(ev: MotionEvent): Boolean {
- if (!enabled || controllers.taskbarStashController.isStashed) {
+ if (!enabled) {
+ return false
+ }
+ val bubbleControllers = controllers.bubbleControllers.orElse(null)
+ if (bubbleControllers != null && bubbleControllers.bubbleBarViewController.isExpanded) {
+ return false
+ }
+ if (
+ (bubbleControllers == null || bubbleControllers.bubbleStashController.isStashed) &&
+ controllers.taskbarStashController.isStashed
+ ) {
return false
}
@@ -122,7 +132,12 @@
return true
}
} else if (ev.action == MotionEvent.ACTION_DOWN) {
- if (screenCoordinatesEv.y < gestureHeightYThreshold) {
+ val isDownOnBubbleBar =
+ (bubbleControllers != null &&
+ bubbleControllers.bubbleBarViewController.isEventOverAnyItem(
+ screenCoordinatesEv
+ ))
+ if (!isDownOnBubbleBar && screenCoordinatesEv.y < gestureHeightYThreshold) {
controllers.taskbarStashController.updateAndAnimateTransientTaskbar(true)
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
index 2b4e67c..916b1e6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
@@ -92,6 +92,10 @@
mControllers.stashedHandleViewController.setTranslationYForSwipe(transY);
mControllers.taskbarViewController.setTranslationYForSwipe(transY);
mControllers.taskbarDragLayerController.setTranslationYForSwipe(transY);
+ mControllers.bubbleControllers.ifPresent(controllers -> {
+ controllers.bubbleBarViewController.setTranslationYForSwipe(transY);
+ controllers.bubbleStashedHandleViewController.setTranslationYForSwipe(transY);
+ });
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
index e0a502b..4ac779f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -45,8 +45,10 @@
public final class TaskbarAllAppsController {
private TaskbarControllers mControllers;
+ private @Nullable TaskbarOverlayContext mOverlayContext;
private @Nullable TaskbarAllAppsSlideInView mSlideInView;
private @Nullable TaskbarAllAppsContainerView mAppsView;
+ private @Nullable TaskbarSearchSessionController mSearchSessionController;
// Application data models.
private AppInfo[] mApps;
@@ -70,6 +72,11 @@
}
}
+ /** Clean up the controller. */
+ public void onDestroy() {
+ cleanUpOverlay();
+ }
+
/** Updates the current {@link AppInfo} instances. */
public void setApps(AppInfo[] apps, int flags, Map<PackageUserKey, Integer> map) {
mApps = apps;
@@ -96,6 +103,9 @@
.findFixedRowByType(PredictionRowView.class)
.setPredictedApps(mPredictedApps);
}
+ if (mSearchSessionController != null) {
+ mSearchSessionController.setZeroStatePredictedItems(predictedApps);
+ }
}
/** Updates the current notification dots. */
@@ -127,20 +137,25 @@
// to catch invalid states.
mControllers.getSharedState().allAppsVisible = true;
- TaskbarOverlayContext overlayContext =
- mControllers.taskbarOverlayController.requestWindow();
- mSlideInView = (TaskbarAllAppsSlideInView) overlayContext.getLayoutInflater().inflate(
- R.layout.taskbar_all_apps, overlayContext.getDragLayer(), false);
+ mOverlayContext = mControllers.taskbarOverlayController.requestWindow();
+
+ // Initialize search session for All Apps.
+ mSearchSessionController = TaskbarSearchSessionController.newInstance(mOverlayContext);
+ mOverlayContext.setSearchSessionController(mSearchSessionController);
+ mSearchSessionController.setZeroStatePredictedItems(mPredictedApps);
+ mSearchSessionController.startLifecycle();
+
+ mSlideInView = (TaskbarAllAppsSlideInView) mOverlayContext.getLayoutInflater().inflate(
+ R.layout.taskbar_all_apps_sheet, mOverlayContext.getDragLayer(), false);
mSlideInView.addOnCloseListener(() -> {
mControllers.getSharedState().allAppsVisible = false;
- mSlideInView = null;
- mAppsView = null;
+ cleanUpOverlay();
});
TaskbarAllAppsViewController viewController = new TaskbarAllAppsViewController(
- overlayContext, mSlideInView, mControllers);
+ mOverlayContext, mSlideInView, mControllers);
viewController.show(animate);
- mAppsView = overlayContext.getAppsView();
+ mAppsView = mOverlayContext.getAppsView();
mAppsView.getAppsStore().setApps(mApps, mAppsModelFlags, mPackageUserKeytoUidMap);
mAppsView.getFloatingHeaderView()
.findFixedRowByType(PredictionRowView.class)
@@ -149,8 +164,21 @@
// Create a shared drag layer between taskbar and taskbarAllApps so that when dragging
// starts and taskbarAllApps can close, but the drag layer that the view is being dragged in
// doesn't also close
- overlayContext.getDragController().setDisallowGlobalDrag(mDisallowGlobalDrag);
- overlayContext.getDragController().setDisallowLongClick(mDisallowLongClick);
+ mOverlayContext.getDragController().setDisallowGlobalDrag(mDisallowGlobalDrag);
+ mOverlayContext.getDragController().setDisallowLongClick(mDisallowLongClick);
+ }
+
+ private void cleanUpOverlay() {
+ if (mSearchSessionController != null) {
+ mSearchSessionController.onDestroy();
+ mSearchSessionController = null;
+ }
+ if (mOverlayContext != null) {
+ mOverlayContext.setSearchSessionController(null);
+ mOverlayContext = null;
+ }
+ mSlideInView = null;
+ mAppsView = null;
}
@VisibleForTesting
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarSearchSessionController.kt b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarSearchSessionController.kt
new file mode 100644
index 0000000..6a9dda5
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarSearchSessionController.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 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.taskbar.allapps
+
+import android.content.Context
+import com.android.launcher3.R
+import com.android.launcher3.config.FeatureFlags
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.util.ResourceBasedOverride
+import com.android.launcher3.util.ResourceBasedOverride.Overrides
+
+/** Stub for managing the Taskbar search session. */
+open class TaskbarSearchSessionController : ResourceBasedOverride {
+
+ /** Start the search session lifecycle. */
+ open fun startLifecycle() {}
+
+ /** Destroy the search session. */
+ open fun onDestroy() {}
+
+ /** Updates the predicted items shown in the zero-state. */
+ open fun setZeroStatePredictedItems(items: List<ItemInfo>) {}
+
+ companion object {
+ @JvmStatic
+ fun newInstance(context: Context): TaskbarSearchSessionController {
+ if (!FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
+ return TaskbarSearchSessionController()
+ }
+
+ return Overrides.getObject(
+ TaskbarSearchSessionController::class.java,
+ context,
+ R.string.taskbar_search_session_controller_class,
+ )
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 82494c6..3786189 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -28,6 +28,8 @@
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.launcher3.taskbar.TaskbarInsetsController;
+import com.android.launcher3.taskbar.TaskbarStashController;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.SystemUiProxy;
@@ -51,6 +53,8 @@
// Initialized in init.
private BubbleStashController mBubbleStashController;
private BubbleBarController mBubbleBarController;
+ private TaskbarStashController mTaskbarStashController;
+ private TaskbarInsetsController mTaskbarInsetsController;
private View.OnClickListener mBubbleClickListener;
private View.OnClickListener mBubbleBarClickListener;
@@ -80,6 +84,8 @@
public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
mBubbleStashController = bubbleControllers.bubbleStashController;
mBubbleBarController = bubbleControllers.bubbleBarController;
+ mTaskbarStashController = controllers.taskbarStashController;
+ mTaskbarInsetsController = controllers.taskbarInsetsController;
mActivity.addOnDeviceProfileChangeListener(dp ->
mBarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarHeight
@@ -89,7 +95,9 @@
mBubbleClickListener = v -> onBubbleClicked(v);
mBubbleBarClickListener = v -> setExpanded(true);
mBarView.setOnClickListener(mBubbleBarClickListener);
- // TODO: when barView layout changes tell taskbarInsetsController the insets have changed.
+ mBarView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
+ mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
+ );
}
private void onBubbleClicked(View v) {
@@ -283,7 +291,8 @@
} else {
Log.w(TAG, "trying to expand bubbles when there isn't one selected");
}
- // TODO: Tell taskbar stash controller to stash without bubbles following
+ mTaskbarStashController.updateAndAnimateTransientTaskbar(true /* stash */,
+ false /* shouldBubblesFollow */);
}
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
index 0ab53b0..b3c7d41 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
@@ -25,6 +25,7 @@
import com.android.launcher3.taskbar.StashedHandleViewController;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.launcher3.taskbar.TaskbarInsetsController;
import com.android.launcher3.taskbar.TaskbarStashController;
import com.android.launcher3.util.MultiPropertyFactory;
@@ -50,6 +51,7 @@
// Initialized in init.
private TaskbarControllers mControllers;
+ private TaskbarInsetsController mTaskbarInsetsController;
private BubbleBarViewController mBarViewController;
private BubbleStashedHandleViewController mHandleViewController;
private TaskbarStashController mTaskbarStashController;
@@ -77,6 +79,7 @@
public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
mControllers = controllers;
+ mTaskbarInsetsController = controllers.taskbarInsetsController;
mBarViewController = bubbleControllers.bubbleBarViewController;
mHandleViewController = bubbleControllers.bubbleStashedHandleViewController;
mTaskbarStashController = controllers.taskbarStashController;
@@ -271,7 +274,7 @@
private void onIsStashedChanged() {
mControllers.runAfterInit(() -> {
mHandleViewController.onIsStashedChanged();
- // TODO: when stash changes tell taskbarInsetsController the insets have changed.
+ mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
});
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
index a642693..cfcc1a0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
@@ -18,6 +18,8 @@
import android.content.Context;
import android.view.View;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.dot.DotInfo;
@@ -29,6 +31,7 @@
import com.android.launcher3.taskbar.TaskbarDragController;
import com.android.launcher3.taskbar.TaskbarUIController;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView;
+import com.android.launcher3.taskbar.allapps.TaskbarSearchSessionController;
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
/**
@@ -47,6 +50,8 @@
private final int mStashedTaskbarHeight;
private final TaskbarUIController mUiController;
+ private @Nullable TaskbarSearchSessionController mSearchSessionController;
+
public TaskbarOverlayContext(
Context windowContext,
TaskbarActivityContext taskbarContext,
@@ -62,6 +67,15 @@
mUiController = controllers.uiController;
}
+ public @Nullable TaskbarSearchSessionController getSearchSessionController() {
+ return mSearchSessionController;
+ }
+
+ public void setSearchSessionController(
+ @Nullable TaskbarSearchSessionController searchSessionController) {
+ mSearchSessionController = searchSessionController;
+ }
+
int getStashedTaskbarHeight() {
return mStashedTaskbarHeight;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java b/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java
deleted file mode 100644
index d8aa235..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * Copyright (C) 2019 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.uioverrides;
-
-import static android.os.IBinder.FLAG_ONEWAY;
-
-import android.os.Binder;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.util.Log;
-
-import androidx.annotation.MainThread;
-
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.function.BiConsumer;
-import java.util.function.Supplier;
-
-/**
- * A binder proxy transaction listener for tracking non-whitelisted binder calls.
- */
-public class DejankBinderTracker implements Binder.ProxyTransactListener {
- private static final String TAG = "DejankBinderTracker";
-
- private static final Object sLock = new Object();
- private static final HashSet<String> sWhitelistedFrameworkClasses = new HashSet<>();
- static {
- // Common IPCs that are ok to block the main thread.
- sWhitelistedFrameworkClasses.add("android.view.IWindowSession");
- sWhitelistedFrameworkClasses.add("android.os.IPowerManager");
- }
- private static boolean sTemporarilyIgnoreTracking = false;
-
- // Used by the client to limit binder tracking to specific regions
- private static boolean sTrackingAllowed = false;
-
- private BiConsumer<String, Integer> mUnexpectedTransactionCallback;
- private boolean mIsTracking = false;
-
- /**
- * Temporarily ignore blocking binder calls for the duration of this {@link Runnable}.
- */
- @MainThread
- public static void whitelistIpcs(Runnable runnable) {
- sTemporarilyIgnoreTracking = true;
- runnable.run();
- sTemporarilyIgnoreTracking = false;
- }
-
- /**
- * Temporarily ignore blocking binder calls for the duration of this {@link Supplier}.
- */
- @MainThread
- public static <T> T whitelistIpcs(Supplier<T> supplier) {
- sTemporarilyIgnoreTracking = true;
- T value = supplier.get();
- sTemporarilyIgnoreTracking = false;
- return value;
- }
-
- /**
- * Enables binder tracking during a test.
- */
- @MainThread
- public static void allowBinderTrackingInTests() {
- sTrackingAllowed = true;
- }
-
- /**
- * Disables binder tracking during a test.
- */
- @MainThread
- public static void disallowBinderTrackingInTests() {
- sTrackingAllowed = false;
- }
-
- public DejankBinderTracker(BiConsumer<String, Integer> unexpectedTransactionCallback) {
- mUnexpectedTransactionCallback = unexpectedTransactionCallback;
- }
-
- @MainThread
- public void startTracking() {
- if (!Build.TYPE.toLowerCase(Locale.ROOT).contains("debug")
- && !Build.TYPE.toLowerCase(Locale.ROOT).equals("eng")) {
- Log.wtf(TAG, "Unexpected use of binder tracker in non-debug build", new Exception());
- return;
- }
- if (mIsTracking) {
- return;
- }
- mIsTracking = true;
- Binder.setProxyTransactListener(this);
- }
-
- @MainThread
- public void stopTracking() {
- if (!mIsTracking) {
- return;
- }
- mIsTracking = false;
- Binder.setProxyTransactListener(null);
- }
-
- // Override the hidden Binder#onTransactStarted method
- public synchronized Object onTransactStarted(IBinder binder, int transactionCode, int flags) {
- if (!mIsTracking
- || !sTrackingAllowed
- || sTemporarilyIgnoreTracking
- || (flags & FLAG_ONEWAY) == FLAG_ONEWAY
- || !isMainThread()) {
- return null;
- }
-
- String descriptor;
- try {
- descriptor = binder.getInterfaceDescriptor();
- if (sWhitelistedFrameworkClasses.contains(descriptor)) {
- return null;
- }
- } catch (RemoteException e) {
- e.printStackTrace();
- descriptor = binder.getClass().getSimpleName();
- }
-
- mUnexpectedTransactionCallback.accept(descriptor, transactionCode);
- return null;
- }
-
- @Override
- public Object onTransactStarted(IBinder binder, int transactionCode) {
- // Do nothing
- return null;
- }
-
- @Override
- public void onTransactEnded(Object session) {
- // Do nothing
- }
-
- public static boolean isMainThread() {
- return Thread.currentThread() == Looper.getMainLooper().getThread();
- }
-}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 2b92188..bf4896d 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -112,6 +112,7 @@
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.util.WindowBounds;
@@ -587,7 +588,7 @@
if (mWasLauncherAlreadyVisible) {
mStateCallback.setState(STATE_LAUNCHER_DRAWN);
} else {
- Object traceToken = TraceHelper.INSTANCE.beginSection("WTS-init");
+ SafeCloseable traceToken = TraceHelper.INSTANCE.beginAsyncSection("WTS-init");
View dragLayer = activity.getDragLayer();
dragLayer.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
boolean mHandled = false;
@@ -599,7 +600,7 @@
}
mHandled = true;
- TraceHelper.INSTANCE.endSection(traceToken);
+ traceToken.close();
dragLayer.post(() ->
dragLayer.getViewTreeObserver().removeOnDrawListener(this));
if (activity != mActivity) {
@@ -681,11 +682,10 @@
private void initializeLauncherAnimationController() {
buildAnimationController();
- Object traceToken = TraceHelper.INSTANCE.beginSection("logToggleRecents",
- TraceHelper.FLAG_IGNORE_BINDERS);
- LatencyTracker.getInstance(mContext).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
- (int) (mLauncherFrameDrawnTime - mTouchTimeMs));
- TraceHelper.INSTANCE.endSection(traceToken);
+ try (SafeCloseable c = TraceHelper.INSTANCE.allowIpcs("logToggleRecents")) {
+ LatencyTracker.getInstance(mContext).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
+ (int) (mLauncherFrameDrawnTime - mTouchTimeMs));
+ }
// This method is only called when STATE_GESTURE_STARTED is set, so we can enable the
// high-res thumbnail loader here once we are sure that we will end up in an overview state
@@ -2039,10 +2039,9 @@
private void setScreenshotCapturedState() {
// If we haven't posted a draw callback, set the state immediately.
- Object traceToken = TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT,
- TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS);
+ TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT);
mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
private void finishCurrentTransitionToRecents() {
diff --git a/quickstep/src/com/android/quickstep/BinderTracker.java b/quickstep/src/com/android/quickstep/BinderTracker.java
new file mode 100644
index 0000000..a876cd8
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/BinderTracker.java
@@ -0,0 +1,187 @@
+/**
+ * Copyright (C) 2023 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.quickstep;
+
+import static android.os.IBinder.FLAG_ONEWAY;
+
+import android.os.Binder;
+import android.os.Binder.ProxyTransactListener;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.Trace;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.util.SafeCloseable;
+import com.android.launcher3.util.TraceHelper;
+
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import kotlin.random.Random;
+
+/**
+ * A binder proxy transaction listener for tracking binder calls on main thread.
+ */
+public class BinderTracker {
+
+ private static final String TAG = "BinderTracker";
+
+ // Common IPCs that are ok to block the main thread.
+ private static final Set<String> sAllowedFrameworkClasses = Set.of(
+ "android.view.IWindowSession",
+ "android.os.IPowerManager",
+ "android.os.IServiceManager");
+
+ /**
+ * Starts tracking binder class and returns a {@link SafeCloseable} to end tracking
+ */
+ public static SafeCloseable startTracking(Consumer<BinderCallSite> callback) {
+ TraceHelper current = TraceHelper.INSTANCE;
+
+ TraceHelperExtension helper = new TraceHelperExtension(callback);
+ TraceHelper.INSTANCE = helper;
+ Binder.setProxyTransactListener(helper);
+
+ return () -> {
+ Binder.setProxyTransactListener(null);
+ TraceHelper.INSTANCE = current;
+ };
+ }
+
+ private static final LinkedList<String> mMainThreadTraceStack = new LinkedList<>();
+ private static final LinkedList<String> mMainThreadIgnoreIpcStack = new LinkedList<>();
+
+ private static class TraceHelperExtension extends TraceHelper implements ProxyTransactListener {
+
+ private final Consumer<BinderCallSite> mUnexpectedTransactionCallback;
+
+ TraceHelperExtension(Consumer<BinderCallSite> unexpectedTransactionCallback) {
+ mUnexpectedTransactionCallback = unexpectedTransactionCallback;
+ }
+
+ @Override
+ public void beginSection(String sectionName) {
+ if (isMainThread()) {
+ mMainThreadTraceStack.add(sectionName);
+ }
+ super.beginSection(sectionName);
+ }
+
+ @Override
+ public SafeCloseable beginAsyncSection(String sectionName) {
+ if (!isMainThread()) {
+ return super.beginAsyncSection(sectionName);
+ }
+
+ mMainThreadTraceStack.add(sectionName);
+ int cookie = Random.Default.nextInt();
+ Trace.beginAsyncSection(sectionName, cookie);
+ return () -> {
+ Trace.endAsyncSection(sectionName, cookie);
+ mMainThreadTraceStack.remove(sectionName);
+ };
+ }
+
+ @Override
+ public void endSection() {
+ super.endSection();
+ if (isMainThread()) {
+ mMainThreadTraceStack.pollLast();
+ }
+ }
+
+ @Override
+ public SafeCloseable allowIpcs(String rpcName) {
+ if (!isMainThread()) {
+ return super.allowIpcs(rpcName);
+ }
+
+ mMainThreadTraceStack.add(rpcName);
+ mMainThreadIgnoreIpcStack.add(rpcName);
+ int cookie = Random.Default.nextInt();
+ Trace.beginAsyncSection(rpcName, cookie);
+ return () -> {
+ Trace.endAsyncSection(rpcName, cookie);
+ mMainThreadTraceStack.remove(rpcName);
+ mMainThreadIgnoreIpcStack.remove(rpcName);
+ };
+ }
+
+ @Override
+ public Object onTransactStarted(IBinder binder, int transactionCode, int flags) {
+ if (!isMainThread() || (flags & FLAG_ONEWAY) == FLAG_ONEWAY) {
+ return null;
+ }
+
+ String ipcBypass = mMainThreadIgnoreIpcStack.peekLast();
+ String descriptor;
+ try {
+ descriptor = binder.getInterfaceDescriptor();
+ if (sAllowedFrameworkClasses.contains(descriptor)) {
+ return null;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error getting IPC descriptor", e);
+ descriptor = binder.getClass().getSimpleName();
+ }
+
+ if (ipcBypass == null) {
+ mUnexpectedTransactionCallback.accept(new BinderCallSite(
+ mMainThreadTraceStack.peekLast(), descriptor, transactionCode));
+ } else {
+ Log.d(TAG, "MainThread-IPC " + descriptor + " ignored due to " + ipcBypass);
+ }
+ return null;
+ }
+
+ @Override
+ public Object onTransactStarted(IBinder binder, int transactionCode) {
+ // Do nothing
+ return null;
+ }
+
+ @Override
+ public void onTransactEnded(Object session) {
+ // Do nothing
+ }
+ }
+
+ private static boolean isMainThread() {
+ return Thread.currentThread() == Looper.getMainLooper().getThread();
+ }
+
+ /**
+ * Information about a binder call
+ */
+ public static class BinderCallSite {
+
+ @Nullable
+ public final String activeTrace;
+ public final String descriptor;
+ public final int transactionCode;
+
+ BinderCallSite(String activeTrace, String descriptor, int transactionCode) {
+ this.activeTrace = activeTrace;
+ this.descriptor = descriptor;
+ this.transactionCode = transactionCode;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java b/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java
index 7638541..529213c 100644
--- a/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java
+++ b/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java
@@ -16,10 +16,13 @@
package com.android.quickstep;
+import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.util.Log;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.util.InstantAppResolver;
@@ -49,4 +52,14 @@
ComponentName cn = info.getTargetComponent();
return cn != null && cn.getClassName().equals(COMPONENT_CLASS_MARKER);
}
+
+ @Override
+ public boolean isInstantApp(String packageName, int userId) {
+ try {
+ return ActivityThread.getPackageManager().isInstantApp(packageName, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to determine whether package is instant app " + packageName, e);
+ return false;
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
index 5f589bf..d1939ef 100644
--- a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
+++ b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
@@ -19,6 +19,8 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
+import android.os.Looper;
+import android.os.Trace;
import android.os.UserManager;
import android.util.Log;
import android.view.ThreadedRenderer;
@@ -60,5 +62,14 @@
// Elevate GPU priority for Quickstep and Remote animations.
ThreadedRenderer.setContextPriority(
ThreadedRenderer.EGL_CONTEXT_PRIORITY_HIGH_IMG);
+
+ // Enable Looper trace points.
+ // This allows us to see Handler callbacks on traces.
+ Looper.getMainLooper().setTraceTag(Trace.TRACE_TAG_APP);
+
+ if (BuildConfig.IS_STUDIO_BUILD) {
+ BinderTracker.startTracking(call -> Log.e("BinderCall",
+ call.descriptor + " called on mainthread under " + call.activeTrace));
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index ec8a591..bd0f4ec 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -22,7 +22,6 @@
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_PRE_DELAY;
-import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
import static com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_STATE_ORDINAL;
import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSafely;
import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
@@ -130,7 +129,7 @@
mScrimView = findViewById(R.id.scrim_view);
mFallbackRecentsView = findViewById(R.id.overview_panel);
mActionsView = findViewById(R.id.overview_actions_view);
- SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f);
+ getRootView().getSysUiScrim().getSysUIProgress().updateValue(0);
SplitSelectStateController controller =
new SplitSelectStateController(this, mHandler, getStateManager(),
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index 8135238..810c028 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -393,11 +393,12 @@
@Override
public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
TaskIdAttributeContainer taskContainer) {
- return InstantAppResolver.newInstance(activity).isInstantApp(activity,
- taskContainer.getTask().getTopComponent().getPackageName()) ?
- Collections.singletonList(new SystemShortcut.Install(activity,
- taskContainer.getItemInfo(), taskContainer.getTaskView())) :
- null;
+ Task t = taskContainer.getTask();
+ return InstantAppResolver.newInstance(activity).isInstantApp(
+ t.getTopComponent().getPackageName(), t.getKey().userId)
+ ? Collections.singletonList(new SystemShortcut.Install(activity,
+ taskContainer.getItemInfo(), taskContainer.getTaskView()))
+ : null;
}
};
diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java
index 67360c4..80a449b 100644
--- a/quickstep/src/com/android/quickstep/TaskUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskUtils.java
@@ -33,6 +33,7 @@
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.TraceHelper;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -51,7 +52,8 @@
* TODO: remove this once we switch to getting the icon and label from IconCache.
*/
public static CharSequence getTitle(Context context, Task task) {
- return getTitle(context, task.key.userId, task.getTopComponent().getPackageName());
+ return TraceHelper.allowIpcs("TaskUtils.getTitle", () ->
+ getTitle(context, task.key.userId, task.getTopComponent().getPackageName()));
}
public static CharSequence getTitle(
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 2a1cc70..06ab619 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -39,7 +39,6 @@
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
@@ -88,7 +87,6 @@
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.provider.RestoreDbTask;
-import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarManager;
@@ -102,6 +100,7 @@
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.LockedUserState;
import com.android.launcher3.util.OnboardingPrefs;
+import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
import com.android.quickstep.inputconsumers.AssistantInputConsumer;
@@ -612,18 +611,6 @@
mOverviewComponentObserver.onSystemUiStateChanged();
mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
- boolean wasFreeformActive =
- (lastSysUIFlags & SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0;
- boolean isFreeformActive =
- (systemUiStateFlags & SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0;
- if (wasFreeformActive != isFreeformActive) {
- DesktopVisibilityController controller =
- LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
- if (controller != null) {
- controller.setFreeformTasksVisible(isFreeformActive);
- }
- }
-
int isShadeExpandedFlag =
SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
boolean wasExpanded = (lastSysUIFlags & isShadeExpandedFlag) != 0;
@@ -700,8 +687,7 @@
return;
}
- Object traceToken = TraceHelper.INSTANCE.beginFlagsOverride(
- TraceHelper.FLAG_ALLOW_BINDER_TRACKING);
+ SafeCloseable traceToken = TraceHelper.INSTANCE.allowIpcs("TIS.onInputEvent");
final int action = event.getActionMasked();
// Note this will create a new consumer every mouse click, as after ACTION_UP from the click
@@ -797,7 +783,7 @@
if (cleanUpConsumer) {
reset();
}
- TraceHelper.INSTANCE.endFlagsOverride(traceToken);
+ traceToken.close();
ProtoTracer.INSTANCE.get(this).scheduleFrameUpdate();
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 5b27f9b..10c6316 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -28,7 +28,6 @@
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS;
import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
@@ -229,8 +228,7 @@
// Until we detect the gesture, handle events as we receive them
mInputEventReceiver.setBatchingEnabled(false);
- Object traceToken = TraceHelper.INSTANCE.beginSection(DOWN_EVT,
- FLAG_CHECK_FOR_RACE_CONDITIONS);
+ TraceHelper.INSTANCE.beginSection(DOWN_EVT);
mActivePointerId = ev.getPointerId(0);
mDownPos.set(ev.getX(), ev.getY());
mLastPos.set(mDownPos);
@@ -241,7 +239,7 @@
startTouchTrackingForWindowAnimation(ev.getEventTime());
}
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
break;
}
case ACTION_POINTER_DOWN: {
@@ -417,8 +415,7 @@
* the animation can still be running.
*/
private void finishTouchTracking(MotionEvent ev) {
- Object traceToken = TraceHelper.INSTANCE.beginSection(UP_EVT,
- FLAG_CHECK_FOR_RACE_CONDITIONS);
+ TraceHelper.INSTANCE.beginSection(UP_EVT);
if (mPassedWindowMoveSlop && mInteractionHandler != null) {
if (ev.getActionMasked() == ACTION_CANCEL) {
@@ -455,7 +452,7 @@
onInteractionGestureFinished();
}
cleanupAfterGesture();
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
private void cleanupAfterGesture() {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
index fbe7fde..e9a0761 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@@ -37,6 +37,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarTranslationController.TransitionCallback;
+import com.android.launcher3.taskbar.bubbles.BubbleControllers;
import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.InputConsumer;
@@ -62,6 +63,7 @@
private final int mTaskbarNavThresholdY;
private final boolean mIsTaskbarAllAppsOpen;
private boolean mHasPassedTaskbarNavThreshold;
+ private boolean mIsInBubbleBarArea;
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
@@ -136,7 +138,7 @@
mHasPassedTaskbarNavThreshold = false;
mTaskbarActivityContext.setAutohideSuspendFlag(
FLAG_AUTOHIDE_SUSPEND_TOUCHING, true);
- if (isInArea(x)) {
+ if (isInTaskbarArea(x)) {
if (!mIsTransientTaskbar) {
mLongPressDownX = x;
mLongPressDownY = y;
@@ -145,10 +147,12 @@
mCanceledUnstashHint = false;
}
}
-
if (mTransitionCallback != null && !mIsTaskbarAllAppsOpen) {
mTransitionCallback.onActionDown();
}
+ if (mIsTransientTaskbar && isInBubbleBarArea(x)) {
+ mIsInBubbleBarArea = true;
+ }
break;
case MotionEvent.ACTION_POINTER_UP:
int ptrIdx = ev.getActionIndex();
@@ -185,7 +189,11 @@
if (!mHasPassedTaskbarNavThreshold && passedTaskbarNavThreshold) {
mHasPassedTaskbarNavThreshold = true;
- mTaskbarActivityContext.onSwipeToUnstashTaskbar();
+ if (mIsInBubbleBarArea) {
+ mTaskbarActivityContext.onSwipeToOpenBubblebar();
+ } else {
+ mTaskbarActivityContext.onSwipeToUnstashTaskbar();
+ }
}
if (dY < 0) {
@@ -208,21 +216,32 @@
mTransitionCallback.onActionEnd();
}
mHasPassedTaskbarNavThreshold = false;
+ mIsInBubbleBarArea = false;
break;
}
}
}
}
- private boolean isInArea(float x) {
+ private boolean isInTaskbarArea(float x) {
float areaFromMiddle = mUnstashArea / 2.0f;
float distFromMiddle = Math.abs(mScreenWidth / 2.0f - x);
return distFromMiddle < areaFromMiddle;
}
+ private boolean isInBubbleBarArea(float x) {
+ if (mTaskbarActivityContext != null && mIsTransientTaskbar) {
+ BubbleControllers controllers = mTaskbarActivityContext.getBubbleControllers();
+ if (controllers == null) return false;
+ Rect bubbleBarBounds = controllers.bubbleBarViewController.getBubbleBarBounds();
+ return x >= bubbleBarBounds.left && x <= bubbleBarBounds.right;
+ }
+ return false;
+ }
+
private void onLongPressDetected(MotionEvent motionEvent) {
if (mTaskbarActivityContext != null
- && isInArea(motionEvent.getRawX())
+ && isInTaskbarArea(motionEvent.getRawX())
&& !mIsTransientTaskbar) {
boolean taskBarPressed = mTaskbarActivityContext.onLongPressToUnstashTaskbar();
if (taskBarPressed) {
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 084f8c1..5ec92a6 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -412,10 +412,12 @@
}
mFeedbackTitleView.setText(titleResId);
- mFeedbackSubtitleView.setText(spokenSubtitleResId == NO_ID
- ? mContext.getText(subtitleResId)
- : Utilities.wrapForTts(
- mContext.getText(subtitleResId), mContext.getString(spokenSubtitleResId)));
+ mFeedbackSubtitleView.setText(
+ ENABLE_NEW_GESTURE_NAV_TUTORIAL.get() || spokenSubtitleResId == NO_ID
+ ? mContext.getText(subtitleResId)
+ : Utilities.wrapForTts(
+ mContext.getText(subtitleResId),
+ mContext.getString(spokenSubtitleResId)));
if (isGestureSuccessful) {
if (mTutorialFragment.isAtFinalStep()) {
showActionButton();
diff --git a/quickstep/src/com/android/quickstep/util/BinderTracker.java b/quickstep/src/com/android/quickstep/util/BinderTracker.java
deleted file mode 100644
index cb04e5b..0000000
--- a/quickstep/src/com/android/quickstep/util/BinderTracker.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 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.quickstep.util;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Looper;
-import android.util.Log;
-
-import com.android.launcher3.config.FeatureFlags;
-
-/**
- * Utility class to test and check binder calls during development.
- */
-public class BinderTracker {
-
- private static final String TAG = "BinderTracker";
-
- public static void start() {
- if (!FeatureFlags.IS_STUDIO_BUILD) {
- Log.wtf(TAG, "Accessing tracker in released code.", new Exception());
- return;
- }
-
- Binder.setProxyTransactListener(new Tracker());
- }
-
- public static void stop() {
- if (!FeatureFlags.IS_STUDIO_BUILD) {
- Log.wtf(TAG, "Accessing tracker in released code.", new Exception());
- return;
- }
- Binder.setProxyTransactListener(null);
- }
-
- private static class Tracker implements Binder.ProxyTransactListener {
-
- @Override
- public Object onTransactStarted(IBinder iBinder, int code) {
- if (Looper.myLooper() == Looper.getMainLooper()) {
- Log.e(TAG, "Binder call on ui thread", new Exception());
- }
- return null;
- }
-
- @Override
- public void onTransactEnded(Object session) { }
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 9099012..6b3199f 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -177,8 +177,8 @@
addDepthAnimationForState(launcher, NORMAL, duration);
- mAnimators.play(launcher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f)
- .setDuration(duration));
+ mAnimators.play(launcher.getRootView().getSysUiScrim().getSysUIMultiplier()
+ .animateToValue(0f, 1f).setDuration(duration));
}
private void addAnimationForPage(CellLayout page, int totalRows, long duration) {
diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
index c82cdb7..5f7d694 100644
--- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -24,6 +24,7 @@
import android.view.WindowMetrics;
import com.android.internal.policy.SystemBarUtils;
+import com.android.launcher3.logging.FileLog;
import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.util.window.CachedDisplayInfo;
import com.android.launcher3.util.window.WindowManagerProxy;
@@ -60,6 +61,7 @@
WindowManager windowManager = displayInfoContext.getSystemService(WindowManager.class);
Set<WindowMetrics> possibleMaximumWindowMetrics =
windowManager.getPossibleMaximumWindowMetrics(DEFAULT_DISPLAY);
+ FileLog.d("b/283944974", "possibleMaximumWindowMetrics: " + possibleMaximumWindowMetrics);
for (WindowMetrics windowMetrics : possibleMaximumWindowMetrics) {
CachedDisplayInfo info = getDisplayInfo(windowMetrics, Surface.ROTATION_0);
List<WindowBounds> bounds = estimateWindowBounds(displayInfoContext, info);
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index f8893bd..7f035a2 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -112,8 +112,7 @@
mContext = context;
mSizeStrategy = sizeStrategy;
- // TODO(b/187074722): Don't create this per-TaskViewSimulator
- mOrientationState = TraceHelper.allowIpcs("",
+ mOrientationState = TraceHelper.allowIpcs("TaskViewSimulator.init",
() -> new RecentsOrientedState(context, sizeStrategy, i -> { }));
mOrientationState.setGestureActive(true);
mCurrentFullscreenParams = new FullscreenDrawParams(context);
diff --git a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
index ac8862f..0a97793 100644
--- a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
+++ b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
@@ -92,7 +92,8 @@
}
// Add sysui scrim animation.
- mAnimators.play(launcher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f));
+ mAnimators.play(launcher.getRootView().getSysUiScrim()
+ .getSysUIMultiplier().animateToValue(0f, 1f));
mAnimators.setDuration(DURATION_MS);
mAnimators.setInterpolator(Interpolators.DECELERATED_EASE);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 200252a..46dd94b 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -32,6 +32,7 @@
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
+import static com.android.quickstep.TaskOverlayFactory.getEnabledShortcuts;
import static com.android.quickstep.util.BorderAnimator.DEFAULT_BORDER_COLOR;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -88,6 +89,7 @@
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
+import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.TransformingTouchDelegate;
import com.android.launcher3.util.ViewPool.Reusable;
import com.android.quickstep.RecentsModel;
@@ -1556,8 +1558,8 @@
if (taskContainer == null) {
continue;
}
- for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
- taskContainer)) {
+ for (SystemShortcut s : TraceHelper.allowIpcs(
+ "TV.a11yInfo", () -> getEnabledShortcuts(this, taskContainer))) {
info.addAction(s.createAccessibilityAction(context));
}
}
@@ -1594,7 +1596,7 @@
if (taskContainer == null) {
continue;
}
- for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
+ for (SystemShortcut s : getEnabledShortcuts(this,
taskContainer)) {
if (s.hasHandlerForAction(action)) {
s.onClick(this);
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index df5303f..5127190 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -20,7 +20,6 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.ui.TaplTestsLauncher3;
-import com.android.launcher3.util.RaceConditionReproducer;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import org.junit.Before;
@@ -45,18 +44,6 @@
startTestActivity(2);
}
- private void runTest(String... eventSequence) {
- final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(eventSequence);
-
- // Destroy Launcher activity.
- closeLauncherActivity();
-
- // The test action.
- eventProcessor.startIteration();
- mLauncher.goHome();
- eventProcessor.finishIteration();
- }
-
@Ignore
@Test
@NavigationModeSwitch
diff --git a/res/drawable-hdpi/workspace_bg.9.png b/res/drawable-hdpi/workspace_bg.9.png
deleted file mode 100755
index 1d82fd4..0000000
--- a/res/drawable-hdpi/workspace_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/workspace_bg.9.png b/res/drawable-mdpi/workspace_bg.9.png
deleted file mode 100755
index 116ce44..0000000
--- a/res/drawable-mdpi/workspace_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/workspace_bg.9.png b/res/drawable-xhdpi/workspace_bg.9.png
deleted file mode 100755
index b1b3b85..0000000
--- a/res/drawable-xhdpi/workspace_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/workspace_bg.9.png b/res/drawable-xxhdpi/workspace_bg.9.png
deleted file mode 100755
index d47f6b2..0000000
--- a/res/drawable-xxhdpi/workspace_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/workspace_bg.9.png b/res/drawable-xxxhdpi/workspace_bg.9.png
deleted file mode 100755
index 3281548..0000000
--- a/res/drawable-xxxhdpi/workspace_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/ic_wallpaper.xml b/res/drawable/ic_wallpaper.xml
deleted file mode 100644
index 9543f88..0000000
--- a/res/drawable/ic_wallpaper.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
- Copyright (C) 2016 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/options_menu_icon_size"
- android:height="@dimen/options_menu_icon_size"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/textColorPrimary">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M9,12.71l2.14,2.58l3-3.87L18,16.57H6L9,12.71z M5,5h6V3H5C3.9,3,3,3.9,3,5v6h2V5z M19,19h-6v2h6c1.1,0,2-0.9,2-2v-6h-2V19z
- M5,19v-6H3v6c0,1.1,0.9,2,2,2h6v-2H5z M19,5v6h2V5c0-1.1-0.9-2-2-2h-6v2H19z M16,9c0.55,0,1-0.45,1-1s-0.45-1-1-1
- c-0.55,0-1,0.45-1,1S15.45,9,16,9z"/>
-</vector>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index b023d10..2e74d7d 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -36,7 +36,6 @@
<attr name="workspaceShadowColor" format="color" />
<attr name="workspaceAmbientShadowColor" format="color" />
<attr name="workspaceKeyShadowColor" format="color" />
- <attr name="workspaceStatusBarScrim" format="reference" />
<attr name="widgetsTheme" format="reference" />
<attr name="iconOnlyShortcutColor" format="color" />
<attr name="eduHalfSheetBGColor" format="color" />
diff --git a/res/values/config.xml b/res/values/config.xml
index 5a6698b..436ece9 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -84,6 +84,7 @@
<string name="window_manager_proxy_class" translatable="false"></string>
<string name="secondary_display_predictions_class" translatable="false"></string>
<string name="widget_holder_factory_class" translatable="false"></string>
+ <string name="taskbar_search_session_controller_class" translatable="false"></string>
<!-- View ID to use for QSB widget -->
<item type="id" name="qsb_widget" />
@@ -102,8 +103,6 @@
<!-- Default packages -->
<string name="wallpaper_picker_package" translatable="false"></string>
- <string name="custom_activity_picker" translatable="false">
- com.android.customization.picker.CustomizationPickerActivity</string>
<string name="local_colors_extraction_class" translatable="false"></string>
<string name="search_session_manager_class" translatable="false"></string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c2eb373..1b46b4d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -250,8 +250,6 @@
<!-- Strings for the customization mode -->
<!-- Text for wallpaper change button [CHAR LIMIT=30]-->
- <string name="wallpaper_button_text">Wallpapers</string>
- <!-- Text for wallpaper change button [CHAR LIMIT=30]-->
<string name="styles_wallpaper_button_text">Wallpaper & style</string>
<!-- Text for edit home screen button [CHAR LIMIT=30]-->
<string name="edit_home_screen">Edit Home Screen</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 876c3a8..2b37db8 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -50,7 +50,6 @@
<item name="workspaceShadowColor">#B0000000</item>
<item name="workspaceAmbientShadowColor">#40000000</item>
<item name="workspaceKeyShadowColor">#89000000</item>
- <item name="workspaceStatusBarScrim">@drawable/workspace_bg</item>
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
<item name="folderPaginationColor">@color/folder_pagination_color_light</item>
<item name="folderPreviewColor">@color/folder_preview_light</item>
@@ -92,7 +91,6 @@
<item name="workspaceAmbientShadowColor">@android:color/transparent</item>
<item name="workspaceKeyShadowColor">@android:color/transparent</item>
<item name="isWorkspaceDarkText">true</item>
- <item name="workspaceStatusBarScrim">@null</item>
<item name="workspaceAccentColor">@color/workspace_accent_color_dark</item>
<item name="dropTargetHoverTextColor">@color/drop_target_hover_text_color_dark</item>
<item name="dropTargetHoverButtonColor">@color/drop_target_hover_button_color_dark</item>
@@ -143,7 +141,6 @@
<item name="workspaceAmbientShadowColor">@android:color/transparent</item>
<item name="workspaceKeyShadowColor">@android:color/transparent</item>
<item name="isWorkspaceDarkText">true</item>
- <item name="workspaceStatusBarScrim">@null</item>
<item name="workspaceAccentColor">@color/workspace_accent_color_dark</item>
<item name="dropTargetHoverTextColor">@color/drop_target_hover_text_color_dark</item>
<item name="dropTargetHoverButtonColor">@color/drop_target_hover_button_color_dark</item>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1da0ef4..8071ae4 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -445,8 +445,7 @@
Trace.beginAsyncSection(DISPLAY_ALL_APPS_TRACE_METHOD_NAME,
DISPLAY_ALL_APPS_TRACE_COOKIE);
}
- Object traceToken = TraceHelper.INSTANCE.beginSection(ON_CREATE_EVT,
- TraceHelper.FLAG_UI_EVENT);
+ TraceHelper.INSTANCE.beginSection(ON_CREATE_EVT);
if (DEBUG_STRICT_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
@@ -580,7 +579,7 @@
LauncherOverlayPlugin.class, false /* allowedMultiple */);
mRotationHelper.initialize();
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
mUserChangedCallbackCloseable = UserCache.INSTANCE.get(this).addUserChangeListener(
() -> getStateManager().goToState(NORMAL));
@@ -1078,15 +1077,14 @@
@Override
protected void onStart() {
- Object traceToken = TraceHelper.INSTANCE.beginSection(ON_START_EVT,
- TraceHelper.FLAG_UI_EVENT);
+ TraceHelper.INSTANCE.beginSection(ON_START_EVT);
super.onStart();
if (!mDeferOverlayCallbacks) {
mOverlayManager.onActivityStarted(this);
}
mAppWidgetHolder.setActivityStarted(true);
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
@Override
@@ -1257,8 +1255,7 @@
@Override
protected void onResume() {
- Object traceToken = TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT,
- TraceHelper.FLAG_UI_EVENT);
+ TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT);
super.onResume();
if (mDeferOverlayCallbacks) {
@@ -1268,7 +1265,7 @@
}
DragView.removeAllViews(this);
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
@Override
@@ -1656,7 +1653,7 @@
if (Utilities.isRunningInTestHarness()) {
Log.d(TestProtocol.PERMANENT_DIAG_TAG, "Launcher.onNewIntent: " + intent);
}
- Object traceToken = TraceHelper.INSTANCE.beginSection(ON_NEW_INTENT_EVT);
+ TraceHelper.INSTANCE.beginSection(ON_NEW_INTENT_EVT);
super.onNewIntent(intent);
boolean alreadyOnHome = hasWindowFocus() && ((intent.getFlags() &
@@ -1703,7 +1700,7 @@
showAllAppsWorkTabFromIntent(alreadyOnHome);
}
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
protected void toggleAllAppsFromIntent(boolean alreadyOnHome) {
@@ -2302,7 +2299,7 @@
* Implementation of the method from LauncherModel.Callbacks.
*/
public void startBinding() {
- Object traceToken = TraceHelper.INSTANCE.beginSection("startBinding");
+ TraceHelper.INSTANCE.beginSection("startBinding");
// Floating panels (except the full widget sheet) are associated with individual icons. If
// we are starting a fresh bind, close all such panels as all the icons are about
// to go away.
@@ -2320,7 +2317,7 @@
if (mHotseat != null) {
mHotseat.resetLayout(getDeviceProfile().isVerticalBarLayout());
}
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
@Override
@@ -2573,7 +2570,7 @@
return view;
}
- Object traceToken = TraceHelper.INSTANCE.beginSection("BIND_WIDGET_id=" + item.appWidgetId);
+ TraceHelper.INSTANCE.beginSection("BIND_WIDGET_id=" + item.appWidgetId);
try {
final LauncherAppWidgetProviderInfo appWidgetInfo;
@@ -2703,7 +2700,7 @@
}
prepareAppWidget(view, item);
} finally {
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
return view;
@@ -2796,7 +2793,7 @@
* Implementation of the method from LauncherModel.Callbacks.
*/
public void finishBindingItems(IntSet pagesBoundFirst) {
- Object traceToken = TraceHelper.INSTANCE.beginSection("finishBindingItems");
+ TraceHelper.INSTANCE.beginSection("finishBindingItems");
mWorkspace.restoreInstanceStateForRemainingPages();
setWorkspaceLoading(false);
@@ -2821,7 +2818,7 @@
mDeviceProfile.inv.numFolderColumns * mDeviceProfile.inv.numFolderRows);
getViewCache().setCacheSize(R.layout.folder_page, 2);
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
mWorkspace.removeExtraEmptyScreen(true);
}
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index c04cdfd..e4f34ae 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -35,7 +35,6 @@
import static com.android.launcher3.LauncherState.WORKSPACE_PAGE_INDICATOR;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
-import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
@@ -54,6 +53,7 @@
import com.android.launcher3.LauncherState.PageAlphaProvider;
import com.android.launcher3.LauncherState.PageTranslationProvider;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
+import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.anim.SpringAnimationBuilder;
@@ -196,7 +196,7 @@
state.getWorkspaceBackgroundAlpha(mLauncher), LINEAR);
SysUiScrim sysUiScrim = mLauncher.getRootView().getSysUiScrim();
- propertySetter.setFloat(sysUiScrim, SYSUI_PROGRESS,
+ propertySetter.setFloat(sysUiScrim.getSysUIProgress(), AnimatedFloat.VALUE,
state.hasFlag(FLAG_HAS_SYS_UI_SCRIM) ? 1 : 0, LINEAR);
propertySetter.setViewBackgroundColor(mLauncher.getScrimView(),
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index d4140d8..898009d 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -70,7 +70,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
-import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
+import com.android.launcher3.allapps.search.AllAppsSearchUiDelegate;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.keyboard.FocusedItemDecorator;
@@ -132,6 +132,7 @@
protected final Point mFastScrollerOffset = new Point();
protected final int mScrimColor;
protected final float mHeaderThreshold;
+ protected final AllAppsSearchUiDelegate mSearchUiDelegate;
// Used to animate Search results out and A-Z apps in, or vice-versa.
private final SearchTransitionController mSearchTransitionController;
@@ -217,11 +218,17 @@
getActiveRecyclerView().requestFocus();
}
});
+ mSearchUiDelegate = createSearchUiDelegate();
initContent();
mSearchTransitionController = new SearchTransitionController(this);
}
+ /** Creates the delegate for initializing search. */
+ protected AllAppsSearchUiDelegate createSearchUiDelegate() {
+ return new AllAppsSearchUiDelegate(this);
+ }
+
/**
* Initializes the view hierarchy and internal variables. Any initialization which actually uses
* these members should be done in {@link #onFinishInflate()}.
@@ -231,7 +238,7 @@
* onFinishInflate -> onPostCreate
*/
protected void initContent() {
- mMainAdapterProvider = createMainAdapterProvider();
+ mMainAdapterProvider = mSearchUiDelegate.createMainAdapterProvider();
mAH.set(AdapterHolder.MAIN, new AdapterHolder(AdapterHolder.MAIN,
new AlphabeticalAppsList<>(mActivityContext, mAllAppsStore, null)));
@@ -252,6 +259,7 @@
mSearchContainer = inflateSearchBox();
addView(mSearchContainer);
mSearchUiManager = (SearchUiManager) mSearchContainer;
+ mSearchUiDelegate.onInitializeSearchBox();
}
@Override
@@ -341,6 +349,7 @@
*/
public void setSearchResults(ArrayList<AdapterItem> results, int searchResultCode) {
setSearchResults(results);
+ mSearchUiDelegate.onSearchResultsChanged(results, searchResultCode);
}
private void animateToSearchState(boolean goingToSearch) {
@@ -788,12 +797,7 @@
* Inflates the search box
*/
protected View inflateSearchBox() {
- return getLayoutInflater().inflate(R.layout.search_container_all_apps, this, false);
- }
-
- /** Creates the adapter provider for the main section. */
- protected SearchAdapterProvider<?> createMainAdapterProvider() {
- return new DefaultSearchAdapterProvider(mActivityContext);
+ return mSearchUiDelegate.inflateSearchBox();
}
/** The adapter provider for the main section. */
@@ -998,7 +1002,7 @@
}
public LayoutInflater getLayoutInflater() {
- return LayoutInflater.from(getContext());
+ return mSearchUiDelegate.getLayoutInflater();
}
@Override
@@ -1306,6 +1310,7 @@
protected void onInitializeRecyclerView(RecyclerView rv) {
rv.addOnScrollListener(mScrollListener);
+ mSearchUiDelegate.onInitializeRecyclerView(rv);
}
/** Returns the instance of @{code SearchTransitionController}. */
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchUiDelegate.java b/src/com/android/launcher3/allapps/search/AllAppsSearchUiDelegate.java
new file mode 100644
index 0000000..abec16e
--- /dev/null
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchUiDelegate.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 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.allapps.search;
+
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
+import com.android.launcher3.views.ActivityContext;
+
+import java.util.List;
+
+/** Initializes the search box and its interactions with All Apps. */
+public class AllAppsSearchUiDelegate {
+
+ protected final ActivityAllAppsContainerView<?> mAppsView;
+ protected final ActivityContext mActivityContext;
+
+ public AllAppsSearchUiDelegate(ActivityAllAppsContainerView<?> appsView) {
+ mAppsView = appsView;
+ mActivityContext = ActivityContext.lookupContext(mAppsView.getContext());
+ }
+
+ /** Invoked when an All Apps {@link RecyclerView} is initialized. */
+ public void onInitializeRecyclerView(RecyclerView rv) {
+ // Do nothing.
+ }
+
+ /** Invoked when search results are updated in All Apps. */
+ public void onSearchResultsChanged(List<AdapterItem> results, int searchResultCode) {
+ // Do nothing.
+ }
+
+ /** Invoked when the search box has been added to All Apps. */
+ public void onInitializeSearchBox() {
+ // Do nothing.
+ }
+
+ /** The layout inflater for All Apps and search UI. */
+ public LayoutInflater getLayoutInflater() {
+ return LayoutInflater.from(mAppsView.getContext());
+ }
+
+ /** Inflate the search box for All Apps. */
+ public View inflateSearchBox() {
+ return getLayoutInflater().inflate(R.layout.search_container_all_apps, mAppsView, false);
+ }
+
+ /** Creates the adapter provider for the main section. */
+ public SearchAdapterProvider<?> createMainAdapterProvider() {
+ return new DefaultSearchAdapterProvider(mActivityContext);
+ }
+}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 80b6452..b8d2df0 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -314,7 +314,7 @@
"Enable a grid-only overview without a focused task.");
public static final BooleanFlag ENABLE_CURSOR_HOVER_STATES = getDebugFlag(243191650,
- "ENABLE_CURSOR_HOVER_STATES", ENABLED,
+ "ENABLE_CURSOR_HOVER_STATES", TEAMFOOD,
"Enables cursor hover states for certain elements.");
// TODO(Block 24): Clean up flags
diff --git a/src/com/android/launcher3/graphics/SysUiScrim.java b/src/com/android/launcher3/graphics/SysUiScrim.java
index 21ebc98..a572a60 100644
--- a/src/com/android/launcher3/graphics/SysUiScrim.java
+++ b/src/com/android/launcher3/graphics/SysUiScrim.java
@@ -13,29 +13,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.launcher3.graphics;
+import static android.graphics.Paint.DITHER_FLAG;
+import static android.graphics.Paint.FILTER_BITMAP_FLAG;
+
import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
-import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.animation.ObjectAnimator;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
-import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
-import android.util.FloatProperty;
import android.view.View;
+import androidx.annotation.ColorInt;
+
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.ScreenOnTracker;
import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener;
@@ -46,33 +47,6 @@
*/
public class SysUiScrim implements View.OnAttachStateChangeListener {
- public static final FloatProperty<SysUiScrim> SYSUI_PROGRESS =
- new FloatProperty<SysUiScrim>("sysUiProgress") {
- @Override
- public Float get(SysUiScrim scrim) {
- return scrim.mSysUiProgress;
- }
-
- @Override
- public void setValue(SysUiScrim scrim, float value) {
- scrim.setSysUiProgress(value);
- }
- };
-
- private static final FloatProperty<SysUiScrim> SYSUI_ANIM_MULTIPLIER =
- new FloatProperty<SysUiScrim>("sysUiAnimMultiplier") {
- @Override
- public Float get(SysUiScrim scrim) {
- return scrim.mSysUiAnimMultiplier;
- }
-
- @Override
- public void setValue(SysUiScrim scrim, float value) {
- scrim.mSysUiAnimMultiplier = value;
- scrim.reapplySysUiAlpha();
- }
- };
-
/**
* Receiver used to get a signal that the user unlocked their device.
*/
@@ -92,44 +66,52 @@
}
};
- private static final int MAX_HOTSEAT_SCRIM_ALPHA = 100;
- private static final int ALPHA_MASK_HEIGHT_DP = 500;
- private static final int ALPHA_MASK_BITMAP_DP = 200;
- private static final int ALPHA_MASK_WIDTH_DP = 2;
+ private static final int MAX_SYSUI_SCRIM_ALPHA = 255;
+ private static final int ALPHA_MASK_BITMAP_WIDTH_DP = 2;
+
+ private static final int BOTTOM_MASK_HEIGHT_DP = 200;
+ private static final int TOP_MASK_HEIGHT_DP = 100;
private boolean mDrawTopScrim, mDrawBottomScrim;
- private final RectF mFinalMaskRect = new RectF();
- private final Paint mBottomMaskPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
- private final Bitmap mBottomMask;
- private final int mMaskHeight;
+ private final RectF mTopMaskRect = new RectF();
+ private final Paint mTopMaskPaint = new Paint(FILTER_BITMAP_FLAG | DITHER_FLAG);
+ private final Bitmap mTopMaskBitmap;
+ private final int mTopMaskHeight;
+
+ private final RectF mBottomMaskRect = new RectF();
+ private final Paint mBottomMaskPaint = new Paint(FILTER_BITMAP_FLAG | DITHER_FLAG);
+ private final Bitmap mBottomMaskBitmap;
+ private final int mBottomMaskHeight;
private final View mRoot;
private final BaseDraggingActivity mActivity;
- private final Drawable mTopScrim;
-
- private float mSysUiProgress = 1;
- private boolean mHideSysUiScrim;
+ private final boolean mHideSysUiScrim;
private boolean mAnimateScrimOnNextDraw = false;
- private float mSysUiAnimMultiplier = 1;
+ private final AnimatedFloat mSysUiAnimMultiplier = new AnimatedFloat(this::reapplySysUiAlpha);
+ private final AnimatedFloat mSysUiProgress = new AnimatedFloat(this::reapplySysUiAlpha);
public SysUiScrim(View view) {
mRoot = view;
mActivity = BaseDraggingActivity.fromContext(view.getContext());
- mMaskHeight = ResourceUtils.pxFromDp(ALPHA_MASK_BITMAP_DP,
- view.getResources().getDisplayMetrics());
- mTopScrim = Themes.getAttrDrawable(view.getContext(), R.attr.workspaceStatusBarScrim);
- if (mTopScrim != null) {
- mTopScrim.setDither(true);
- mBottomMask = createDitheredAlphaMask();
- mHideSysUiScrim = false;
- } else {
- mBottomMask = null;
- mHideSysUiScrim = true;
- }
+ DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
- view.addOnAttachStateChangeListener(this);
+ mTopMaskHeight = ResourceUtils.pxFromDp(TOP_MASK_HEIGHT_DP, dm);
+ mBottomMaskHeight = ResourceUtils.pxFromDp(BOTTOM_MASK_HEIGHT_DP, dm);
+ mHideSysUiScrim = Themes.getAttrBoolean(view.getContext(), R.attr.isWorkspaceDarkText);
+
+ mTopMaskBitmap = mHideSysUiScrim ? null : createDitheredAlphaMask(mTopMaskHeight,
+ new int[]{0x50FFFFFF, 0x0AFFFFFF, 0x00FFFFFF},
+ new float[]{0f, 0.7f, 1f});
+ mTopMaskPaint.setColor(0xFF222222);
+ mBottomMaskBitmap = mHideSysUiScrim ? null : createDitheredAlphaMask(mBottomMaskHeight,
+ new int[]{0x00FFFFFF, 0x2FFFFFFF},
+ new float[]{0f, 1f});
+
+ if (!KEYGUARD_ANIMATION.get() && !mHideSysUiScrim) {
+ view.addOnAttachStateChangeListener(this);
+ }
}
/**
@@ -137,16 +119,16 @@
*/
public void draw(Canvas canvas) {
if (!mHideSysUiScrim) {
- if (mSysUiProgress <= 0) {
+ if (mSysUiProgress.value <= 0) {
mAnimateScrimOnNextDraw = false;
return;
}
if (mAnimateScrimOnNextDraw) {
- mSysUiAnimMultiplier = 0;
+ mSysUiAnimMultiplier.value = 0;
reapplySysUiAlphaNoInvalidate();
- ObjectAnimator oa = createSysuiMultiplierAnim(1);
+ ObjectAnimator oa = mSysUiAnimMultiplier.animateToValue(1);
oa.setDuration(600);
oa.setStartDelay(mActivity.getWindow().getTransitionBackgroundFadeDuration());
oa.start();
@@ -154,21 +136,26 @@
}
if (mDrawTopScrim) {
- mTopScrim.draw(canvas);
+ canvas.drawBitmap(mTopMaskBitmap, null, mTopMaskRect, mTopMaskPaint);
}
if (mDrawBottomScrim) {
- canvas.drawBitmap(mBottomMask, null, mFinalMaskRect, mBottomMaskPaint);
+ canvas.drawBitmap(mBottomMaskBitmap, null, mBottomMaskRect, mBottomMaskPaint);
}
}
}
/**
- * @return an ObjectAnimator that controls the fade in/out of the sys ui scrim.
+ * Returns the sysui multiplier property for controlling fade in/out of the scrim
*/
- public ObjectAnimator createSysuiMultiplierAnim(float... values) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(this, SYSUI_ANIM_MULTIPLIER, values);
- anim.setAutoCancel(true);
- return anim;
+ public AnimatedFloat getSysUIMultiplier() {
+ return mSysUiAnimMultiplier;
+ }
+
+ /**
+ * Returns the sysui progress property for controlling fade in/out of the scrim
+ */
+ public AnimatedFloat getSysUIProgress() {
+ return mSysUiProgress;
}
/**
@@ -180,44 +167,26 @@
*/
public void onInsetsChanged(Rect insets) {
DeviceProfile dp = mActivity.getDeviceProfile();
- mDrawTopScrim = mTopScrim != null && insets.top > 0;
- mDrawBottomScrim = mBottomMask != null
- && !dp.isVerticalBarLayout()
- && !dp.isGestureMode
- && !dp.isTaskbarPresent;
+ mDrawTopScrim = insets.top > 0;
+ mDrawBottomScrim = !dp.isVerticalBarLayout() && !dp.isGestureMode && !dp.isTaskbarPresent;
}
@Override
public void onViewAttachedToWindow(View view) {
- if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
- ScreenOnTracker.INSTANCE.get(mActivity).addListener(mScreenOnListener);
- }
+ ScreenOnTracker.INSTANCE.get(mActivity).addListener(mScreenOnListener);
}
@Override
public void onViewDetachedFromWindow(View view) {
- if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
- ScreenOnTracker.INSTANCE.get(mActivity).removeListener(mScreenOnListener);
- }
+ ScreenOnTracker.INSTANCE.get(mActivity).removeListener(mScreenOnListener);
}
/**
* Set the width and height of the view being scrimmed
- * @param w
- * @param h
*/
public void setSize(int w, int h) {
- if (mTopScrim != null) {
- mTopScrim.setBounds(0, 0, w, h);
- mFinalMaskRect.set(0, h - mMaskHeight, w, h);
- }
- }
-
- private void setSysUiProgress(float progress) {
- if (progress != mSysUiProgress) {
- mSysUiProgress = progress;
- reapplySysUiAlpha();
- }
+ mTopMaskRect.set(0, 0, w, mTopMaskHeight);
+ mBottomMaskRect.set(0, h - mBottomMaskHeight, w, h);
}
private void reapplySysUiAlpha() {
@@ -228,29 +197,21 @@
}
private void reapplySysUiAlphaNoInvalidate() {
- float factor = mSysUiProgress * mSysUiAnimMultiplier;
- mBottomMaskPaint.setAlpha(Math.round(MAX_HOTSEAT_SCRIM_ALPHA * factor));
- if (mTopScrim != null) {
- mTopScrim.setAlpha(Math.round(255 * factor));
- }
+ float factor = mSysUiProgress.value * mSysUiAnimMultiplier.value;
+ mBottomMaskPaint.setAlpha(Math.round(MAX_SYSUI_SCRIM_ALPHA * factor));
+ mTopMaskPaint.setAlpha(Math.round(MAX_SYSUI_SCRIM_ALPHA * factor));
}
- private Bitmap createDitheredAlphaMask() {
+ private Bitmap createDitheredAlphaMask(int height, @ColorInt int[] colors, float[] positions) {
DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
- int width = ResourceUtils.pxFromDp(ALPHA_MASK_WIDTH_DP, dm);
- int gradientHeight = ResourceUtils.pxFromDp(ALPHA_MASK_HEIGHT_DP, dm);
- Bitmap dst = Bitmap.createBitmap(width, mMaskHeight, Bitmap.Config.ALPHA_8);
+ int width = ResourceUtils.pxFromDp(ALPHA_MASK_BITMAP_WIDTH_DP, dm);
+ Bitmap dst = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Canvas c = new Canvas(dst);
- Paint paint = new Paint(Paint.DITHER_FLAG);
- LinearGradient lg = new LinearGradient(0, 0, 0, gradientHeight,
- new int[]{
- 0x00FFFFFF,
- setColorAlphaBound(Color.WHITE, (int) (0xFF * 0.95)),
- 0xFFFFFFFF},
- new float[]{0f, 0.8f, 1f},
- Shader.TileMode.CLAMP);
+ Paint paint = new Paint(DITHER_FLAG);
+ LinearGradient lg = new LinearGradient(0, 0, 0, height,
+ colors, positions, Shader.TileMode.CLAMP);
paint.setShader(lg);
- c.drawRect(0, 0, width, gradientHeight, paint);
+ c.drawPaint(paint);
return dst;
}
}
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 66ed779..7e065a9 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -831,6 +831,10 @@
*/
public interface StatsLatencyLogger {
+ /**
+ * Should be in sync with:
+ * google3/wireless/android/sysui/aster/asterstats/launcher_event_processed.proto
+ */
enum LatencyType {
UNKNOWN(0),
// example: launcher restart that happens via daily backup and restore
diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java
index dcd61a8..5d85b1c 100644
--- a/src/com/android/launcher3/model/BaseLauncherBinder.java
+++ b/src/com/android/launcher3/model/BaseLauncherBinder.java
@@ -23,8 +23,6 @@
import android.os.Process;
import android.util.Log;
-import androidx.annotation.WorkerThread;
-
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel.CallbackTask;
@@ -36,13 +34,11 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.LooperIdleLock;
import com.android.launcher3.util.PackageUserKey;
-import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RunnableList;
import java.util.ArrayList;
@@ -150,9 +146,7 @@
/**
* Binds the all apps results from LoaderTask to the callbacks UX.
*/
- @WorkerThread
public void bindAllApps() {
- Preconditions.assertWorkerThread();
// shallow copy
AppInfo[] apps = mBgAllAppsList.copyData();
int flags = mBgAllAppsList.getFlags();
@@ -282,33 +276,18 @@
sortWorkspaceItemsSpatially(idp, currentWorkspaceItems);
sortWorkspaceItemsSpatially(idp, otherWorkspaceItems);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "Before posting startBinding");
- }
// Tell the workspace that we're about to start binding items
executeCallbacksTask(c -> {
c.clearPendingBinds();
c.startBinding();
}, mUiExecutor);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "1");
- }
// Bind workspace screens
executeCallbacksTask(c -> c.bindScreens(mOrderedScreenIds), mUiExecutor);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "2");
- }
// Load items on the current page.
bindWorkspaceItems(currentWorkspaceItems, mUiExecutor);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "3");
- }
bindAppWidgets(currentAppWidgets, mUiExecutor);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "4");
- }
if (!FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
mExtraItems.forEach(item ->
executeCallbacksTask(c -> c.bindExtraContainerItems(item), mUiExecutor));
@@ -317,18 +296,8 @@
RunnableList pendingTasks = new RunnableList();
Executor pendingExecutor = pendingTasks::add;
bindWorkspaceItems(otherWorkspaceItems, pendingExecutor);
-
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "5");
- }
bindAppWidgets(otherAppWidgets, pendingExecutor);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "6");
- }
executeCallbacksTask(c -> c.finishBindingItems(currentScreenIds), pendingExecutor);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "After posting finishBindingItems");
- }
pendingExecutor.execute(
() -> {
MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java
index 1ba015a..866e222 100644
--- a/src/com/android/launcher3/model/BaseModelUpdateTask.java
+++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java
@@ -22,7 +22,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
@@ -37,7 +36,6 @@
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
-import com.android.launcher3.util.Preconditions;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import java.util.ArrayList;
@@ -158,9 +156,7 @@
scheduleCallbackTask(c -> c.bindWorkspaceComponentsRemoved(matcher));
}
- @WorkerThread
public void bindApplicationsIfNeeded() {
- Preconditions.assertWorkerThread();
boolean changeFlag = mAllAppsList.getAndResetChangeFlag();
if (TestProtocol.sDebugTracing) {
Log.d(WORK_TAB_MISSING, "bindApplicationsIfNeeded changeFlag? " +
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 0767426..4f542fe 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -203,7 +203,7 @@
}
}
- Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
+ TraceHelper.INSTANCE.beginSection(TAG);
LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
@@ -327,7 +327,7 @@
memoryLogger.printLogs();
throw e;
}
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
public synchronized void stopLocked() {
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index d3a237c..623b557 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -249,6 +249,8 @@
bottomPadding + insets.getSystemWindowInsetBottom());
return insets.consumeSystemWindowInsets();
});
+ // Overriding Text Direction in the Androidx preference library to support RTL
+ view.setTextDirection(View.TEXT_DIRECTION_LOCALE);
}
@Override
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 8bc1c37..cec4574 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -384,8 +384,8 @@
} else {
logReachedState(targetState);
}
- mLauncher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(
- 1f).setDuration(0).start();
+ mLauncher.getRootView().getSysUiScrim().getSysUIMultiplier().animateToValue(1f)
+ .setDuration(0).start();
}
private void logReachedState(LauncherState targetState) {
diff --git a/src/com/android/launcher3/util/InstantAppResolver.java b/src/com/android/launcher3/util/InstantAppResolver.java
index 6f706d2..bdb5e77 100644
--- a/src/com/android/launcher3/util/InstantAppResolver.java
+++ b/src/com/android/launcher3/util/InstantAppResolver.java
@@ -42,14 +42,7 @@
return false;
}
- public boolean isInstantApp(Context context, String packageName) {
- PackageManager packageManager = context.getPackageManager();
- try {
- return isInstantApp(packageManager.getPackageInfo(packageName, 0).applicationInfo);
- } catch (PackageManager.NameNotFoundException e) {
- Log.e("InstantAppResolver", "Failed to determine whether package is instant app "
- + packageName, e);
- }
+ public boolean isInstantApp(String packageName, int userId) {
return false;
}
}
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 1d6bc25..91203a7 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -164,13 +164,6 @@
}
}
- public static Intent getStyleWallpapersIntent(Context context) {
- return new Intent(Intent.ACTION_SET_WALLPAPER).setComponent(
- new ComponentName(context.getString(R.string.wallpaper_picker_package),
- context.getString(R.string.custom_activity_picker)
- ));
- }
-
/**
* Starts the details activity for {@code info}
*/
diff --git a/src/com/android/launcher3/util/TraceHelper.java b/src/com/android/launcher3/util/TraceHelper.java
index c23df77..138cc4a 100644
--- a/src/com/android/launcher3/util/TraceHelper.java
+++ b/src/com/android/launcher3/util/TraceHelper.java
@@ -15,12 +15,17 @@
*/
package com.android.launcher3.util;
+import android.annotation.SuppressLint;
import android.os.Trace;
import androidx.annotation.MainThread;
+import com.android.launcher3.Utilities;
+
import java.util.function.Supplier;
+import kotlin.random.Random;
+
/**
* A wrapper around {@link Trace} to allow better testing.
*
@@ -36,54 +41,63 @@
// Temporarily ignore blocking binder calls for this trace.
public static final int FLAG_IGNORE_BINDERS = 1 << 1;
- public static final int FLAG_CHECK_FOR_RACE_CONDITIONS = 1 << 2;
-
- public static final int FLAG_UI_EVENT =
- FLAG_ALLOW_BINDER_TRACKING | FLAG_CHECK_FOR_RACE_CONDITIONS;
-
/**
* Static instance of Trace helper, overridden in tests.
*/
public static TraceHelper INSTANCE = new TraceHelper();
/**
- * @return a token to pass into {@link #endSection(Object)}.
+ * @see Trace#beginSection(String)
*/
- public Object beginSection(String sectionName) {
- return beginSection(sectionName, 0);
- }
-
- public Object beginSection(String sectionName, int flags) {
+ public void beginSection(String sectionName) {
Trace.beginSection(sectionName);
- return null;
}
/**
- * @param token the token returned from {@link #beginSection(String, int)}
+ * @see Trace#endSection()
*/
- public void endSection(Object token) {
+ public void endSection() {
Trace.endSection();
}
/**
- * Similar to {@link #beginSection} but doesn't add a trace section.
+ * @see Trace#beginAsyncSection(String, int)
+ * @return a SafeCloseable that can be used to end the session
*/
- public Object beginFlagsOverride(int flags) {
- return null;
+ @SuppressWarnings("NewApi")
+ @SuppressLint("NewApi")
+ public SafeCloseable beginAsyncSection(String sectionName) {
+ if (!Utilities.ATLEAST_Q) {
+ return () -> { };
+ }
+ int cookie = Random.Default.nextInt();
+ Trace.beginAsyncSection(sectionName, cookie);
+ return () -> Trace.endAsyncSection(sectionName, cookie);
}
- public void endFlagsOverride(Object token) { }
+ /**
+ * Returns a SafeCloseable to temporarily ignore blocking binder calls.
+ */
+ @SuppressWarnings("NewApi")
+ @SuppressLint("NewApi")
+ public SafeCloseable allowIpcs(String rpcName) {
+ if (!Utilities.ATLEAST_Q) {
+ return () -> { };
+ }
+ int cookie = Random.Default.nextInt();
+ Trace.beginAsyncSection(rpcName, cookie);
+ return () -> Trace.endAsyncSection(rpcName, cookie);
+ }
/**
* Temporarily ignore blocking binder calls for the duration of this {@link Supplier}.
+ *
+ * Note, new features should be designed to not rely on mainThread RPCs.
*/
@MainThread
public static <T> T allowIpcs(String rpcName, Supplier<T> supplier) {
- Object traceToken = INSTANCE.beginSection(rpcName, FLAG_IGNORE_BINDERS);
- try {
+ try (SafeCloseable c = INSTANCE.allowIpcs(rpcName)) {
return supplier.get();
- } finally {
- INSTANCE.endSection(traceToken);
}
}
}
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index aebf752..55febc7 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -55,7 +55,6 @@
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
import java.util.ArrayList;
@@ -190,14 +189,9 @@
*/
public static ArrayList<OptionItem> getOptions(Launcher launcher) {
ArrayList<OptionItem> options = new ArrayList<>();
- boolean styleWallpaperExists = styleWallpapersExists(launcher);
- int resString = styleWallpaperExists
- ? R.string.styles_wallpaper_button_text : R.string.wallpaper_button_text;
- int resDrawable = styleWallpaperExists
- ? R.drawable.ic_palette : R.drawable.ic_wallpaper;
options.add(new OptionItem(launcher,
- resString,
- resDrawable,
+ R.string.styles_wallpaper_button_text,
+ R.drawable.ic_palette,
IGNORE,
OptionsPopupView::startWallpaperPicker));
if (!WidgetsModel.GO_DISABLE_WIDGETS) {
@@ -274,12 +268,8 @@
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
.putExtra(EXTRA_WALLPAPER_OFFSET,
launcher.getWorkspace().getWallpaperOffsetForCenterPage())
- .putExtra(EXTRA_WALLPAPER_LAUNCH_SOURCE, "app_launched_launcher");
- if (!styleWallpapersExists(launcher)) {
- intent.putExtra(EXTRA_WALLPAPER_FLAVOR, "wallpaper_only");
- } else {
- intent.putExtra(EXTRA_WALLPAPER_FLAVOR, "focus_wallpaper");
- }
+ .putExtra(EXTRA_WALLPAPER_LAUNCH_SOURCE, "app_launched_launcher")
+ .putExtra(EXTRA_WALLPAPER_FLAVOR, "focus_wallpaper");
String pickerPackage = launcher.getString(R.string.wallpaper_picker_package);
if (!TextUtils.isEmpty(pickerPackage)) {
intent.setPackage(pickerPackage);
@@ -322,9 +312,4 @@
this.clickListener = clickListener;
}
}
-
- private static boolean styleWallpapersExists(Context context) {
- return context.getPackageManager().resolveActivity(
- PackageManagerHelper.getStyleWallpapersIntent(context), 0) != null;
- }
}
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index dbaf19b..7f2d4a0 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -155,7 +155,6 @@
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
public static final String WORK_TAB_MISSING = "b/243688989";
public static final String TWO_TASKBAR_LONG_CLICKS = "b/262282528";
- public static final String WORKSPACE_LOADS_FOREVER = "b/267200150";
public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display";
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
index c426480..b07a402 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
+++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
@@ -28,7 +28,6 @@
import com.android.launcher3.celllayout.testcases.MultipleCellLayoutsSimpleReorder;
import com.android.launcher3.tapl.Widget;
import com.android.launcher3.tapl.WidgetResizeFrame;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.rule.ShellCommandRule;
@@ -115,11 +114,8 @@
// resetLoaderState triggers the launcher to start loading the workspace which allows
// waitForLauncherCondition to wait for that condition, otherwise the condition would
// always be true and it wouldn't wait for the changes to be applied.
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "before resetLoaderState");
resetLoaderState();
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "after resetLoaderState");
waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
- Log.d(TestProtocol.WORKSPACE_LOADS_FOREVER, "after waitForLauncherCondition");
Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.getCellX(),
mainWidgetCellPos.getCellY());
assertNotNull(widget);
diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java b/tests/src/com/android/launcher3/util/RaceConditionReproducer.java
deleted file mode 100644
index ed2ec7b..0000000
--- a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.util;
-
-import static com.android.launcher3.util.Executors.createAndStartNewLooper;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.os.Handler;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Event processor for reliably reproducing multithreaded apps race conditions in tests.
- *
- * The app notifies us about “events” that happen in its threads. The race condition test runs the
- * test action multiple times (aka iterations), trying to generate all possible permutations of
- * these events. It keeps a set of all seen event sequences and steers the execution towards
- * executing events in previously unseen order. It does it by postponing execution of threads that
- * would lead to an already seen sequence.
- *
- * If an event A occurs before event B in the sequence, this is how execution order looks like:
- * Events: ... A ... B ...
- * Events and instructions, guaranteed order:
- * (instructions executed prior to A) A ... B (instructions executed after B)
- *
- * Each iteration has 3 parts (phases).
- * Phase 1. Picking a previously seen event subsequence that we believe can have previously unseen
- * continuations. Reproducing this sequence by pausing threads that would lead to other sequences.
- * Phase 2. Trying to generate previously unseen continuation of the sequence from Phase 1. We need
- * one new event after that sequence. All threads leading to seen continuations will be postponed
- * for some short period of time. The phase ends once the new event is registered, or after the
- * period of time ends (in which case we declare that the sequence can’t have new continuations).
- * Phase 3. Releasing all threads and letting the test iteration run till its end.
- *
- * The iterations end when all seen paths have been declared “uncontinuable”.
- *
- * When we register event XXX:enter, we hold all other events until we register XXX:exit.
- */
-public class RaceConditionReproducer {
- private static final String TAG = "RaceConditionReproducer";
-
- private static final boolean ENTER = true;
- private static final boolean EXIT = false;
- private static final String ENTER_POSTFIX = "enter";
- private static final String EXIT_POSTFIX = "exit";
-
- private static final long SHORT_TIMEOUT_MS = 2000;
- private static final long LONG_TIMEOUT_MS = 60000;
- // Handler used to resume postponed events.
- private static final Handler POSTPONED_EVENT_RESUME_HANDLER =
- new Handler(createAndStartNewLooper("RaceConditionEventResumer"));
-
- public static String enterExitEvt(String eventName, boolean isEnter) {
- return eventName + ":" + (isEnter ? ENTER_POSTFIX : EXIT_POSTFIX);
- }
-
- public static String enterEvt(String eventName) {
- return enterExitEvt(eventName, ENTER);
- }
-
- public static String exitEvt(String eventName) {
- return enterExitEvt(eventName, EXIT);
- }
-
- /**
- * Event in a particular sequence of events. A node in the prefix tree of all seen event
- * sequences.
- */
- private class EventNode {
- // Events that were seen just after this event.
- private final Map<String, EventNode> mNextEvents = new HashMap<>();
- // Whether we believe that further iterations will not be able to add more events to
- // mNextEvents.
- private boolean mStoppedAddingChildren = true;
-
- private void debugDump(StringBuilder sb, int indent, String name) {
- for (int i = 0; i < indent; ++i) sb.append('.');
- sb.append(!mStoppedAddingChildren ? "+" : "-");
- sb.append(" : ");
- sb.append(name);
- if (mLastRegisteredEvent == this) sb.append(" <");
- sb.append('\n');
-
- for (String key : mNextEvents.keySet()) {
- mNextEvents.get(key).debugDump(sb, indent + 2, key);
- }
- }
-
- /** Number of leaves in the subtree with this node as a root. */
- private int numberOfLeafNodes() {
- if (mNextEvents.isEmpty()) return 1;
-
- int leaves = 0;
- for (String event : mNextEvents.keySet()) {
- leaves += mNextEvents.get(event).numberOfLeafNodes();
- }
- return leaves;
- }
-
- /**
- * Whether we believe that further iterations will not be able add nodes to the subtree with
- * this node as a root.
- */
- private boolean stoppedAddingChildrenToTree() {
- if (!mStoppedAddingChildren) return false;
-
- for (String event : mNextEvents.keySet()) {
- if (!mNextEvents.get(event).stoppedAddingChildrenToTree()) return false;
- }
- return true;
- }
-
- /**
- * In the subtree with this node as a root, tries finding a node where we may have a
- * chance to add new children.
- * If succeeds, returns true and fills 'path' with the sequence of events to that node;
- * otherwise returns false.
- */
- private boolean populatePathToGrowthPoint(List<String> path) {
- for (String event : mNextEvents.keySet()) {
- if (mNextEvents.get(event).populatePathToGrowthPoint(path)) {
- path.add(0, event);
- return true;
- }
- }
- if (!mStoppedAddingChildren) {
- // Mark that we have finished adding children. It will remain true if no new
- // children are added, or will be set to false upon adding a new child.
- mStoppedAddingChildren = true;
- return true;
- }
- return false;
- }
- }
-
- // Starting point of all event sequences; the root of the prefix tree representation all
- // sequences generated by test iterations. A test iteration can add nodes int it.
- private EventNode mRoot = new EventNode();
- // During a test iteration, the last event that was registered.
- private EventNode mLastRegisteredEvent;
- // Length of the current sequence of registered events for the current test iteration.
- private int mRegisteredEventCount = 0;
- // During the first part of a test iteration, we go to a specific node under mRoot by
- // 'playing back' mSequenceToFollow. During this part, all events that don't belong to this
- // sequence get postponed.
- private List<String> mSequenceToFollow = new ArrayList<>();
- // Collection of events that got postponed, with corresponding wait objects used to let them go.
- private Map<String, Semaphore> mPostponedEvents = new HashMap<>();
- // Callback to run by POSTPONED_EVENT_RESUME_HANDLER, used to let go of all currently
- // postponed events.
- private Runnable mResumeAllEventsCallback;
- // String representation of the sequence of events registered so far for the current test
- // iteration. After registering any event, we output it to the log. The last output before
- // the test failure can be later played back to reliable reproduce the exact sequence of
- // events that broke the test.
- // Format: EV1|EV2|...\EVN
- private StringBuilder mCurrentSequence;
- // When not null, we are in a repro mode. We run only one test iteration, and are trying to
- // reproduce the event sequence represented by this string. The format is same as for
- // mCurrentSequence.
- private final String mReproString;
-
- /* Constructor for a normal test. */
- public RaceConditionReproducer() {
- mReproString = null;
- }
-
- /**
- * Constructor for reliably reproducing a race condition failure. The developer should find in
- * the log the latest "Repro sequence:" record and locally modify the test by passing that
- * string to the constructor. Running the test will have only one iteration that will reliably
- * "play back" that sequence.
- */
- public RaceConditionReproducer(String reproString) {
- mReproString = reproString;
- }
-
- public RaceConditionReproducer(String... reproSequence) {
- this(String.join("|", reproSequence));
- }
-
- public synchronized String getCurrentSequenceString() {
- return mCurrentSequence.toString();
- }
-
- /**
- * Starts a new test iteration. Events reported via RaceConditionTracker.onEvent before this
- * call will be ignored.
- */
- public synchronized void startIteration() {
- mLastRegisteredEvent = mRoot;
- mRegisteredEventCount = 0;
- mCurrentSequence = new StringBuilder();
- Log.d(TAG, "Repro sequence: " + mCurrentSequence);
- mSequenceToFollow = mReproString != null ?
- parseReproString(mReproString) : generateSequenceToFollowLocked();
- Log.e(TAG, "---- Start of iteration; state:\n" + dumpStateLocked());
- checkIfCompletedSequenceToFollowLocked();
-
- TraceHelperForTest.setRaceConditionReproducer(this);
- }
-
- /**
- * Ends a new test iteration. Events reported via RaceConditionTracker.onEvent after this call
- * will be ignored.
- * Returns whether we need more iterations.
- */
- public synchronized boolean finishIteration() {
- TraceHelperForTest.setRaceConditionReproducer(null);
-
- runResumeAllEventsCallbackLocked();
- assertTrue("Non-empty postponed events", mPostponedEvents.isEmpty());
- assertTrue("Last registered event is :enter", lastEventAsEnter() == null);
-
- // No events came after mLastRegisteredEvent. It doesn't make sense to come to it again
- // because we won't see new continuations.
- mLastRegisteredEvent.mStoppedAddingChildren = true;
- Log.e(TAG, "---- End of iteration; state:\n" + dumpStateLocked());
- if (mReproString != null) {
- assertTrue("Repro mode: failed to reproduce the sequence",
- mCurrentSequence.toString().startsWith(mReproString));
- }
- // If we are in a repro mode, we need only one iteration. Otherwise, continue if the tree
- // has prospective growth points.
- return mReproString == null && !mRoot.stoppedAddingChildrenToTree();
- }
-
- private static List<String> parseReproString(String reproString) {
- return Arrays.asList(reproString.split("\\|"));
- }
-
- /**
- * Called when the app issues an event.
- */
- public void onEvent(String event) {
- final Semaphore waitObject = tryRegisterEvent(event);
- if (waitObject != null) {
- waitUntilCanRegister(event, waitObject);
- }
- }
-
- /**
- * Returns whether the last event was not an XXX:enter, or this event is a matching XXX:exit.
- */
- private boolean canRegisterEventNowLocked(String event) {
- final String lastEventAsEnter = lastEventAsEnter();
- final String thisEventAsExit = eventAsExit(event);
-
- if (lastEventAsEnter != null) {
- if (!lastEventAsEnter.equals(thisEventAsExit)) {
- assertTrue("YYY:exit after XXX:enter", thisEventAsExit == null);
- // Last event was :enter, but this event is not :exit.
- return false;
- }
- } else {
- // Previous event was not :enter.
- assertTrue(":exit after a non-enter event", thisEventAsExit == null);
- }
- return true;
- }
-
- /**
- * Registers an event issued by the app and returns null or decides that the event must be
- * postponed, and returns an object to wait on.
- */
- private synchronized Semaphore tryRegisterEvent(String event) {
- Log.d(TAG, "Event issued by the app: " + event);
-
- if (!canRegisterEventNowLocked(event)) {
- return createWaitObjectForPostponedEventLocked(event);
- }
-
- if (mRegisteredEventCount < mSequenceToFollow.size()) {
- // We are in the first part of the iteration. We only register events that follow the
- // mSequenceToFollow and postponing all other events.
- if (event.equals(mSequenceToFollow.get(mRegisteredEventCount))) {
- // The event is the next one expected in the sequence. Register it.
- registerEventLocked(event);
-
- // If there are postponed events that could continue the sequence, register them.
- while (mRegisteredEventCount < mSequenceToFollow.size() &&
- mPostponedEvents.containsKey(
- mSequenceToFollow.get(mRegisteredEventCount))) {
- registerPostponedEventLocked(mSequenceToFollow.get(mRegisteredEventCount));
- }
-
- // Perhaps we just completed the required sequence...
- checkIfCompletedSequenceToFollowLocked();
- } else {
- // The event is not the next one in the sequence. Postpone it.
- return createWaitObjectForPostponedEventLocked(event);
- }
- } else if (mRegisteredEventCount == mSequenceToFollow.size()) {
- // The second phase of the iteration. We have just registered the whole
- // mSequenceToFollow, and want to add previously not seen continuations for the last
- // node in the sequence aka 'growth point'.
- if (!mLastRegisteredEvent.mNextEvents.containsKey(event) || mReproString != null) {
- // The event was never seen as a continuation for the current node.
- // Or we are in repro mode, in which case we are not in business of generating
- // new sequences after we've played back the required sequence.
- // Register it immediately.
- registerEventLocked(event);
- } else {
- // The event was seen as a continuation for the current node. Postpone it, hoping
- // that a new event will come from other threads.
- return createWaitObjectForPostponedEventLocked(event);
- }
- } else {
- // The third phase of the iteration. We are past the growth point and register
- // everything that comes.
- registerEventLocked(event);
- // Register events that may have been postponed while waiting for an :exit event
- // during the third phase. We don't do this if just registered event is :enter.
- if (eventAsEnter(event) == null && mRegisteredEventCount > mSequenceToFollow.size()) {
- registerPostponedEventsLocked(new HashSet<>(mPostponedEvents.keySet()));
- }
- }
- return null;
- }
-
- /** Called when there are chances that we just have registered the whole mSequenceToFollow. */
- private void checkIfCompletedSequenceToFollowLocked() {
- if (mRegisteredEventCount == mSequenceToFollow.size()) {
- // We just entered the second phase of the iteration. We have just registered the
- // whole mSequenceToFollow, and want to add previously not seen continuations for the
- // last node in the sequence aka 'growth point'. All seen continuations will be
- // postponed for SHORT_TIMEOUT_MS. At the end of this time period, we'll let them go.
- scheduleResumeAllEventsLocked();
-
- // Among the events that were postponed during the first stage, there may be an event
- // that wasn't seen after the current. If so, register it immediately because this
- // creates a new sequence.
- final Set<String> keys = new HashSet<>(mPostponedEvents.keySet());
- keys.removeAll(mLastRegisteredEvent.mNextEvents.keySet());
- if (!keys.isEmpty()) {
- registerPostponedEventLocked(keys.iterator().next());
- }
- }
- }
-
- private Semaphore createWaitObjectForPostponedEventLocked(String event) {
- final Semaphore waitObject = new Semaphore(0);
- assertTrue("Event already postponed: " + event, !mPostponedEvents.containsKey(event));
- mPostponedEvents.put(event, waitObject);
- return waitObject;
- }
-
- private void waitUntilCanRegister(String event, Semaphore waitObject) {
- try {
- assertTrue("Never registered event: " + event,
- waitObject.tryAcquire(LONG_TIMEOUT_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e) {
- fail("Wait was interrupted");
- }
- }
-
- /** Schedules resuming all postponed events after SHORT_TIMEOUT_MS */
- private void scheduleResumeAllEventsLocked() {
- assertTrue(mResumeAllEventsCallback == null);
- mResumeAllEventsCallback = this::allEventsResumeCallback;
- POSTPONED_EVENT_RESUME_HANDLER.postDelayed(mResumeAllEventsCallback, SHORT_TIMEOUT_MS);
- }
-
- private synchronized void allEventsResumeCallback() {
- assertTrue("In callback, but callback is not set", mResumeAllEventsCallback != null);
- mResumeAllEventsCallback = null;
- registerPostponedEventsLocked(new HashSet<>(mPostponedEvents.keySet()));
- }
-
- private void registerPostponedEventsLocked(Collection<String> events) {
- for (String event : events) {
- registerPostponedEventLocked(event);
- if (eventAsEnter(event) != null) {
- // Once :enter is registered, switch to waiting for :exit to come. Won't register
- // other postponed events.
- break;
- }
- }
- }
-
- private void registerPostponedEventLocked(String event) {
- mPostponedEvents.remove(event).release();
- registerEventLocked(event);
- }
-
- /**
- * If the last registered event was XXX:enter, returns XXX, otherwise, null.
- */
- private String lastEventAsEnter() {
- return eventAsEnter(mCurrentSequence.substring(mCurrentSequence.lastIndexOf("|") + 1));
- }
-
- /**
- * If the event is XXX:postfix, returns XXX, otherwise, null.
- */
- private static String prefixFromPostfixedEvent(String event, String postfix) {
- final int columnPos = event.indexOf(':');
- if (columnPos != -1 && postfix.equals(event.substring(columnPos + 1))) {
- return event.substring(0, columnPos);
- }
- return null;
- }
-
- /**
- * If the event is XXX:enter, returns XXX, otherwise, null.
- */
- private static String eventAsEnter(String event) {
- return prefixFromPostfixedEvent(event, ENTER_POSTFIX);
- }
-
- /**
- * If the event is XXX:exit, returns XXX, otherwise, null.
- */
- private static String eventAsExit(String event) {
- return prefixFromPostfixedEvent(event, EXIT_POSTFIX);
- }
-
- private void registerEventLocked(String event) {
- assertTrue(canRegisterEventNowLocked(event));
-
- Log.d(TAG, "Actually registering event: " + event);
- EventNode next = mLastRegisteredEvent.mNextEvents.get(event);
- if (next == null) {
- // This event wasn't seen after mLastRegisteredEvent.
- next = new EventNode();
- mLastRegisteredEvent.mNextEvents.put(event, next);
- // The fact that we've added a new event after the previous one means that the
- // previous event is still a growth point, unless this event is :exit, which means
- // that the previous event is :enter.
- mLastRegisteredEvent.mStoppedAddingChildren = eventAsExit(event) != null;
- }
-
- mLastRegisteredEvent = next;
- mRegisteredEventCount++;
-
- if (mCurrentSequence.length() > 0) mCurrentSequence.append("|");
- mCurrentSequence.append(event);
- Log.d(TAG, "Repro sequence: " + mCurrentSequence);
- }
-
- private void runResumeAllEventsCallbackLocked() {
- if (mResumeAllEventsCallback != null) {
- POSTPONED_EVENT_RESUME_HANDLER.removeCallbacks(mResumeAllEventsCallback);
- mResumeAllEventsCallback.run();
- }
- }
-
- private CharSequence dumpStateLocked() {
- StringBuilder sb = new StringBuilder();
-
- sb.append("Sequence to follow: ");
- for (String event : mSequenceToFollow) sb.append(" " + event);
- sb.append(".\n");
- sb.append("Registered event count: " + mRegisteredEventCount);
-
- sb.append("\nPostponed events: ");
- for (String event : mPostponedEvents.keySet()) sb.append(" " + event);
- sb.append(".");
-
- sb.append("\nNodes: \n");
- mRoot.debugDump(sb, 0, "");
- return sb;
- }
-
- public int numberOfLeafNodes() {
- return mRoot.numberOfLeafNodes();
- }
-
- private List<String> generateSequenceToFollowLocked() {
- ArrayList<String> sequence = new ArrayList<>();
- mRoot.populatePathToGrowthPoint(sequence);
- return sequence;
- }
-}
diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java b/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java
deleted file mode 100644
index 59f2173..0000000
--- a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public class RaceConditionReproducerTest {
- private final static String SOME_VALID_SEQUENCE_3_3 = "B1|A1|A2|B2|A3|B3";
-
- private static int factorial(int n) {
- int res = 1;
- for (int i = 2; i <= n; ++i) res *= i;
- return res;
- }
-
- RaceConditionReproducer eventProcessor;
-
- @Before
- public void setup() {
- eventProcessor = new RaceConditionReproducer();
- }
-
- @After
- public void tearDown() {
- TraceHelperForTest.cleanup();
- }
-
- private void run3_3_TestAction() throws InterruptedException {
- Thread tb = new Thread(() -> {
- eventProcessor.onEvent("B1");
- eventProcessor.onEvent("B2");
- eventProcessor.onEvent("B3");
- });
- tb.start();
-
- eventProcessor.onEvent("A1");
- eventProcessor.onEvent("A2");
- eventProcessor.onEvent("A3");
-
- tb.join();
- }
-
- @Test
- @Ignore // The test is too long for continuous testing.
- // 2 threads, 3 events each.
- public void test3_3() throws Exception {
- boolean sawTheValidSequence = false;
-
- for (; ; ) {
- eventProcessor.startIteration();
- run3_3_TestAction();
- final boolean needMoreIterations = eventProcessor.finishIteration();
-
- sawTheValidSequence = sawTheValidSequence ||
- SOME_VALID_SEQUENCE_3_3.equals(eventProcessor.getCurrentSequenceString());
-
- if (!needMoreIterations) break;
- }
-
- assertEquals("Wrong number of leaf nodes",
- factorial(3 + 3) / (factorial(3) * factorial(3)),
- eventProcessor.numberOfLeafNodes());
- assertTrue(sawTheValidSequence);
- }
-
- @Test
- @Ignore // The test is too long for continuous testing.
- // 2 threads, 3 events, including enter-exit pairs each.
- public void test3_3_enter_exit() throws Exception {
- boolean sawTheValidSequence = false;
-
- for (; ; ) {
- eventProcessor.startIteration();
- Thread tb = new Thread(() -> {
- eventProcessor.onEvent("B1:enter");
- eventProcessor.onEvent("B1:exit");
- eventProcessor.onEvent("B2");
- eventProcessor.onEvent("B3:enter");
- eventProcessor.onEvent("B3:exit");
- });
- tb.start();
-
- eventProcessor.onEvent("A1");
- eventProcessor.onEvent("A2:enter");
- eventProcessor.onEvent("A2:exit");
- eventProcessor.onEvent("A3:enter");
- eventProcessor.onEvent("A3:exit");
-
- tb.join();
- final boolean needMoreIterations = eventProcessor.finishIteration();
-
- sawTheValidSequence = sawTheValidSequence ||
- "B1:enter|B1:exit|A1|A2:enter|A2:exit|B2|A3:enter|A3:exit|B3:enter|B3:exit".
- equals(eventProcessor.getCurrentSequenceString());
-
- if (!needMoreIterations) break;
- }
-
- assertEquals("Wrong number of leaf nodes",
- factorial(3 + 3) / (factorial(3) * factorial(3)),
- eventProcessor.numberOfLeafNodes());
- assertTrue(sawTheValidSequence);
- }
-
- @Test
- // 2 threads, 3 events each; reproducing a particular event sequence.
- public void test3_3_ReproMode() throws Exception {
- eventProcessor = new RaceConditionReproducer(SOME_VALID_SEQUENCE_3_3);
- eventProcessor.startIteration();
- run3_3_TestAction();
- assertTrue(!eventProcessor.finishIteration());
- assertEquals(SOME_VALID_SEQUENCE_3_3, eventProcessor.getCurrentSequenceString());
-
- assertEquals("Wrong number of leaf nodes", 1, eventProcessor.numberOfLeafNodes());
- }
-
- @Test
- @Ignore // The test is too long for continuous testing.
- // 2 threads with 2 events; 1 thread with 1 event.
- public void test2_1_2() throws Exception {
- for (; ; ) {
- eventProcessor.startIteration();
- Thread tb = new Thread(() -> {
- eventProcessor.onEvent("B1");
- eventProcessor.onEvent("B2");
- });
- tb.start();
-
- Thread tc = new Thread(() -> {
- eventProcessor.onEvent("C1");
- });
- tc.start();
-
- eventProcessor.onEvent("A1");
- eventProcessor.onEvent("A2");
-
- tb.join();
- tc.join();
-
- if (!eventProcessor.finishIteration()) break;
- }
-
- assertEquals("Wrong number of leaf nodes",
- factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)),
- eventProcessor.numberOfLeafNodes());
- }
-
- @Test
- @Ignore // The test is too long for continuous testing.
- // 2 threads with 2 events; 1 thread with 1 event. Includes enter-exit pairs.
- public void test2_1_2_enter_exit() throws Exception {
- for (; ; ) {
- eventProcessor.startIteration();
- Thread tb = new Thread(() -> {
- eventProcessor.onEvent("B1:enter");
- eventProcessor.onEvent("B1:exit");
- eventProcessor.onEvent("B2:enter");
- eventProcessor.onEvent("B2:exit");
- });
- tb.start();
-
- Thread tc = new Thread(() -> {
- eventProcessor.onEvent("C1:enter");
- eventProcessor.onEvent("C1:exit");
- });
- tc.start();
-
- eventProcessor.onEvent("A1:enter");
- eventProcessor.onEvent("A1:exit");
- eventProcessor.onEvent("A2:enter");
- eventProcessor.onEvent("A2:exit");
-
- tb.join();
- tc.join();
-
- if (!eventProcessor.finishIteration()) break;
- }
-
- assertEquals("Wrong number of leaf nodes",
- factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)),
- eventProcessor.numberOfLeafNodes());
- }
-}
diff --git a/tests/src/com/android/launcher3/util/TraceHelperForTest.java b/tests/src/com/android/launcher3/util/TraceHelperForTest.java
deleted file mode 100644
index f1c8a67..0000000
--- a/tests/src/com/android/launcher3/util/TraceHelperForTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * Copyright (C) 2019 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.util;
-
-import java.util.LinkedList;
-import java.util.function.IntConsumer;
-
-public class TraceHelperForTest extends TraceHelper {
-
- private static final TraceHelperForTest INSTANCE_FOR_TEST = new TraceHelperForTest();
-
- private final ThreadLocal<LinkedList<TraceInfo>> mStack =
- ThreadLocal.withInitial(LinkedList::new);
-
- private RaceConditionReproducer mRaceConditionReproducer;
- private IntConsumer mFlagsChangeListener;
-
- public static void setRaceConditionReproducer(RaceConditionReproducer reproducer) {
- TraceHelper.INSTANCE = INSTANCE_FOR_TEST;
- INSTANCE_FOR_TEST.mRaceConditionReproducer = reproducer;
- }
-
- public static void cleanup() {
- INSTANCE_FOR_TEST.mRaceConditionReproducer = null;
- INSTANCE_FOR_TEST.mFlagsChangeListener = null;
- }
-
- public static void setFlagsChangeListener(IntConsumer listener) {
- TraceHelper.INSTANCE = INSTANCE_FOR_TEST;
- INSTANCE_FOR_TEST.mFlagsChangeListener = listener;
- }
-
- private TraceHelperForTest() { }
-
- @Override
- public Object beginSection(String sectionName, int flags) {
- LinkedList<TraceInfo> stack = mStack.get();
- TraceInfo info = new TraceInfo(sectionName, flags);
- stack.add(info);
-
- if ((flags & TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS) != 0
- && mRaceConditionReproducer != null) {
- mRaceConditionReproducer.onEvent(RaceConditionReproducer.enterEvt(sectionName));
- }
- updateBinderTracking(stack);
-
- super.beginSection(sectionName, flags);
- return info;
- }
-
- @Override
- public void endSection(Object token) {
- LinkedList<TraceInfo> stack = mStack.get();
- if (stack.size() == 0) {
- new Throwable().printStackTrace();
- }
- TraceInfo info = (TraceInfo) token;
- stack.remove(info);
- if ((info.flags & TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS) != 0
- && mRaceConditionReproducer != null) {
- mRaceConditionReproducer.onEvent(RaceConditionReproducer.exitEvt(info.sectionName));
- }
- updateBinderTracking(stack);
-
- super.endSection(token);
- }
-
- @Override
- public Object beginFlagsOverride(int flags) {
- LinkedList<TraceInfo> stack = mStack.get();
- TraceInfo info = new TraceInfo(null, flags);
- stack.add(info);
- updateBinderTracking(stack);
- super.beginFlagsOverride(flags);
- return info;
- }
-
- @Override
- public void endFlagsOverride(Object token) {
- super.endFlagsOverride(token);
- LinkedList<TraceInfo> stack = mStack.get();
- TraceInfo info = (TraceInfo) token;
- stack.remove(info);
- updateBinderTracking(stack);
- }
-
- private void updateBinderTracking(LinkedList<TraceInfo> stack) {
- if (mFlagsChangeListener != null) {
- mFlagsChangeListener.accept(stack.stream()
- .mapToInt(info -> info.flags).reduce(0, (a, b) -> a | b));
- }
- }
-
- private static class TraceInfo {
- public final String sectionName;
- public final int flags;
-
- TraceInfo(String sectionName, int flags) {
- this.sectionName = sectionName;
- this.flags = flags;
- }
- }
-}