Merge "Prediction icons in Taskbar were updating when dragging icon in the same place"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3984890..b459b2d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -58,6 +58,7 @@
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
+ <action android:name="android.intent.action.SHOW_WORK_APPS" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
diff --git a/quickstep/protos_overrides/launcher_atom_extension.proto b/quickstep/protos_overrides/launcher_atom_extension.proto
index d2dc0cb..ff050ea 100644
--- a/quickstep/protos_overrides/launcher_atom_extension.proto
+++ b/quickstep/protos_overrides/launcher_atom_extension.proto
@@ -23,20 +23,24 @@
// Message name should match with launcher_atom_extension.proto message at
// the AOSP level.
message ExtendedContainers {
+ reserved 2; // Deleted fields
oneof Container{
DeviceSearchResultContainer device_search_result_container = 1;
- CorrectedDeviceSearchResultContainer corrected_device_search_result_container = 2;
}
}
// Represents on-device search result container.
message DeviceSearchResultContainer{
optional int32 query_length = 1;
-}
+ optional SearchAttributes search_attributes = 2;
-// Represents on-device search result container with results from spell-corrected query.
-message CorrectedDeviceSearchResultContainer{
- optional int32 query_length = 1;
-}
+ message SearchAttributes{
+ // True if results are based on spell corrected query
+ optional bool corrected_query = 1;
+
+ // True if the item's title/content is a direct match to the search query, false otherwise.
+ optional bool direct_match = 2;
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
index 4404ffb..3f29e43 100644
--- a/quickstep/src/com/android/launcher3/model/AppEventProducer.java
+++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
+import static com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers.ContainerCase.DEVICE_SEARCH_RESULT_CONTAINER;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_CONVERTED_TO_ICON;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_PREDICTION_PINNED;
@@ -293,10 +294,9 @@
case SEARCH_RESULT_CONTAINER:
return "search-results";
case EXTENDED_CONTAINERS: {
- switch(ci.getExtendedContainers().getContainerCase()) {
- case DEVICE_SEARCH_RESULT_CONTAINER:
- case CORRECTED_DEVICE_SEARCH_RESULT_CONTAINER:
- return "search-results";
+ if (ci.getExtendedContainers().getContainerCase()
+ == DEVICE_SEARCH_RESULT_CONTAINER) {
+ return "search-results";
}
}
default: // fall out
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index bc06944..e218db1 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -249,6 +249,8 @@
private RunningWindowAnim[] mRunningWindowAnim;
// Possible second animation running at the same time as mRunningWindowAnim
private Animator mParallelRunningAnim;
+ // Current running divider animation
+ private ValueAnimator mDividerAnimator;
private boolean mIsMotionPaused;
private boolean mHasMotionEverBeenPaused;
@@ -831,8 +833,8 @@
// Notify when the animation starts
flushOnRecentsAnimationAndLauncherBound();
- TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
- false /*shown*/, true /*animate*/);
+ // Start hiding the divider
+ setDividerShown(false /* shown */, false /* immediate */);
// Only add the callback to enable the input consumer after we actually have the controller
mStateCallback.runOnceAtState(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
@@ -849,8 +851,7 @@
mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
if (mRecentsAnimationTargets != null) {
- TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
- true /*shown*/, true /*animate*/);
+ setDividerShown(true /* shown */, false /* immediate */);
}
// Defer clearing the controller and the targets until after we've updated the state
@@ -1000,8 +1001,7 @@
mStateCallback.setState(STATE_RESUME_LAST_TASK);
}
if (mRecentsAnimationTargets != null) {
- TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
- true /*shown*/, false /*animate*/);
+ setDividerShown(true /* shown */, true /* immediate */);
}
break;
}
@@ -1653,8 +1653,7 @@
mActivityInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget());
if (mRecentsAnimationTargets != null) {
- TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
- true /*shown*/, false /*animate*/);
+ setDividerShown(true /* shown */, true /* immediate */);
}
// Leave the pending invisible flag, as it may be used by wallpaper open animation.
@@ -1920,8 +1919,7 @@
@Override
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
if (!controller.getFinishTargetIsLauncher()) {
- TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
- true /*shown*/, true /*animate*/);
+ setDividerShown(true /* shown */, false /* immediate */);
}
mRecentsAnimationController = null;
mRecentsAnimationTargets = null;
@@ -2026,6 +2024,19 @@
return scaleProgress;
}
+ private void setDividerShown(boolean shown, boolean immediate) {
+ if (mDividerAnimator != null) {
+ mDividerAnimator.cancel();
+ }
+ mDividerAnimator = TaskViewUtils.createSplitAuxiliarySurfacesAnimator(
+ mRecentsAnimationTargets.nonApps, shown, (dividerAnimator) -> {
+ dividerAnimator.start();
+ if (immediate) {
+ dividerAnimator.end();
+ }
+ });
+ }
+
/**
* Used for winscope tracing, see launcher_trace.proto
* @see com.android.systemui.shared.tracing.ProtoTraceable#writeToProto
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 5b69aeb..e67b0a5 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -88,6 +88,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Consumer;
/**
* Utility class for helpful methods related to {@link TaskView} objects and their tasks.
@@ -554,8 +555,16 @@
nonAppTargets, depthController, pa);
if (launcherClosing) {
// TODO(b/182592057): differentiate between "restore split" vs "launch fullscreen app"
- TaskViewUtils.setSplitAuxiliarySurfacesShown(nonAppTargets,
- true /*shown*/, true /*animate*/, pa);
+ TaskViewUtils.createSplitAuxiliarySurfacesAnimator(nonAppTargets, true /*shown*/,
+ (dividerAnimator) -> {
+ // If split apps are launching, we want to delay showing the divider bar
+ // until the very end once the apps are mostly in place. This is because we
+ // aren't moving the divider leash in the relative position with the
+ // launching apps.
+ dividerAnimator.setStartDelay(pa.getDuration()
+ - SPLIT_DIVIDER_ANIM_DURATION);
+ pa.add(dividerAnimator);
+ });
}
Animator childStateAnimation = null;
@@ -610,16 +619,17 @@
anim.addListener(windowAnimEndListener);
}
- public static void setSplitAuxiliarySurfacesShown(RemoteAnimationTargetCompat[] nonApps,
- boolean shown, boolean animate) {
- setSplitAuxiliarySurfacesShown(nonApps, shown, animate,null);
- }
-
- private static void setSplitAuxiliarySurfacesShown(
- @NonNull RemoteAnimationTargetCompat[] nonApps, boolean shown, boolean animate,
- @Nullable PendingAnimation splitLaunchAnimation) {
+ /**
+ * Creates an animation to show/hide the auxiliary surfaces (aka. divider bar), only calling
+ * {@param animatorHandler} if there are valid surfaces to animate.
+ *
+ * @return the animator animating the surfaces
+ */
+ public static ValueAnimator createSplitAuxiliarySurfacesAnimator(
+ RemoteAnimationTargetCompat[] nonApps, boolean shown,
+ Consumer<ValueAnimator> animatorHandler) {
if (nonApps == null || nonApps.length == 0) {
- return;
+ return null;
}
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
@@ -634,20 +644,7 @@
}
}
if (!hasSurfaceToAnimate) {
- return;
- }
-
- if (!animate) {
- for (SurfaceControl leash : auxiliarySurfaces) {
- t.setAlpha(leash, shown ? 1 : 0);
- if (shown) {
- t.show(leash);
- } else {
- t.hide(leash);
- }
- }
- t.apply();
- return;
+ return null;
}
ValueAnimator dockFadeAnimator = ValueAnimator.ofFloat(0f, 1f);
@@ -684,15 +681,7 @@
}
});
dockFadeAnimator.setDuration(SPLIT_DIVIDER_ANIM_DURATION);
- if (splitLaunchAnimation != null) {
- // If split apps are launching, we want to delay showing the divider bar until the very
- // end once the apps are mostly in place. This is because we aren't moving the divider
- // leash in the relative position with the launching apps.
- dockFadeAnimator.setStartDelay(
- splitLaunchAnimation.getDuration() - SPLIT_DIVIDER_ANIM_DURATION);
- splitLaunchAnimation.add(dockFadeAnimator);
- } else {
- dockFadeAnimator.start();
- }
+ animatorHandler.accept(dockFadeAnimator);
+ return dockFadeAnimator;
}
}
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 676161e..ad52a66 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -48,6 +48,7 @@
import com.android.launcher3.logger.LauncherAtom.FromState;
import com.android.launcher3.logger.LauncherAtom.ToState;
import com.android.launcher3.logger.LauncherAtomExtensions.DeviceSearchResultContainer;
+import com.android.launcher3.logger.LauncherAtomExtensions.DeviceSearchResultContainer.SearchAttributes;
import com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
@@ -89,6 +90,12 @@
private static final int EXTENDED_CONTAINERS_HIERARCHY_OFFSET = 300;
private static final int ATTRIBUTE_MULTIPLIER = 100;
+ /**
+ * Flags for converting SearchAttribute to integer value.
+ */
+ private static final int SEARCH_ATTRIBUTES_CORRECTED_QUERY = 1;
+ private static final int SEARCH_ATTRIBUTES_DIRECT_MATCH = 1 << 1;
+
public static final CopyOnWriteArrayList<StatsLogConsumer> LOGS_CONSUMER =
new CopyOnWriteArrayList<>();
@@ -405,7 +412,10 @@
atomInfo.getFolderIcon().getToLabelState().getNumber() /* toState */,
atomInfo.getFolderIcon().getLabelInfo() /* edittext */,
getCardinality(atomInfo) /* cardinality */,
- getFeatures(atomInfo) /* features */);
+ getFeatures(atomInfo) /* features */
+ // TODO(b/217753033) : Add SearchAttributes field after necessary approval
+ // getSearchAttributes(atomInfo) /* searchAttributes */
+ );
}
}
@@ -561,6 +571,25 @@
return 0;
}
+ private static int getSearchAttributes(LauncherAtom.ItemInfo info) {
+ if (info.getContainerInfo().getExtendedContainers().getDeviceSearchResultContainer()
+ .hasSearchAttributes()) {
+ return searchAttributesToInt(info.getContainerInfo().getExtendedContainers()
+ .getDeviceSearchResultContainer().getSearchAttributes());
+ }
+ return 0;
+ }
+
+ private static int searchAttributesToInt(SearchAttributes searchAttributes) {
+ int response = 0;
+ if (searchAttributes.getCorrectedQuery()) {
+ response = response | SEARCH_ATTRIBUTES_CORRECTED_QUERY;
+ }
+ if (searchAttributes.getDirectMatch()) {
+ response = response | SEARCH_ATTRIBUTES_DIRECT_MATCH;
+ }
+ return response;
+ }
/**
* Interface to get stats log while it is dispatched to the system
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 1d14bad..2a2d1dd 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -4297,9 +4297,12 @@
if (isSuccess) {
if (tv.getTaskIds()[1] != -1) {
// TODO(b/194414938): make this part of the animations instead.
- TaskViewUtils.setSplitAuxiliarySurfacesShown(mRemoteTargetHandles[0]
- .getTransformParams().getTargetSet().nonApps,
- true /*shown*/, false /*animate*/);
+ TaskViewUtils.createSplitAuxiliarySurfacesAnimator(
+ mRemoteTargetHandles[0].getTransformParams().getTargetSet().nonApps,
+ true /*shown*/, (dividerAnimator) -> {
+ dividerAnimator.start();
+ dividerAnimator.end();
+ });
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && tv.isRunningTask()) {
finishRecentsAnimation(false /* toRecents */, null);
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index 7f9f63e..6df6212 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -33,7 +33,6 @@
android:id="@+id/all_apps_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_below="@id/search_container_all_apps"
android:clipToPadding="false"
android:paddingTop="@dimen/all_apps_header_top_padding"
android:paddingBottom="@dimen/all_apps_header_bottom_padding"
diff --git a/res/layout/all_apps_content_layout.xml b/res/layout/all_apps_content_layout.xml
deleted file mode 100644
index 5698977..0000000
--- a/res/layout/all_apps_content_layout.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 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.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/apps_list_view_override"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@id/search_container_all_apps"
- android:clipToPadding="false"
- android:descendantFocusability="afterDescendants"
- android:focusable="true"
- android:layout_marginTop="@dimen/all_apps_header_top_padding"
- android:orientation="vertical">
-</LinearLayout>
diff --git a/res/layout/all_apps_fast_scroller.xml b/res/layout/all_apps_fast_scroller.xml
index 5537bc6..f6a6156 100644
--- a/res/layout/all_apps_fast_scroller.xml
+++ b/res/layout/all_apps_fast_scroller.xml
@@ -21,7 +21,7 @@
android:id="@+id/fast_scroller_popup"
style="@style/FastScrollerPopup"
android:layout_alignParentEnd="true"
- android:layout_below="@+id/search_container_all_apps"
+ android:layout_alignTop="@+id/all_apps_header"
android:layout_marginEnd="@dimen/fastscroll_popup_margin" />
<com.android.launcher3.views.RecyclerViewFastScroller
@@ -30,7 +30,7 @@
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
- android:layout_below="@+id/search_container_all_apps"
+ android:layout_alignTop="@+id/all_apps_header"
android:layout_marginEnd="@dimen/fastscroll_end_margin"
launcher:canThumbDetach="true" />
diff --git a/res/layout/all_apps_rv_layout.xml b/res/layout/all_apps_rv_layout.xml
index c353b36..26d8ecc 100644
--- a/res/layout/all_apps_rv_layout.xml
+++ b/res/layout/all_apps_rv_layout.xml
@@ -19,7 +19,6 @@
android:id="@+id/apps_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@id/search_container_all_apps"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:focusable="true" />
diff --git a/res/layout/all_apps_tabs.xml b/res/layout/all_apps_tabs.xml
index de4a69d..cf68f51 100644
--- a/res/layout/all_apps_tabs.xml
+++ b/res/layout/all_apps_tabs.xml
@@ -20,7 +20,6 @@
android:id="@+id/all_apps_tabs_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@id/search_container_all_apps"
android:layout_gravity="center_horizontal|top"
android:layout_marginTop="@dimen/all_apps_header_pill_height"
android:clipChildren="true"
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 59c40cc..661aa00 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -41,6 +41,7 @@
import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions;
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD;
+import static com.android.launcher3.logging.StatsLogManager.EventEnum;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_ENTRY;
@@ -124,6 +125,7 @@
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.allapps.AllAppsStore;
import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.launcher3.allapps.BaseAllAppsContainerView;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PropertyListBuilder;
@@ -141,6 +143,8 @@
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
+import com.android.launcher3.logger.LauncherAtom.WorkspaceContainer;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
@@ -1103,14 +1107,23 @@
&& mAllAppsSessionLogId == null) {
// creates new instance ID since new all apps session is started.
mAllAppsSessionLogId = new InstanceIdSequence().newInstanceId();
- getStatsLogManager()
- .logger()
- .log(FeatureFlags.ENABLE_DEVICE_SEARCH.get()
- ? LAUNCHER_ALLAPPS_ENTRY_WITH_DEVICE_SEARCH
- : LAUNCHER_ALLAPPS_ENTRY);
+ getStatsLogManager().logger().withContainerInfo(
+ ContainerInfo.newBuilder().setWorkspace(
+ WorkspaceContainer.newBuilder().setPageIndex(
+ getWorkspace().getCurrentPage())).build())
+ .log(getAllAppsEntryEvent());
}
}
+ /**
+ * Returns {@link EventEnum} that should be logged when Launcher enters into AllApps state.
+ */
+ protected EventEnum getAllAppsEntryEvent() {
+ return FeatureFlags.ENABLE_DEVICE_SEARCH.get()
+ ? LAUNCHER_ALLAPPS_ENTRY_WITH_DEVICE_SEARCH
+ : LAUNCHER_ALLAPPS_ENTRY;
+ }
+
@Override
public void onStateSetEnd(LauncherState state) {
super.onStateSetEnd(state);
@@ -1567,6 +1580,7 @@
boolean isActionMain = Intent.ACTION_MAIN.equals(intent.getAction());
boolean internalStateHandled = ACTIVITY_TRACKER.handleNewIntent(this);
hideKeyboard();
+
if (isActionMain) {
if (!internalStateHandled) {
// In all these cases, only animate if we're already on home
@@ -1595,6 +1609,8 @@
handleGestureContract(intent);
} else if (Intent.ACTION_ALL_APPS.equals(intent.getAction())) {
showAllAppsFromIntent(alreadyOnHome);
+ } else if (Intent.ACTION_SHOW_WORK_APPS.equals(intent.getAction())) {
+ showAllAppsWorkTabFromIntent(alreadyOnHome);
}
TraceHelper.INSTANCE.endSection(traceToken);
@@ -1605,6 +1621,11 @@
getStateManager().goToState(ALL_APPS, alreadyOnHome);
}
+ private void showAllAppsWorkTabFromIntent(boolean alreadyOnHome) {
+ showAllAppsFromIntent(alreadyOnHome);
+ mAppsView.switchToTab(BaseAllAppsContainerView.AdapterHolder.WORK);
+ }
+
/**
* Handles gesture nav contract
*/
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 070b98e..fb87f88 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -21,6 +21,7 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.widget.RelativeLayout;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.RecyclerView;
@@ -177,6 +178,28 @@
}
@Override
+ protected View replaceRVContainer(boolean showTabs) {
+ View rvContainer = super.replaceRVContainer(showTabs);
+ if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+ alignParentTop(rvContainer);
+ layoutAboveSearchContainer(rvContainer);
+ } else {
+ layoutBelowSearchContainer(rvContainer);
+ }
+ return rvContainer;
+ }
+
+ @Override
+ void setupHeader() {
+ super.setupHeader();
+ if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+ alignParentTop(mHeader);
+ } else {
+ layoutBelowSearchContainer(mHeader);
+ }
+ }
+
+ @Override
protected void updateHeaderScroll(int scrolledOffset) {
super.updateHeaderScroll(scrolledOffset);
if (mSearchUiManager.getEditText() == null) {
@@ -202,6 +225,36 @@
@Override
protected int getHeaderBottom() {
+ if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+ return super.getHeaderBottom();
+ }
return super.getHeaderBottom() + mSearchContainer.getBottom();
}
+
+ private void layoutBelowSearchContainer(View v) {
+ if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
+ return;
+ }
+ RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
+ layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
+ layoutParams.removeRule(RelativeLayout.ABOVE);
+ layoutParams.addRule(RelativeLayout.BELOW, R.id.search_container_all_apps);
+ }
+
+ private void layoutAboveSearchContainer(View v) {
+ if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
+ return;
+ }
+ RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
+ layoutParams.addRule(RelativeLayout.ABOVE, R.id.search_container_all_apps);
+ }
+
+ private void alignParentTop(View v) {
+ if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
+ return;
+ }
+ RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
+ layoutParams.removeRule(RelativeLayout.BELOW);
+ layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ }
}
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index b257407..2b2c7c5 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -331,6 +331,16 @@
return mViewPager.getNextPage() == 0;
}
+ /**
+ * Switches the current page to the provided {@code tab} if tabs are supported, otherwise does
+ * nothing.
+ */
+ public void switchToTab(int tab) {
+ if (mUsingTabs) {
+ mViewPager.setCurrentPage(tab);
+ }
+ }
+
public LayoutInflater getLayoutInflater() {
return LayoutInflater.from(getContext());
}
@@ -368,8 +378,7 @@
}
@Override
- public void onDropCompleted(View target, DragObject d, boolean success) {
- }
+ public void onDropCompleted(View target, DragObject d, boolean success) {}
@Override
public void setInsets(Rect insets) {
@@ -478,7 +487,7 @@
return mHasWorkApps;
}
- private void replaceRVContainer(boolean showTabs) {
+ protected View replaceRVContainer(boolean showTabs) {
for (AdapterHolder adapterHolder : mAH) {
if (adapterHolder.mRecyclerView != null) {
adapterHolder.mRecyclerView.setLayoutManager(null);
@@ -503,6 +512,7 @@
mWorkManager.detachWorkModeSwitch();
mViewPager = null;
}
+ return newView;
}
public View getRecyclerViewContainer() {
@@ -634,7 +644,9 @@
@Override
public void drawOnScrim(Canvas canvas) {
- if (!mHeader.isHeaderProtectionSupported()) return;
+ if (!mHeader.isHeaderProtectionSupported()) {
+ return;
+ }
mHeaderPaint.setColor(mHeaderColor);
mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index 9d1b04e..bcb0d14 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -26,12 +26,14 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
+import android.view.ViewGroup;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
@@ -138,6 +140,15 @@
mWorkModeSwitch = (WorkModeSwitch) mAllApps.getLayoutInflater().inflate(
R.layout.work_mode_fab, mAllApps, false);
}
+ int workFabMarginBottom =
+ mWorkModeSwitch.getResources().getDimensionPixelSize(R.dimen.work_fab_margin);
+ if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+ workFabMarginBottom <<= 1; // Double margin to add space above search bar.
+ workFabMarginBottom +=
+ mWorkModeSwitch.getResources().getDimensionPixelSize(R.dimen.qsb_widget_height);
+ }
+ ((ViewGroup.MarginLayoutParams) mWorkModeSwitch.getLayoutParams()).bottomMargin =
+ workFabMarginBottom;
if (mWorkModeSwitch.getParent() != mAllApps) {
mAllApps.addView(mWorkModeSwitch);
}
@@ -158,7 +169,6 @@
mWorkModeSwitch = null;
}
-
public WorkAdapterProvider getAdapterProvider() {
return mAdapterProvider;
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 6e985f5..99c9bb9 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -92,6 +92,10 @@
public static final BooleanFlag ENABLE_ONE_SEARCH = new DeviceFlag("ENABLE_ONE_SEARCH", false,
"Use homescreen search box to complete allApps searches");
+ public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR =
+ getDebugFlag("ENABLE_FLOATING_SEARCH_BAR", false,
+ "Keep All Apps search bar at the bottom (but above keyboard if open)");
+
public static final BooleanFlag COLLECT_SEARCH_HISTORY = new DeviceFlag(
"COLLECT_SEARCH_HISTORY", false, "Allow launcher to collect search history for log");
@@ -249,7 +253,7 @@
"Enables accessing All Apps from the system Taskbar.");
public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(
- "ENABLE_SPLIT_FROM_WORKSPACE", false,
+ "ENABLE_SPLIT_FROM_WORKSPACE", true,
"Enable initiating split screen from workspace.");
public static void initialize(Context context) {
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index f0b4ba0..53c772f 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -16,12 +16,16 @@
package com.android.launcher3.widget;
+import android.annotation.TargetApi;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Handler;
import android.os.SystemClock;
+import android.os.Trace;
+import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.MotionEvent;
@@ -52,6 +56,8 @@
implements TouchCompleteListener, View.OnLongClickListener,
LocalColorExtractor.Listener {
+ private static final String TAG = "LauncherAppWidgetHostView";
+
// Related to the auto-advancing of widgets
private static final long ADVANCE_INTERVAL = 20000;
private static final long ADVANCE_STAGGER = 250;
@@ -61,6 +67,8 @@
// Maximum duration for which updates can be deferred.
private static final long UPDATE_LOCK_TIMEOUT_MILLIS = 1000;
+ private static final String TRACE_METHOD_NAME = "appwidget load-widget ";
+
private final Rect mTempRect = new Rect();
private final CheckLongPressHelper mLongPressHelper;
protected final Launcher mLauncher;
@@ -88,6 +96,8 @@
/** The drag content height which is only set when the drag content scale is not 1f. */
private int mDragContentHeight = 0;
+ private boolean mTrackingWidgetUpdate = false;
+
public LauncherAppWidgetHostView(Context context) {
super(context);
mLauncher = Launcher.getLauncher(context);
@@ -121,7 +131,25 @@
}
@Override
+ @TargetApi(Build.VERSION_CODES.Q)
+ public void setAppWidget(int appWidgetId, AppWidgetProviderInfo info) {
+ super.setAppWidget(appWidgetId, info);
+ if (!mTrackingWidgetUpdate && Utilities.ATLEAST_Q) {
+ mTrackingWidgetUpdate = true;
+ Trace.beginAsyncSection(TRACE_METHOD_NAME + info.provider, appWidgetId);
+ Log.i(TAG, "App widget created with id: " + appWidgetId);
+ }
+ }
+
+ @Override
+ @TargetApi(Build.VERSION_CODES.Q)
public void updateAppWidget(RemoteViews remoteViews) {
+ if (mTrackingWidgetUpdate && remoteViews != null && Utilities.ATLEAST_Q) {
+ Log.i(TAG, "App widget with id: " + getAppWidgetId() + " loaded");
+ Trace.endAsyncSection(
+ TRACE_METHOD_NAME + getAppWidgetInfo().provider, getAppWidgetId());
+ mTrackingWidgetUpdate = false;
+ }
if (isDeferringUpdates()) {
mDeferredRemoteViews = remoteViews;
return;
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 5511770..c22b4da 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -98,7 +98,7 @@
public final class LauncherInstrumentation {
private static final String TAG = "Tapl";
- private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 20;
+ private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 15;
private static final int GESTURE_STEP_MS = 16;
private static final long FORCE_PAUSE_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(2);