From 9e754b008d33c60727dcc9e0dd4173dc7f4f7a07 Mon Sep 17 00:00:00 2001 From: Andy Wickham Date: Sun, 9 Aug 2020 21:49:18 -0700 Subject: [PATCH 01/45] Adds ability to use LauncherPreviewRenderer in Sandbox. This is mostly a proof-of-concept for future use and tweaks as desired by UX. The idea is to better replicate the actual UI. Screenshot: https://drive.google.com/file/d/1EGDgcrSH2QZuSh6P3zWLBl6L8Xd-gtFY/view?usp=sharing Bug: 148542211 Change-Id: Ibed4b8118346ef72599463c9fd6a2f71166993fd --- .../res/layout/gesture_tutorial_fragment.xml | 9 ++-- .../interaction/EdgeBackGestureHandler.java | 4 ++ .../interaction/NavBarGestureHandler.java | 6 +++ .../interaction/RootSandboxLayout.java | 44 +++++++++++++++++++ .../interaction/SandboxLauncherRenderer.java | 44 +++++++++++++++++++ .../interaction/TutorialController.java | 4 ++ .../interaction/TutorialFragment.java | 21 +++++++-- src/com/android/launcher3/CellLayout.java | 7 +-- .../launcher3/WorkspaceLayoutManager.java | 6 ++- .../graphics/LauncherPreviewRenderer.java | 3 +- 10 files changed, 133 insertions(+), 15 deletions(-) create mode 100644 quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java create mode 100644 quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml index 43bf0ea966..52475dfc8a 100644 --- a/quickstep/res/layout/gesture_tutorial_fragment.xml +++ b/quickstep/res/layout/gesture_tutorial_fragment.xml @@ -13,7 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> - @@ -93,11 +94,11 @@ style="@style/TextAppearance.GestureTutorial.Feedback" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_above="@id/gesture_tutorial_fragment_action_button" + android:layout_below="@id/gesture_tutorial_fragment_titles_container" android:layout_centerHorizontal="true" android:layout_marginStart="@dimen/gesture_tutorial_feedback_margin_start_end" android:layout_marginEnd="@dimen/gesture_tutorial_feedback_margin_start_end" - android:layout_marginBottom="10dp"/> + android:layout_marginTop="40dp"/> @@ -126,4 +127,4 @@ android:background="@null" android:foreground="?android:attr/selectableItemBackgroundBorderless" android:stateListAnimator="@null"/> - \ No newline at end of file + \ No newline at end of file diff --git a/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java index e4b348e51b..9489bac266 100644 --- a/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java +++ b/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java @@ -143,6 +143,10 @@ public class EdgeBackGestureHandler implements OnTouchListener { return false; } + boolean onInterceptTouch(MotionEvent motionEvent) { + return isWithinTouchRegion((int) motionEvent.getX(), (int) motionEvent.getY()); + } + private boolean isWithinTouchRegion(int x, int y) { // Disallow if too far from the edge if (x > mEdgeWidth + mLeftInset && x < (mDisplaySize.x - mEdgeWidth - mRightInset)) { diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java index f897ecc01a..d1b0a7088f 100644 --- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java +++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java @@ -250,6 +250,12 @@ public class NavBarGestureHandler implements OnTouchListener, return intercepted; } + boolean onInterceptTouch(MotionEvent event) { + return mAssistantLeftRegion.contains(event.getX(), event.getY()) + || mAssistantRightRegion.contains(event.getX(), event.getY()) + || event.getY() >= mDisplaySize.y - mBottomGestureHeight; + } + protected void onMotionPauseDetected() { VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC); } diff --git a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java new file mode 100644 index 0000000000..db1afc2012 --- /dev/null +++ b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java @@ -0,0 +1,44 @@ +/* + * 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. + */ +package com.android.quickstep.interaction; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.RelativeLayout; + +import androidx.fragment.app.FragmentManager; + +/** Root layout that TutorialFragment uses to intercept motion events. */ +public class RootSandboxLayout extends RelativeLayout { + public RootSandboxLayout(Context context) { + super(context); + } + + public RootSandboxLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public RootSandboxLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent motionEvent) { + return ((TutorialFragment) FragmentManager.findFragment(this)) + .onInterceptTouch(motionEvent); + } +} diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java b/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java new file mode 100644 index 0000000000..80ffe6609e --- /dev/null +++ b/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java @@ -0,0 +1,44 @@ +/* + * 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. + */ +package com.android.quickstep.interaction; + +import android.content.Context; +import android.view.View; + +import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.graphics.LauncherPreviewRenderer; + +/** Renders a fake Launcher for use in the Sandbox. */ +class SandboxLauncherRenderer extends LauncherPreviewRenderer { + SandboxLauncherRenderer(Context context, InvariantDeviceProfile idp, boolean migrated) { + super(context, idp, migrated); + } + + @Override + public boolean shouldShowRealLauncherPreview() { + return false; + } + + @Override + public boolean shouldShowQsb() { + return false; + } + + @Override + public View.OnLongClickListener getWorkspaceChildOnLongClickListener() { + return null; + } +} diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java index 73f1f8cb8c..db80342673 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java @@ -47,6 +47,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, final TextView mTitleTextView; final TextView mSubtitleTextView; final TextView mFeedbackView; + final View mLauncherView; final ClipIconView mFakeIconView; final View mFakeTaskView; final View mRippleView; @@ -68,6 +69,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, mTitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_title_view); mSubtitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_subtitle_view); mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view); + mLauncherView = tutorialFragment.getLauncherView(); mFakeIconView = rootView.findViewById(R.id.gesture_tutorial_fake_icon_view); mFakeTaskView = rootView.findViewById(R.id.gesture_tutorial_fake_task_view); mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view); @@ -162,8 +164,10 @@ abstract class TutorialController implements BackGestureAttemptCallback, if (isComplete()) { hideHandCoachingAnimation(); + mLauncherView.setVisibility(View.INVISIBLE); } else { showHandCoachingAnimation(); + mLauncherView.setVisibility(View.VISIBLE); } } diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java index 9a8264d098..c90ad94b8c 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java @@ -31,6 +31,7 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; +import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.R; import com.android.quickstep.interaction.TutorialController.TutorialType; @@ -45,6 +46,7 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { TutorialHandAnimation mHandCoachingAnimation; EdgeBackGestureHandler mEdgeBackGestureHandler; NavBarGestureHandler mNavBarGestureHandler; + private View mLauncherView; public static TutorialFragment newInstance(TutorialType tutorialType) { TutorialFragment fragment = getFragmentForTutorialType(tutorialType); @@ -114,8 +116,11 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { return insets; }); mRootView.setOnTouchListener(this); - mHandCoachingAnimation = new TutorialHandAnimation(getContext(), mRootView, - getHandAnimationResId()); + mHandCoachingAnimation = + new TutorialHandAnimation(getContext(), mRootView, getHandAnimationResId()); + InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(getContext()); + mLauncherView = new SandboxLauncherRenderer(getContext(), dp, true).getRenderedView(); + ((ViewGroup) mRootView).addView(mLauncherView, 0); return mRootView; } @@ -133,11 +138,17 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { @Override public boolean onTouch(View view, MotionEvent motionEvent) { - // Note: Using logical or to ensure both functions get called. + // Note: Using logical-or to ensure both functions get called. return mEdgeBackGestureHandler.onTouch(view, motionEvent) | mNavBarGestureHandler.onTouch(view, motionEvent); } + boolean onInterceptTouch(MotionEvent motionEvent) { + // Note: Using logical-or to ensure both functions get called. + return mEdgeBackGestureHandler.onInterceptTouch(motionEvent) + | mNavBarGestureHandler.onInterceptTouch(motionEvent); + } + void onAttachedToWindow() { mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView()); } @@ -168,6 +179,10 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { return mRootView; } + View getLauncherView() { + return mLauncherView; + } + TutorialHandAnimation getHandAnimation() { return mHandCoachingAnimation; } diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 1cd201f99e..2809bd5a96 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -323,11 +323,8 @@ public class CellLayout extends ViewGroup { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (mTouchHelper != null - || (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev))) { - return true; - } - return false; + return mTouchHelper != null + || (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev)); } public void enableHardwareLayer(boolean hasLayer) { diff --git a/src/com/android/launcher3/WorkspaceLayoutManager.java b/src/com/android/launcher3/WorkspaceLayoutManager.java index ea887cc5eb..d6302ce580 100644 --- a/src/com/android/launcher3/WorkspaceLayoutManager.java +++ b/src/com/android/launcher3/WorkspaceLayoutManager.java @@ -130,12 +130,16 @@ public interface WorkspaceLayoutManager { } child.setHapticFeedbackEnabled(false); - child.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE); + child.setOnLongClickListener(getWorkspaceChildOnLongClickListener()); if (child instanceof DropTarget) { onAddDropTarget((DropTarget) child); } } + default View.OnLongClickListener getWorkspaceChildOnLongClickListener() { + return ItemLongClickListener.INSTANCE_WORKSPACE; + } + Hotseat getHotseat(); CellLayout getScreenWithId(int screenId); diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java index cd84c96171..effb3a4a0c 100644 --- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java @@ -513,8 +513,7 @@ public class LauncherPreviewRenderer extends ContextThemeWrapper } // Setup search view - SearchUiManager searchUiManager = - mRootView.findViewById(R.id.search_container_all_apps); + SearchUiManager searchUiManager = mRootView.findViewById(R.id.search_container_all_apps); mRootView.findViewById(R.id.apps_view).setTranslationY( mDp.heightPx - searchUiManager.getScrollRangeDelta(mInsets)); ViewGroup searchView = (ViewGroup) searchUiManager; From b1ee0a020fddf0d4aa25055273f612c0d3214264 Mon Sep 17 00:00:00 2001 From: vadimt Date: Thu, 17 Sep 2020 11:51:42 -0700 Subject: [PATCH 02/45] Remove tracing for a non-repro flake Change-Id: I53cc5020435bb3b630754a77d73590b35b595407 --- src/com/android/launcher3/pm/UserCache.java | 5 ----- src/com/android/launcher3/testing/TestProtocol.java | 1 - tests/src/com/android/launcher3/ui/WorkTabTest.java | 5 ----- 3 files changed, 11 deletions(-) diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java index 2d7d6b092a..5aab41a8a2 100644 --- a/src/com/android/launcher3/pm/UserCache.java +++ b/src/com/android/launcher3/pm/UserCache.java @@ -21,10 +21,8 @@ import android.content.Intent; import android.os.UserHandle; import android.os.UserManager; import android.util.ArrayMap; -import android.util.Log; import android.util.LongSparseArray; -import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.SafeCloseable; import com.android.launcher3.util.SimpleBroadcastReceiver; @@ -104,9 +102,6 @@ public class UserCache { mUsers = null; mUserToSerialMap = null; } - if (TestProtocol.sDebugTracing) { - Log.d(TestProtocol.WORK_PROFILE_REMOVED, "Work profile removed", new Exception()); - } } } diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index b2d008119e..7f7635561d 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -106,5 +106,4 @@ public final class TestProtocol { public static final String PAUSE_NOT_DETECTED = "b/139891609"; public static final String OVERIEW_NOT_ALLAPPS = "b/156095088"; public static final String NO_SWIPE_TO_HOME = "b/158017601"; - public static final String WORK_PROFILE_REMOVED = "b/159671700"; } diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java index f5f93c429f..e51c1cad37 100644 --- a/tests/src/com/android/launcher3/ui/WorkTabTest.java +++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java @@ -24,7 +24,6 @@ import static org.junit.Assert.assertTrue; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; -import android.util.Log; import android.widget.TextView; import androidx.test.filters.LargeTest; @@ -35,7 +34,6 @@ import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsPagedView; import com.android.launcher3.allapps.WorkModeSwitch; import com.android.launcher3.dragndrop.DragLayer; -import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.views.WorkEduView; import org.junit.After; @@ -135,9 +133,6 @@ public class WorkTabTest extends AbstractLauncherUiTest { workEduView.findViewById(R.id.proceed).callOnClick(); }); - executeOnLauncher(launcher -> Log.d(TestProtocol.WORK_PROFILE_REMOVED, - "Work profile status: " + launcher.getAppsView().isPersonalTabVisible())); - // verify work edu is seen next waitForLauncherCondition("Launcher did not show the next edu screen", l -> ((AllAppsPagedView) l.getAppsView().getContentView()).getCurrentPage() == WORK_PAGE From a85fa09885903470346faa97ff141cf5fd7ef2b2 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 21 Sep 2020 11:14:49 -0700 Subject: [PATCH 03/45] Make overview to home translate faster Fixes: 169052350 Change-Id: Ia6f21f479498927a5561819fcc256b698acbd095 --- .../src/com/android/quickstep/util/OverviewToHomeAnim.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java index 4a298d3bad..1031c5b080 100644 --- a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java +++ b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java @@ -18,8 +18,10 @@ package com.android.quickstep.util; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.DEACCEL; +import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.FINAL_FRAME; import static com.android.launcher3.anim.Interpolators.INSTANT; +import static com.android.launcher3.anim.Interpolators.clampToProgress; import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; @@ -110,7 +112,7 @@ public class OverviewToHomeAnim { boolean isLayoutNaturalToLauncher = recentsView.getPagedOrientationHandler() .isLayoutNaturalToLauncher(); config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, isLayoutNaturalToLauncher - ? DEACCEL : FINAL_FRAME); + ? clampToProgress(FAST_OUT_SLOW_IN, 0, 0.75f) : FINAL_FRAME); config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME); config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME); config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, INSTANT); From ca23b981d9aa72b98ac3c5d53009a7e9477be6be Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 21 Sep 2020 11:47:40 -0700 Subject: [PATCH 04/45] Allow touches on Workspace during transition from Overview Previously we only allowed touches on the hotseat (due to it being in the shelf in Overview); now we allow touches anywhere if we are not in an overview state. Test: enter overview, swipe up to home and scroll workspace or tap a workspace icon during the transition Bug: 169052350 Change-Id: I59ee695ba9cb6f5fddd8e41c5796cdba6b3d2112 --- .../android/quickstep/views/LauncherRecentsView.java | 11 ++--------- src/com/android/launcher3/Workspace.java | 7 ------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index b338bd07ee..52a7466429 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -36,7 +36,6 @@ import android.view.Surface; import android.widget.FrameLayout; import com.android.launcher3.BaseQuickstepLauncher; -import com.android.launcher3.Hotseat; import com.android.launcher3.LauncherState; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.StateManager.StateListener; @@ -177,14 +176,8 @@ public class LauncherRecentsView extends RecentsView @Override protected boolean shouldStealTouchFromSiblingsBelow(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - // Allow touches to go through to the hotseat. - Hotseat hotseat = mActivity.getHotseat(); - boolean touchingHotseat = hotseat.isShown() - && mActivity.getDragLayer().isEventOverView(hotseat, ev, this); - return !touchingHotseat; - } - return super.shouldStealTouchFromSiblingsBelow(ev); + return mActivity.getStateManager().getState().overviewUi + && super.shouldStealTouchFromSiblingsBelow(ev); } @Override diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 45aaa1b673..e7ded363a2 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -1175,13 +1175,6 @@ public class Workspace extends PagedView computeScrollHelper(false); } - @Override - protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) { - if (!isSwitchingState()) { - super.determineScrollingStart(ev, touchSlopScale); - } - } - @Override public void announceForAccessibility(CharSequence text) { // Don't announce if apps is on top of us. From 35a0c59021a267c84b7ffcb77782cbf8cdfb1d15 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Mon, 21 Sep 2020 15:49:24 -0700 Subject: [PATCH 05/45] Add window focus / visibility changed signals to AllAppsSearchPlugin Change-Id: Ieb48e398cca85dd4343e37fef0015f5e4fece86f --- .../com/android/systemui/plugins/AllAppsSearchPlugin.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java index 4fa670f44a..48369a4890 100644 --- a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java +++ b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java @@ -42,6 +42,12 @@ public interface AllAppsSearchPlugin extends Plugin { void onStateTransitionStart(int fromState, int toState); void onStateTransitionComplete(int state); + /** + * Send launcher window focus and visibility changed signals. + */ + void onWindowFocusChanged(boolean hasFocus); + void onWindowVisibilityChanged(int visibility); + /** * Send signal when user starts typing, perform search, when search ends */ From 25ecae1ef1d1900d680c6fe80d73f1b05278c7f3 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Mon, 14 Sep 2020 14:07:38 -0700 Subject: [PATCH 06/45] Add cross-fade animation to launcher for dark/light theme changes. Test: manual Fixing b/167570781. The launcher was not cross-fading it's original appearance with its new appearance on theme changes. It would only reload. Added a cross-fade animation. Demo: https://drive.google.com/file/d/1adRIJIMFw4WGdfSqZbS0caR2LH3j_yH-/view?usp=sharing Change-Id: I69162d9c49565e007cb33402389abf7d20806dd7 --- src/com/android/launcher3/Launcher.java | 59 ++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 90566f3ce8..1cf2e89e44 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -18,6 +18,7 @@ package com.android.launcher3; import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; +import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO; import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; @@ -70,6 +71,7 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.sqlite.SQLiteDatabase; +import android.graphics.Bitmap; import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; @@ -88,9 +90,10 @@ import android.view.Menu; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; import android.view.animation.OvershootInterpolator; +import android.widget.ImageView; import android.widget.Toast; import androidx.annotation.CallSuper; @@ -117,6 +120,7 @@ import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.folder.FolderGridOrganizer; import com.android.launcher3.folder.FolderIcon; +import com.android.launcher3.icons.BitmapRenderer; import com.android.launcher3.icons.IconCache; import com.android.launcher3.keyboard.CustomActionsPopup; import com.android.launcher3.keyboard.ViewGroupFocusHelper; @@ -269,6 +273,8 @@ public class Launcher extends StatefulActivity implements Launche private static final int APPS_VIEW_ALPHA_CHANNEL_INDEX = 1; private static final int SCRIM_VIEW_ALPHA_CHANNEL_INDEX = 0; + private static final int THEME_CROSS_FADE_ANIMATION_DURATION = 375; + private LauncherAppTransitionManager mAppTransitionManager; private Configuration mOldConfig; @@ -400,6 +406,7 @@ public class Launcher extends StatefulActivity implements Launche inflateRootView(R.layout.launcher); setupViews(); + crossFadeWithPreviousAppearance(); mPopupDataProvider = new PopupDataProvider(this::updateNotificationDots); mAppTransitionManager = LauncherAppTransitionManager.newInstance(this); @@ -476,7 +483,7 @@ public class Launcher extends StatefulActivity implements Launche () -> getStateManager().goToState(NORMAL)); if (Utilities.ATLEAST_R) { - getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); + getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING); } mLifecycleRegistry = new LifecycleRegistry(this); @@ -1364,6 +1371,18 @@ public class Launcher extends StatefulActivity implements Launche closeContextMenu(); } + @Override + public Object onRetainNonConfigurationInstance() { + int width = mDragLayer.getWidth(); + int height = mDragLayer.getHeight(); + + if (width <= 0 || height <= 0) { + return null; + } + + return BitmapRenderer.createHardwareBitmap(width, height, mDragLayer::draw); + } + public AllAppsTransitionController getAllAppsController() { return mAllAppsController; } @@ -2758,4 +2777,40 @@ public class Launcher extends StatefulActivity implements Launche void onLauncherResume(); } + + /** + * Cross-fades the launcher's updated appearance with its previous appearance. + * + * This method is used to cross-fade UI updates on activity creation, specifically dark mode + * updates. + */ + private void crossFadeWithPreviousAppearance() { + Bitmap previousAppearanceBitmap = (Bitmap) getLastNonConfigurationInstance(); + + if (previousAppearanceBitmap == null) { + return; + } + + ImageView crossFadeHelper = new ImageView(this); + + crossFadeHelper.setImageBitmap(previousAppearanceBitmap); + crossFadeHelper.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); + + InsettableFrameLayout.LayoutParams layoutParams = new InsettableFrameLayout.LayoutParams( + InsettableFrameLayout.LayoutParams.MATCH_PARENT, + InsettableFrameLayout.LayoutParams.MATCH_PARENT); + + layoutParams.ignoreInsets = true; + + crossFadeHelper.setLayoutParams(layoutParams); + + getRootView().addView(crossFadeHelper); + + crossFadeHelper + .animate() + .setDuration(THEME_CROSS_FADE_ANIMATION_DURATION) + .alpha(0f) + .withEndAction(() -> getRootView().removeView(crossFadeHelper)) + .start(); + } } From c445a359ae1609f431f4a83399e5adc74e39afb0 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 21 Sep 2020 16:18:43 -0700 Subject: [PATCH 07/45] Remove invisible home task view as soon as gesture to Recents ends Fixes: 168288052 Change-Id: I929d021b26dad8b2f9b1f6a659522054bbf3ec28 --- .../src/com/android/quickstep/AbsSwipeUpHandler.java | 10 +++++++--- .../quickstep/fallback/FallbackRecentsView.java | 10 ++++++---- .../src/com/android/quickstep/views/RecentsView.java | 10 +++++++++- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 26ad3778a7..22e6755eb1 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -434,9 +434,13 @@ public abstract class AbsSwipeUpHandler, Q extends mOnDeferredActivityLaunch); mGestureState.runOnceAtState(STATE_END_TARGET_SET, - () -> mDeviceState.getRotationTouchHelper(). - onEndTargetCalculated(mGestureState.getEndTarget(), - mActivityInterface)); + () -> { + mDeviceState.getRotationTouchHelper() + .onEndTargetCalculated(mGestureState.getEndTarget(), + mActivityInterface); + + mRecentsView.onGestureEndTargetCalculated(mGestureState.getEndTarget()); + }); notifyGestureStartedAsync(); } diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java index f5f525965f..8f2356c696 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -15,6 +15,7 @@ */ package com.android.quickstep.fallback; +import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS; import static com.android.quickstep.fallback.RecentsState.DEFAULT; import static com.android.quickstep.fallback.RecentsState.MODAL_TASK; @@ -27,6 +28,7 @@ import android.util.AttributeSet; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.statemanager.StateManager.StateListener; import com.android.quickstep.FallbackActivityInterface; +import com.android.quickstep.GestureState; import com.android.quickstep.RecentsActivity; import com.android.quickstep.views.OverviewActionsView; import com.android.quickstep.views.RecentsView; @@ -74,14 +76,14 @@ public class FallbackRecentsView extends RecentsView } /** - * When the gesture ends and recents view become interactive, we also remove the temporary + * When the gesture ends and we're going to recents view, we also remove the temporary * invisible tile added for the home task. This also pushes the remaining tiles back * to the center. */ @Override - public void onGestureAnimationEnd() { - super.onGestureAnimationEnd(); - if (mHomeTaskInfo != null) { + public void onGestureEndTargetCalculated(GestureState.GestureEndTarget endTarget) { + super.onGestureEndTargetCalculated(endTarget); + if (mHomeTaskInfo != null && endTarget == RECENTS) { TaskView tv = getTaskView(mHomeTaskInfo.taskId); if (tv != null) { PendingAnimation pa = createTaskDismissAnimation(tv, true, false, 150); diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 0362377399..b617817728 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -118,6 +118,7 @@ import com.android.launcher3.util.ResourceBasedOverride.Overrides; import com.android.launcher3.util.Themes; import com.android.launcher3.util.ViewPool; import com.android.quickstep.BaseActivityInterface; +import com.android.quickstep.GestureState; import com.android.quickstep.RecentsAnimationController; import com.android.quickstep.RecentsAnimationTargets; import com.android.quickstep.RecentsModel; @@ -1183,7 +1184,14 @@ public abstract class RecentsView extends PagedView } /** - * Called when a gesture from an app has finished. + * Called when a gesture from an app has finished, and an end target has been determined. + */ + public void onGestureEndTargetCalculated(GestureState.GestureEndTarget endTarget) { + + } + + /** + * Called when a gesture from an app has finished, and the animation to the target has ended. */ public void onGestureAnimationEnd() { if (mOrientationState.setGestureActive(false)) { From 0f5c9dbb6f72025b8fe3f1690c4c953b448dc3ea Mon Sep 17 00:00:00 2001 From: "Wesley.CW Wang" Date: Tue, 8 Sep 2020 16:33:11 +0800 Subject: [PATCH 08/45] Add intent extra when launching WallpaperPicker from Launcher - Add extra to the intent to help WallpaperPicker log the launch source - design doc: go/log-wppg-launch-source Bug: 154781896 Test: manually Change-Id: Ife774866b06251c01f28f72555c3dcc844fdc051 --- src/com/android/launcher3/Utilities.java | 4 ++++ src/com/android/launcher3/views/OptionsPopupView.java | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index bf637886b7..681118d882 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -141,6 +141,10 @@ public final class Utilities { public static final String EXTRA_WALLPAPER_OFFSET = "com.android.launcher3.WALLPAPER_OFFSET"; public static final String EXTRA_WALLPAPER_FLAVOR = "com.android.launcher3.WALLPAPER_FLAVOR"; + // An intent extra to indicate the launch source by launcher. + public static final String EXTRA_WALLPAPER_LAUNCH_SOURCE = + "com.android.wallpaper.LAUNCH_SOURCE"; + public static boolean IS_RUNNING_IN_TEST_HARNESS = ActivityManager.isRunningInTestHarness(); diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java index d558781be8..349ba9d5c1 100644 --- a/src/com/android/launcher3/views/OptionsPopupView.java +++ b/src/com/android/launcher3/views/OptionsPopupView.java @@ -16,6 +16,7 @@ package com.android.launcher3.views; import static com.android.launcher3.Utilities.EXTRA_WALLPAPER_FLAVOR; +import static com.android.launcher3.Utilities.EXTRA_WALLPAPER_LAUNCH_SOURCE; import static com.android.launcher3.Utilities.EXTRA_WALLPAPER_OFFSET; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS; @@ -210,7 +211,8 @@ public class OptionsPopupView extends ArrowPopup Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) .putExtra(EXTRA_WALLPAPER_OFFSET, - launcher.getWorkspace().getWallpaperOffsetForCenterPage()); + launcher.getWorkspace().getWallpaperOffsetForCenterPage()) + .putExtra(EXTRA_WALLPAPER_LAUNCH_SOURCE, "app_launched_launcher"); if (!Utilities.existsStyleWallpapers(launcher)) { intent.putExtra(EXTRA_WALLPAPER_FLAVOR, "wallpaper_only"); } else { From b3a0f1ffc06612e2d951e408293dd6eca9070765 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Sun, 20 Sep 2020 11:28:18 -0700 Subject: [PATCH 09/45] Add thumbnail viewtype to SearchTarget Bug: 168825522 Change-Id: I012665ef5e5ac66f37f9bdb37d55cc47726b29a9 --- res/layout/search_result_thumbnail.xml | 19 +++++ .../launcher3/allapps/AllAppsGridAdapter.java | 22 +++-- .../views/ThumbnailSearchResultView.java | 81 +++++++++++++++++++ .../systemui/plugins/shared/SearchTarget.java | 45 ++++++++++- 4 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 res/layout/search_result_thumbnail.xml create mode 100644 src/com/android/launcher3/views/ThumbnailSearchResultView.java diff --git a/res/layout/search_result_thumbnail.xml b/res/layout/search_result_thumbnail.xml new file mode 100644 index 0000000000..0cc5a29f60 --- /dev/null +++ b/res/layout/search_result_thumbnail.xml @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java index d1340faf23..e08bd5ba3b 100644 --- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java +++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java @@ -96,6 +96,8 @@ public class AllAppsGridAdapter extends public static final int VIEW_TYPE_SEARCH_PEOPLE = 1 << 11; + public static final int VIEW_TYPE_SEARCH_THUMBNAIL = 1 << 12; + // Common view type masks public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER; public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON; @@ -186,6 +188,7 @@ public class AllAppsGridAdapter extends || viewType == VIEW_TYPE_SEARCH_SLICE || viewType == VIEW_TYPE_SEARCH_ROW || viewType == VIEW_TYPE_SEARCH_PEOPLE + || viewType == VIEW_TYPE_SEARCH_THUMBNAIL || viewType == VIEW_TYPE_SEARCH_SHORTCUT; } } @@ -307,15 +310,21 @@ public class AllAppsGridAdapter extends @Override public int getSpanSize(int position) { - if (isIconViewType(mApps.getAdapterItems().get(position).viewType)) { - return 1; + int viewType = mApps.getAdapterItems().get(position).viewType; + if (isIconViewType(viewType)) { + return 1 * SPAN_MULTIPLIER; + } else if (viewType == VIEW_TYPE_SEARCH_THUMBNAIL) { + return mAppsPerRow; } else { // Section breaks span the full width - return mAppsPerRow; + return mAppsPerRow * SPAN_MULTIPLIER; } } } + // multiplier to support adapter item column count that is not mAppsPerRow. + private static final int SPAN_MULTIPLIER = 3; + private final BaseDraggingActivity mLauncher; private final LayoutInflater mLayoutInflater; private final AlphabeticalAppsList mApps; @@ -352,7 +361,7 @@ public class AllAppsGridAdapter extends public void setAppsPerRow(int appsPerRow) { mAppsPerRow = appsPerRow; - mGridLayoutMgr.setSpanCount(mAppsPerRow); + mGridLayoutMgr.setSpanCount(mAppsPerRow * SPAN_MULTIPLIER); } /** @@ -444,6 +453,9 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_PEOPLE: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_people_item, parent, false)); + case VIEW_TYPE_SEARCH_THUMBNAIL: + return new ViewHolder(mLayoutInflater.inflate( + R.layout.search_result_thumbnail, parent, false)); default: throw new RuntimeException("Unexpected view type"); } @@ -525,6 +537,7 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_ROW: case VIEW_TYPE_SEARCH_SHORTCUT: case VIEW_TYPE_SEARCH_PEOPLE: + case VIEW_TYPE_SEARCH_THUMBNAIL: PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView; payloadResultView.applyAdapterInfo( (AdapterItemWithPayload) mApps.getAdapterItems().get(position)); @@ -553,7 +566,6 @@ public class AllAppsGridAdapter extends } } - @Override public boolean onFailedToRecycleView(ViewHolder holder) { // Always recycle and we will reset the view when it is bound diff --git a/src/com/android/launcher3/views/ThumbnailSearchResultView.java b/src/com/android/launcher3/views/ThumbnailSearchResultView.java new file mode 100644 index 0000000000..decc861565 --- /dev/null +++ b/src/com/android/launcher3/views/ThumbnailSearchResultView.java @@ -0,0 +1,81 @@ +/* + * 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. + */ +package com.android.launcher3.views; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.util.AttributeSet; + +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.android.launcher3.Launcher; +import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload; +import com.android.launcher3.allapps.search.AllAppsSearchBarController; +import com.android.launcher3.util.Themes; +import com.android.systemui.plugins.AllAppsSearchPlugin; +import com.android.systemui.plugins.shared.SearchTarget; +import com.android.systemui.plugins.shared.SearchTargetEvent; + +/** + * A view representing a high confidence app search result that includes shortcuts + */ +public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView + implements AllAppsSearchBarController.PayloadResultHandler { + + Intent mIntent; + AllAppsSearchPlugin mPlugin; + + public ThumbnailSearchResultView(Context context) { + super(context); + } + + public ThumbnailSearchResultView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ThumbnailSearchResultView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + private void handleSelection(int eventType) { + Launcher launcher = Launcher.getLauncher(getContext()); + launcher.startActivitySafely(this, mIntent, null); + + SearchTargetEvent event = new SearchTargetEvent( + SearchTarget.ItemType.SCREENSHOT, eventType); + if (mPlugin != null) { + mPlugin.notifySearchTargetEvent(event); + } + } + + @Override + public void applyAdapterInfo(AdapterItemWithPayload adapterItem) { + RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(null, + (Bitmap) adapterItem.getPayload().getParcelable("bitmap")); + drawable.setCornerRadius(Themes.getDialogCornerRadius(getContext())); + setImageDrawable(drawable); + mIntent = new Intent(Intent.ACTION_VIEW) + .setData(Uri.parse(adapterItem.getPayload().getString("uri"))) + .setType("image/*") + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mPlugin = adapterItem.getPlugin(); + adapterItem.setSelectionHandler(this::handleSelection); + } +} diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java index c6b8300499..9144976f98 100644 --- a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java +++ b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java @@ -26,14 +26,52 @@ import java.util.List; public class SearchTarget implements Comparable { public enum ViewType { + + /** + * Consists of N number of icons. (N: launcher column count) + */ TOP_HIT(0), + + /** + * Consists of 1 icon and two subsidiary icons. + */ HERO(1), + + /** + * Main/sub/breadcrumb texts are rendered. + */ DETAIL(2), + + /** + * Consists of an icon, three detail strings. + */ ROW(3), + + /** + * Consists of an icon, three detail strings and a button. + */ ROW_WITH_BUTTON(4), + + /** + * Consists of a single slice view + */ SLICE(5), + + /** + * Similar to hero section. + */ SHORTCUT(6), - PEOPLE(7); + + /** + * Person icon and handling app icons are rendered. + */ + PEOPLE(7), + + /** + * N number of 1x1 ratio thumbnail is rendered. + * (current N = 3) + */ + THUMBNAIL(8); private final int mId; ViewType(int id) { @@ -52,9 +90,12 @@ public class SearchTarget implements Comparable { APP(3, "", ViewType.TOP_HIT), APP_HERO(4, "", ViewType.HERO), SHORTCUT(5, "Shortcuts", ViewType.SHORTCUT), - PEOPLE(6, "People", ViewType.PEOPLE); + PEOPLE(6, "People", ViewType.PEOPLE), + SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL); private final int mId; + + /** Used to render section title. */ private final String mTitle; private final ViewType mViewType; From 573b9ca9ada0b3b0dff7daeeff8acba7d4d95229 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 22 Sep 2020 12:13:35 -0700 Subject: [PATCH 10/45] Moving package installer initialization to worker thread Bug: 169002215 Change-Id: Ie7b9a1eb27b634455e3d43da411037642efd0534 --- .../android/launcher3/LauncherAppState.java | 2 +- .../launcher3/SessionCommitReceiver.java | 8 +++ .../launcher3/pm/InstallSessionHelper.java | 51 +++++++++++-------- .../launcher3/pm/InstallSessionTracker.java | 3 ++ 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index bfe327e40d..a4181c53c9 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -105,7 +105,7 @@ public class LauncherAppState { new Handler().post( () -> mInvariantDeviceProfile.verifyConfigChangedInBackground(context)); mInstallSessionTracker = InstallSessionHelper.INSTANCE.get(context) - .registerInstallTracker(mModel, MODEL_EXECUTOR); + .registerInstallTracker(mModel); // Register an observer to rebind the notification listener when dots are re-enabled. mNotificationDotsObserver = diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java index 007e5f5370..1bbbb2b59e 100644 --- a/src/com/android/launcher3/SessionCommitReceiver.java +++ b/src/com/android/launcher3/SessionCommitReceiver.java @@ -25,8 +25,11 @@ import android.content.pm.PackageManager; import android.os.UserHandle; import android.text.TextUtils; +import androidx.annotation.WorkerThread; + import com.android.launcher3.model.ItemInstallQueue; import com.android.launcher3.pm.InstallSessionHelper; +import com.android.launcher3.util.Executors; /** * BroadcastReceiver to handle session commit intent. @@ -38,6 +41,11 @@ public class SessionCommitReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { + Executors.MODEL_EXECUTOR.execute(() -> processIntent(context, intent)); + } + + @WorkerThread + private static void processIntent(Context context, Intent intent) { if (!isEnabled(context)) { // User has decided to not add icons on homescreen. return; diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java index 753a6dd85e..fa25114d49 100644 --- a/src/com/android/launcher3/pm/InstallSessionHelper.java +++ b/src/com/android/launcher3/pm/InstallSessionHelper.java @@ -17,6 +17,7 @@ package com.android.launcher3.pm; import static com.android.launcher3.Utilities.getPrefs; +import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -31,6 +32,7 @@ import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; +import androidx.annotation.WorkerThread; import com.android.launcher3.LauncherSettings; import com.android.launcher3.SessionCommitReceiver; @@ -39,10 +41,10 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.ItemInstallQueue; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; -import com.android.launcher3.util.LooperExecutor; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; +import com.android.launcher3.util.Preconditions; import java.util.ArrayList; import java.util.HashMap; @@ -65,27 +67,27 @@ public class InstallSessionHelper { private final LauncherApps mLauncherApps; private final Context mAppContext; - private final IntSet mPromiseIconIds; private final PackageInstaller mInstaller; private final HashMap mSessionVerifiedMap = new HashMap<>(); + private IntSet mPromiseIconIds; + public InstallSessionHelper(Context context) { mInstaller = context.getPackageManager().getPackageInstaller(); mAppContext = context.getApplicationContext(); mLauncherApps = context.getSystemService(LauncherApps.class); + } + @WorkerThread + private IntSet getPromiseIconIds() { + Preconditions.assertWorkerThread(); + if (mPromiseIconIds != null) { + return mPromiseIconIds; + } mPromiseIconIds = IntSet.wrap(IntArray.fromConcatString( - getPrefs(context).getString(PROMISE_ICON_IDS, ""))); + getPrefs(mAppContext).getString(PROMISE_ICON_IDS, ""))); - cleanUpPromiseIconIds(); - } - - public static UserHandle getUserHandle(SessionInfo info) { - return Utilities.ATLEAST_Q ? info.getUser() : Process.myUserHandle(); - } - - protected void cleanUpPromiseIconIds() { IntArray existingIds = new IntArray(); for (SessionInfo info : getActiveSessions().values()) { existingIds.add(info.getSessionId()); @@ -100,6 +102,7 @@ public class InstallSessionHelper { for (int i = idsToRemove.size() - 1; i >= 0; --i) { mPromiseIconIds.getArray().removeValue(idsToRemove.get(i)); } + return mPromiseIconIds; } public HashMap getActiveSessions() { @@ -126,7 +129,7 @@ public class InstallSessionHelper { private void updatePromiseIconPrefs() { getPrefs(mAppContext).edit() - .putString(PROMISE_ICON_IDS, mPromiseIconIds.getArray().toConcatString()) + .putString(PROMISE_ICON_IDS, getPromiseIconIds().getArray().toConcatString()) .apply(); } @@ -184,13 +187,15 @@ public class InstallSessionHelper { return info.getInstallReason() == PackageManager.INSTALL_REASON_DEVICE_RESTORE; } + @WorkerThread public boolean promiseIconAddedForId(int sessionId) { - return mPromiseIconIds.contains(sessionId); + return getPromiseIconIds().contains(sessionId); } + @WorkerThread public void removePromiseIconId(int sessionId) { - if (mPromiseIconIds.contains(sessionId)) { - mPromiseIconIds.getArray().removeValue(sessionId); + if (promiseIconAddedForId(sessionId)) { + getPromiseIconIds().getArray().removeValue(sessionId); updatePromiseIconPrefs(); } } @@ -203,6 +208,7 @@ public class InstallSessionHelper { * - The app is not already installed * - A promise icon for the session has not already been created */ + @WorkerThread void tryQueuePromiseAppIcon(PackageInstaller.SessionInfo sessionInfo) { if (FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get() && SessionCommitReceiver.isEnabled(mAppContext) @@ -210,25 +216,24 @@ public class InstallSessionHelper { && sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER && sessionInfo.getAppIcon() != null && !TextUtils.isEmpty(sessionInfo.getAppLabel()) - && !mPromiseIconIds.contains(sessionInfo.getSessionId()) + && !promiseIconAddedForId(sessionInfo.getSessionId()) && new PackageManagerHelper(mAppContext).getApplicationInfo( sessionInfo.getAppPackageName(), getUserHandle(sessionInfo), 0) == null) { ItemInstallQueue.INSTANCE.get(mAppContext) .queueItem(sessionInfo.getAppPackageName(), getUserHandle(sessionInfo)); - mPromiseIconIds.add(sessionInfo.getSessionId()); + getPromiseIconIds().add(sessionInfo.getSessionId()); updatePromiseIconPrefs(); } } - public InstallSessionTracker registerInstallTracker( - InstallSessionTracker.Callback callback, LooperExecutor executor) { + public InstallSessionTracker registerInstallTracker(InstallSessionTracker.Callback callback) { InstallSessionTracker tracker = new InstallSessionTracker(this, callback); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { - mInstaller.registerSessionCallback(tracker, executor.getHandler()); + mInstaller.registerSessionCallback(tracker, MODEL_EXECUTOR.getHandler()); } else { - mLauncherApps.registerPackageInstallerSessionCallback(executor, tracker); + mLauncherApps.registerPackageInstallerSessionCallback(MODEL_EXECUTOR, tracker); } return tracker; } @@ -240,4 +245,8 @@ public class InstallSessionHelper { mLauncherApps.unregisterPackageInstallerSessionCallback(tracker); } } + + public static UserHandle getUserHandle(SessionInfo info) { + return Utilities.ATLEAST_Q ? info.getUser() : Process.myUserHandle(); + } } diff --git a/src/com/android/launcher3/pm/InstallSessionTracker.java b/src/com/android/launcher3/pm/InstallSessionTracker.java index eb3ca7366b..b0b907ab19 100644 --- a/src/com/android/launcher3/pm/InstallSessionTracker.java +++ b/src/com/android/launcher3/pm/InstallSessionTracker.java @@ -24,8 +24,11 @@ import android.content.pm.PackageInstaller.SessionInfo; import android.os.UserHandle; import android.util.SparseArray; +import androidx.annotation.WorkerThread; + import com.android.launcher3.util.PackageUserKey; +@WorkerThread public class InstallSessionTracker extends PackageInstaller.SessionCallback { // Lazily initialized From e806f95349ce2f34250fe4de5b368e90b3112d6c Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Tue, 22 Sep 2020 11:05:20 -0700 Subject: [PATCH 11/45] Additional logs to resolve flaky work profile Bug: 159671700 Change-Id: I9bed08ef89b06f79ee1e6a4140a880eeeb76ee75 --- src/com/android/launcher3/pm/UserCache.java | 5 +++++ src/com/android/launcher3/testing/TestProtocol.java | 1 + tests/src/com/android/launcher3/ui/WorkTabTest.java | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java index 5aab41a8a2..5ade22be5e 100644 --- a/src/com/android/launcher3/pm/UserCache.java +++ b/src/com/android/launcher3/pm/UserCache.java @@ -21,8 +21,10 @@ import android.content.Intent; import android.os.UserHandle; import android.os.UserManager; import android.util.ArrayMap; +import android.util.Log; import android.util.LongSparseArray; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.SafeCloseable; import com.android.launcher3.util.SimpleBroadcastReceiver; @@ -58,6 +60,9 @@ public class UserCache { private void onUsersChanged(Intent intent) { enableAndResetCache(); mUserChangeListeners.forEach(Runnable::run); + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.WORK_PROFILE_REMOVED, "profile changed", new Exception()); + } } /** diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 7f7635561d..b2d008119e 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -106,4 +106,5 @@ public final class TestProtocol { public static final String PAUSE_NOT_DETECTED = "b/139891609"; public static final String OVERIEW_NOT_ALLAPPS = "b/156095088"; public static final String NO_SWIPE_TO_HOME = "b/158017601"; + public static final String WORK_PROFILE_REMOVED = "b/159671700"; } diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java index e51c1cad37..488e763f94 100644 --- a/tests/src/com/android/launcher3/ui/WorkTabTest.java +++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; +import android.util.Log; import android.widget.TextView; import androidx.test.filters.LargeTest; @@ -34,6 +35,7 @@ import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsPagedView; import com.android.launcher3.allapps.WorkModeSwitch; import com.android.launcher3.dragndrop.DragLayer; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.views.WorkEduView; import org.junit.After; @@ -133,6 +135,10 @@ public class WorkTabTest extends AbstractLauncherUiTest { workEduView.findViewById(R.id.proceed).callOnClick(); }); + executeOnLauncher(launcher -> Log.d(TestProtocol.WORK_PROFILE_REMOVED, + "work profile status (" + mProfileUserId + ") :" + + launcher.getAppsView().isWorkTabVisible())); + // verify work edu is seen next waitForLauncherCondition("Launcher did not show the next edu screen", l -> ((AllAppsPagedView) l.getAppsView().getContentView()).getCurrentPage() == WORK_PAGE From 649122edc0f9ea1690fc78e8707523d2cf1e3ba0 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 22 Sep 2020 23:43:51 +0000 Subject: [PATCH 12/45] Revert "Disabling testToast on virtual devices" This reverts commit f6385576d51a4bba48f5e9760a54d9fc33aa8b7f. Reason for revert: Test Change-Id: I9caec3b2d64995b31f3dbbf5cb2865f4e5941afe --- .../com/android/quickstep/DigitalWellBeingToastTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java index ccfa3fc0fb..9a053f2f62 100644 --- a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java +++ b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java @@ -3,6 +3,8 @@ package com.android.quickstep; import static androidx.test.InstrumentationRegistry.getInstrumentation; import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT; +import static com.android.launcher3.util.rule.TestStabilityRule.UNBUNDLED_POSTSUBMIT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -11,12 +13,12 @@ import static org.junit.Assert.assertTrue; import android.app.PendingIntent; import android.app.usage.UsageStatsManager; import android.content.Intent; -import android.os.Build; import androidx.test.filters.LargeTest; import androidx.test.runner.AndroidJUnit4; import com.android.launcher3.Launcher; +import com.android.launcher3.util.rule.TestStabilityRule; import com.android.quickstep.views.DigitalWellBeingToast; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; @@ -33,10 +35,9 @@ public class DigitalWellBeingToastTest extends AbstractQuickStepTest { resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR); @Test + // b/150303529 + @TestStabilityRule.Stability(flavors = UNBUNDLED_POSTSUBMIT | PLATFORM_POSTSUBMIT) public void testToast() throws Exception { - // b/150303529 - if (Build.MODEL.contains("Cuttlefish")) return; - startAppFast(CALCULATOR_PACKAGE); final UsageStatsManager usageStatsManager = From 407ff592720e5f4a0f9c26f264b24ed539f3c589 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Sun, 9 Aug 2020 22:01:28 -0700 Subject: [PATCH 13/45] [DO NOT MERGE][NPE] check RecentsView exists before using it Bug: 162176024 Change-Id: I8fe2ed42836bd6645f600b223e81526840ead557 --- .../src/com/android/quickstep/views/TaskView.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index 2058a7f375..3621658b79 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -419,7 +419,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } }, resultCallbackHandler); } - getRecentsView().onTaskLaunched(mTask); + RecentsView recentsView = getRecentsView(); + if (recentsView != null) { + recentsView.onTaskLaunched(mTask); + } } } From 9b947993be58725b65da3d7670643ac7bebd34c3 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Tue, 22 Sep 2020 14:17:03 -0700 Subject: [PATCH 14/45] [DO NOT MERGE] Encode launch location for hotseat items Bug: 162003157 Test: Manual Change-Id: I18f8f3f431dbabb3d22898d27d70c8730ad0150f --- src/com/android/launcher3/model/AppLaunchTracker.java | 1 + src/com/android/launcher3/touch/ItemClickHandler.java | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/com/android/launcher3/model/AppLaunchTracker.java b/src/com/android/launcher3/model/AppLaunchTracker.java index 629a0ee496..906c2e018b 100644 --- a/src/com/android/launcher3/model/AppLaunchTracker.java +++ b/src/com/android/launcher3/model/AppLaunchTracker.java @@ -41,6 +41,7 @@ public class AppLaunchTracker implements ResourceBasedOverride { public static final String CONTAINER_PREDICTIONS = Integer.toString(ContainerType.PREDICTION); public static final String CONTAINER_SEARCH = Integer.toString(ContainerType.SEARCHRESULT); public static final String CONTAINER_OVERVIEW = Integer.toString(ContainerType.OVERVIEW); + public static final String CONTAINER_HOTSEAT = Integer.toString(ContainerType.HOTSEAT); public static final MainThreadInitializedObject INSTANCE = diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java index 848666674d..f50b2b30de 100644 --- a/src/com/android/launcher3/touch/ItemClickHandler.java +++ b/src/com/android/launcher3/touch/ItemClickHandler.java @@ -19,6 +19,7 @@ import static com.android.launcher3.Launcher.REQUEST_BIND_PENDING_APPWIDGET; import static com.android.launcher3.Launcher.REQUEST_RECONFIGURE_APPWIDGET; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN; import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_ALL_APPS; +import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_HOTSEAT; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_BY_PUBLISHER; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_QUIET_USER; @@ -42,6 +43,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.BubbleTextView; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetProviderInfo; +import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.folder.Folder; @@ -240,6 +242,12 @@ public class ItemClickHandler { } } + if (sourceContainer == null && ( + shortcut.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT + || shortcut.container + == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION)) { + sourceContainer = CONTAINER_HOTSEAT; + } // Start activities startAppShortcutOrInfoActivity(v, shortcut, launcher, sourceContainer); } From 657f396c9c12bb8b76ae599879be535ce022795b Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 22 Sep 2020 16:36:34 -0700 Subject: [PATCH 15/45] Scale task view in TaskViewSimulator before translating it The pivot is supposed to be at the center of the task view, hence why we use width / 2, height / 2, but technically this is assuming that translation == 0. This error isn't normally noticeable because scale is 1 when the task is centered, so the pivot doesn't matter. By scaling before translating, we ensure the pivot doesn't depend on the translation. Test: scroll side to side while swiping up from an app, ensure the running window scales down properly; when you let go to enter recents while the second task is centermost, the running window ends in the exact position as the first TaskView that replaces it. Fixes: 169103357 Change-Id: Ica53c6b6fb073304c29f26d30fb829bb9d282185 --- .../src/com/android/quickstep/util/TaskViewSimulator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java index 903e87a7f8..081413e4f3 100644 --- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java @@ -297,9 +297,9 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { mMatrix.postTranslate(insets.left, insets.top); mMatrix.postScale(scale, scale); - // Apply TaskView matrix: translate, scale, scroll - mMatrix.postTranslate(mTaskRect.left, mTaskRect.top + mOffsetY); + // Apply TaskView matrix: scale, translate, scroll mMatrix.postScale(mCurveScale, mCurveScale, taskWidth / 2, taskHeight / 2); + mMatrix.postTranslate(mTaskRect.left, mTaskRect.top + mOffsetY); mOrientationState.getOrientationHandler().set( mMatrix, MATRIX_POST_TRANSLATE, mScrollState.scroll); From 99d6c2ff0d28e6079de64e0a343067755cbccbde Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Tue, 22 Sep 2020 18:28:22 -0700 Subject: [PATCH 16/45] Update hero app shortcuts with icon - set appropriate click handler for recycled app icons Bug: 168810843 Bug: 168733655 Test: Manual Change-Id: Ic644deb4ac6c7a1cb9a2c3b75f7e2ac86380a9d0 --- .../launcher3/allapps/AllAppsGridAdapter.java | 4 +++ .../launcher3/views/HeroSearchResultView.java | 29 ++++++++++++++----- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java index e08bd5ba3b..0abf84a798 100644 --- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java +++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java @@ -495,6 +495,10 @@ public class AllAppsGridAdapter extends }); withPayload.setSelectionHandler(selectionHandler); } + else { + icon.setOnClickListener(mOnIconClickListener); + icon.setOnLongClickListener(mOnIconLongClickListener); + } break; case VIEW_TYPE_EMPTY_SEARCH: TextView emptyViewText = (TextView) holder.itemView; diff --git a/src/com/android/launcher3/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java index a8e1c6b30c..845c6de824 100644 --- a/src/com/android/launcher3/views/HeroSearchResultView.java +++ b/src/com/android/launcher3/views/HeroSearchResultView.java @@ -16,12 +16,16 @@ package com.android.launcher3.views; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS; +import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; +import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.content.Context; import android.content.Intent; +import android.content.pm.ShortcutInfo; import android.graphics.Point; import android.os.Bundle; import android.util.AttributeSet; +import android.util.Pair; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; @@ -31,9 +35,10 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget; import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload; -import com.android.launcher3.allapps.search.AllAppsSearchBarController; +import com.android.launcher3.allapps.search.AllAppsSearchBarController.PayloadResultHandler; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.graphics.DragPreviewProvider; @@ -53,7 +58,7 @@ import java.util.List; * A view representing a high confidence app search result that includes shortcuts */ public class HeroSearchResultView extends LinearLayout implements DragSource, - AllAppsSearchBarController.PayloadResultHandler> { + PayloadResultHandler>> { public static final int MAX_SHORTCUTS_COUNT = 2; BubbleTextView mBubbleTextView; @@ -119,15 +124,25 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, * Apply {@link ItemInfo} for appIcon and shortcut Icons */ @Override - public void applyAdapterInfo(AdapterItemWithPayload> adapterItem) { + public void applyAdapterInfo( + AdapterItemWithPayload>> adapterItem) { mBubbleTextView.applyFromApplicationInfo(adapterItem.appInfo); mIconView.setBackground(mBubbleTextView.getIcon()); mIconView.setTag(adapterItem.appInfo); - List shorcutInfos = adapterItem.getPayload(); + List> shortcutDetails = adapterItem.getPayload(); + LauncherAppState appState = LauncherAppState.getInstance(getContext()); for (int i = 0; i < mDeepShortcutTextViews.length; i++) { - mDeepShortcutTextViews[i].setVisibility(shorcutInfos.size() > i ? VISIBLE : GONE); - if (i < shorcutInfos.size()) { - mDeepShortcutTextViews[i].applyFromItemInfoWithIcon(shorcutInfos.get(i)); + BubbleTextView shortcutView = mDeepShortcutTextViews[i]; + mDeepShortcutTextViews[i].setVisibility(shortcutDetails.size() > i ? VISIBLE : GONE); + if (i < shortcutDetails.size()) { + Pair p = shortcutDetails.get(i); + //apply ItemInfo and prepare view + shortcutView.applyFromItemInfoWithIcon(p.second); + MODEL_EXECUTOR.execute(() -> { + // load unbadged shortcut in background and update view when icon ready + appState.getIconCache().getUnbadgedShortcutIcon(p.second, p.first); + MAIN_EXECUTOR.post(() -> shortcutView.reapplyItemInfo(p.second)); + }); } } mPlugin = adapterItem.getPlugin(); From f01064953b4106b86ea18a0925dbb5f4247ce656 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Tue, 22 Sep 2020 20:52:45 -0700 Subject: [PATCH 17/45] Track search results with position and search Identifier Bug: 169087008 Test: Manual Change-Id: I54c74093b90e5aea03a7810f55fcc32f0ddf8dda --- .../launcher3/allapps/AllAppsGridAdapter.java | 47 ++++++++++++------- .../search/AllAppsSearchBarController.java | 40 ++++++++++++++++ .../launcher3/views/HeroSearchResultView.java | 12 +++-- .../views/SearchResultPeopleView.java | 20 +++++--- .../launcher3/views/SearchResultPlayItem.java | 9 +++- .../launcher3/views/SearchResultShortcut.java | 11 ++++- .../views/SearchSectionHeaderView.java | 5 ++ .../views/SearchSettingsRowView.java | 9 +++- .../views/ThumbnailSearchResultView.java | 10 +++- .../systemui/plugins/AllAppsSearchPlugin.java | 2 +- .../systemui/plugins/shared/SearchTarget.java | 4 +- .../plugins/shared/SearchTargetEvent.java | 8 +++- 12 files changed, 141 insertions(+), 36 deletions(-) diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java index 0abf84a798..f01f90be11 100644 --- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java +++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java @@ -200,6 +200,7 @@ public class AllAppsGridAdapter extends */ public static class AdapterItemWithPayload extends AdapterItem { private T mPayload; + private String mSearchSessionId; private AllAppsSearchPlugin mPlugin; private IntConsumer mSelectionHandler; @@ -221,6 +222,14 @@ public class AllAppsGridAdapter extends mSelectionHandler = runnable; } + public void setSearchSessionId(String searchSessionId) { + mSearchSessionId = searchSessionId; + } + + public String getSearchSessionId() { + return mSearchSessionId; + } + public IntConsumer getSelectionHandler() { return mSelectionHandler; } @@ -228,6 +237,8 @@ public class AllAppsGridAdapter extends public T getPayload() { return mPayload; } + + } /** @@ -476,24 +487,23 @@ public class AllAppsGridAdapter extends //TODO: replace with custom TopHitBubbleTextView with support for both shortcut // and apps if (adapterItem instanceof AdapterItemWithPayload) { - AdapterItemWithPayload withPayload = (AdapterItemWithPayload) adapterItem; - IntConsumer selectionHandler = type -> { + AdapterItemWithPayload item = (AdapterItemWithPayload) adapterItem; + item.setSelectionHandler(type -> { SearchTargetEvent e = new SearchTargetEvent(SearchTarget.ItemType.APP, - type); + type, item.position, item.getSearchSessionId()); e.bundle = HeroSearchResultView.getAppBundle(info); - if (withPayload.getPlugin() != null) { - withPayload.getPlugin().notifySearchTargetEvent(e); + if (item.getPlugin() != null) { + item.getPlugin().notifySearchTargetEvent(e); } - }; + }); icon.setOnClickListener(view -> { - selectionHandler.accept(SearchTargetEvent.SELECT); + item.getSelectionHandler().accept(SearchTargetEvent.SELECT); mOnIconClickListener.onClick(view); }); icon.setOnLongClickListener(view -> { - selectionHandler.accept(SearchTargetEvent.LONG_PRESS); + item.getSelectionHandler().accept(SearchTargetEvent.SELECT); return mOnIconLongClickListener.onLongClick(view); }); - withPayload.setSelectionHandler(selectionHandler); } else { icon.setOnClickListener(mOnIconClickListener); @@ -516,20 +526,22 @@ public class AllAppsGridAdapter extends break; case VIEW_TYPE_SEARCH_SLICE: SliceView sliceView = (SliceView) holder.itemView; - AdapterItemWithPayload item = + AdapterItemWithPayload slicePayload = (AdapterItemWithPayload) mApps.getAdapterItems().get(position); sliceView.setOnSliceActionListener((info1, s) -> { - if (item.getPlugin() != null) { + if (slicePayload.getPlugin() != null) { SearchTargetEvent searchTargetEvent = new SearchTargetEvent( SearchTarget.ItemType.SETTINGS_SLICE, - SearchTargetEvent.CHILD_SELECT); + SearchTargetEvent.CHILD_SELECT, slicePayload.position, + slicePayload.getSearchSessionId()); searchTargetEvent.bundle = new Bundle(); - searchTargetEvent.bundle.putParcelable("uri", item.getPayload()); - item.getPlugin().notifySearchTargetEvent(searchTargetEvent); + searchTargetEvent.bundle.putParcelable("uri", slicePayload.getPayload()); + slicePayload.getPlugin().notifySearchTargetEvent(searchTargetEvent); } }); try { - LiveData liveData = SliceLiveData.fromUri(mLauncher, item.getPayload()); + LiveData liveData = SliceLiveData.fromUri(mLauncher, + slicePayload.getPayload()); liveData.observe((Launcher) mLauncher, sliceView); sliceView.setTag(liveData); } catch (Exception ignored) { @@ -542,9 +554,10 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_SHORTCUT: case VIEW_TYPE_SEARCH_PEOPLE: case VIEW_TYPE_SEARCH_THUMBNAIL: + AdapterItemWithPayload item = + (AdapterItemWithPayload) mApps.getAdapterItems().get(position); PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView; - payloadResultView.applyAdapterInfo( - (AdapterItemWithPayload) mApps.getAdapterItems().get(position)); + payloadResultView.setup(item); break; case VIEW_TYPE_ALL_APPS_DIVIDER: // nothing to do diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java index 3320189a1d..d7fa5bc479 100644 --- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java +++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java @@ -35,6 +35,8 @@ import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.PackageManagerHelper; import com.android.systemui.plugins.AllAppsSearchPlugin; +import com.android.systemui.plugins.shared.SearchTarget; +import com.android.systemui.plugins.shared.SearchTargetEvent; import java.util.ArrayList; import java.util.List; @@ -213,6 +215,44 @@ public class AllAppsSearchBarController /** * Updates View using Adapter's payload */ + + default void setup(AdapterItemWithPayload adapterItemWithPayload) { + Object[] targetInfo = getTargetInfo(); + if (targetInfo != null) { + targetInfo[0] = adapterItemWithPayload.getSearchSessionId(); + targetInfo[1] = adapterItemWithPayload.position; + } + applyAdapterInfo(adapterItemWithPayload); + } + void applyAdapterInfo(AdapterItemWithPayload adapterItemWithPayload); + + /** + * Gets object created by {@link PayloadResultHandler#createTargetInfo()} + */ + Object[] getTargetInfo(); + + /** + * Creates a wrapper object to hold searchSessionId and item position + */ + default Object[] createTargetInfo() { + return new Object[2]; + } + + /** + * Generates a SearchTargetEvent object for a PayloadHandlerView + */ + default SearchTargetEvent getSearchTargetEvent(SearchTarget.ItemType itemType, + int eventType) { + Object[] targetInfo = getTargetInfo(); + if (targetInfo == null) return null; + + String searchSessionId = (String) targetInfo[0]; + int position = (int) targetInfo[1]; + return new SearchTargetEvent(itemType, eventType, + position, searchSessionId); + } } + + } \ No newline at end of file diff --git a/src/com/android/launcher3/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java index 845c6de824..94b9ca1484 100644 --- a/src/com/android/launcher3/views/HeroSearchResultView.java +++ b/src/com/android/launcher3/views/HeroSearchResultView.java @@ -61,6 +61,7 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, PayloadResultHandler>> { public static final int MAX_SHORTCUTS_COUNT = 2; + private final Object[] mTargetInfo = createTargetInfo(); BubbleTextView mBubbleTextView; View mIconView; BubbleTextView[] mDeepShortcutTextViews = new BubbleTextView[2]; @@ -107,7 +108,7 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, grid.allAppsIconSizePx)); bubbleTextView.setOnClickListener(view -> { WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) bubbleTextView.getTag(); - SearchTargetEvent event = new SearchTargetEvent( + SearchTargetEvent event = getSearchTargetEvent( SearchTarget.ItemType.APP_HERO, SearchTargetEvent.CHILD_SELECT); event.bundle = getAppBundle(itemInfo); @@ -149,6 +150,11 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, adapterItem.setSelectionHandler(this::handleSelection); } + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + @Override public void onDropCompleted(View target, DropTarget.DragObject d, boolean success) { mBubbleTextView.setVisibility(VISIBLE); @@ -184,7 +190,7 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, mLauncher.getWorkspace().beginDragShared(mContainer.mBubbleTextView, draggableView, mContainer, itemInfo, previewProvider, new DragOptions()); - SearchTargetEvent event = new SearchTargetEvent( + SearchTargetEvent event = mContainer.getSearchTargetEvent( SearchTarget.ItemType.APP_HERO, SearchTargetEvent.LONG_PRESS); event.bundle = getAppBundle(itemInfo); if (mContainer.mPlugin != null) { @@ -201,7 +207,7 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, Launcher launcher = Launcher.getLauncher(getContext()); launcher.startActivitySafely(this, itemInfo.getIntent(), itemInfo); - SearchTargetEvent event = new SearchTargetEvent( + SearchTargetEvent event = getSearchTargetEvent( SearchTarget.ItemType.APP_HERO, eventType); event.bundle = getAppBundle(itemInfo); if (mPlugin != null) { diff --git a/src/com/android/launcher3/views/SearchResultPeopleView.java b/src/com/android/launcher3/views/SearchResultPeopleView.java index 6e45e88b32..eacc095188 100644 --- a/src/com/android/launcher3/views/SearchResultPeopleView.java +++ b/src/com/android/launcher3/views/SearchResultPeopleView.java @@ -67,7 +67,7 @@ public class SearchResultPeopleView extends LinearLayout implements private ImageButton[] mProviderButtons = new ImageButton[3]; private AllAppsSearchPlugin mPlugin; private Uri mContactUri; - + private final Object[] mTargetInfo = createTargetInfo(); public SearchResultPeopleView(Context context) { this(context, null, 0); @@ -129,14 +129,14 @@ public class SearchResultPeopleView extends LinearLayout implements Bundle provider = providers.get(i); Intent intent = Intent.parseUri(provider.getString("intent_uri_str"), URI_ANDROID_APP_SCHEME | URI_ALLOW_UNSAFE); - setupProviderButton(button, provider, intent); + setupProviderButton(button, provider, intent, adapterItemWithPayload); String pkg = provider.getString("package_name"); UI_HELPER_EXECUTOR.post(() -> { try { ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo( pkg, 0); Drawable appIcon = applicationInfo.loadIcon(mPackageManager); - MAIN_EXECUTOR.post(()-> button.setImageDrawable(appIcon)); + MAIN_EXECUTOR.post(() -> button.setImageDrawable(appIcon)); } catch (PackageManager.NameNotFoundException ignored) { } @@ -151,11 +151,17 @@ public class SearchResultPeopleView extends LinearLayout implements adapterItemWithPayload.setSelectionHandler(this::handleSelection); } - private void setupProviderButton(ImageButton button, Bundle provider, Intent intent) { + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + + private void setupProviderButton(ImageButton button, Bundle provider, Intent intent, + AllAppsGridAdapter.AdapterItem adapterItem) { Launcher launcher = Launcher.getLauncher(getContext()); button.setOnClickListener(b -> { launcher.startActivitySafely(b, intent, null); - SearchTargetEvent searchTargetEvent = new SearchTargetEvent( + SearchTargetEvent searchTargetEvent = getSearchTargetEvent( SearchTarget.ItemType.PEOPLE, SearchTargetEvent.CHILD_SELECT); searchTargetEvent.bundle = new Bundle(); @@ -173,8 +179,8 @@ public class SearchResultPeopleView extends LinearLayout implements Launcher launcher = Launcher.getLauncher(getContext()); launcher.startActivitySafely(this, new Intent(Intent.ACTION_VIEW, mContactUri).setFlags( Intent.FLAG_ACTIVITY_NEW_TASK), null); - SearchTargetEvent searchTargetEvent = new SearchTargetEvent( - SearchTarget.ItemType.PEOPLE, eventType); + SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.PEOPLE, + eventType); searchTargetEvent.bundle = new Bundle(); searchTargetEvent.bundle.putParcelable("contact_uri", mContactUri); if (mPlugin != null) { diff --git a/src/com/android/launcher3/views/SearchResultPlayItem.java b/src/com/android/launcher3/views/SearchResultPlayItem.java index 8624609f80..ff3ecc8bc3 100644 --- a/src/com/android/launcher3/views/SearchResultPlayItem.java +++ b/src/com/android/launcher3/views/SearchResultPlayItem.java @@ -58,6 +58,8 @@ public class SearchResultPlayItem extends LinearLayout implements private String mPackageName; private boolean mIsInstantGame; private AllAppsSearchPlugin mPlugin; + private final Object[] mTargetInfo = createTargetInfo(); + public SearchResultPlayItem(Context context) { this(context, null, 0); @@ -125,6 +127,11 @@ public class SearchResultPlayItem extends LinearLayout implements }); } + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + private void showIfNecessary(TextView textView, @Nullable String string) { if (string == null || string.isEmpty()) { textView.setVisibility(GONE); @@ -160,7 +167,7 @@ public class SearchResultPlayItem extends LinearLayout implements } private void logSearchEvent(int eventType) { - SearchTargetEvent searchTargetEvent = new SearchTargetEvent( + SearchTargetEvent searchTargetEvent = getSearchTargetEvent( SearchTarget.ItemType.PLAY_RESULTS, eventType); searchTargetEvent.bundle = new Bundle(); searchTargetEvent.bundle.putString("package_name", mPackageName); diff --git a/src/com/android/launcher3/views/SearchResultShortcut.java b/src/com/android/launcher3/views/SearchResultShortcut.java index 307cf34c7d..a409f0807f 100644 --- a/src/com/android/launcher3/views/SearchResultShortcut.java +++ b/src/com/android/launcher3/views/SearchResultShortcut.java @@ -50,6 +50,8 @@ public class SearchResultShortcut extends FrameLayout implements private View mIconView; private ShortcutInfo mShortcutInfo; private AllAppsSearchPlugin mPlugin; + private final Object[] mTargetInfo = createTargetInfo(); + public SearchResultShortcut(@NonNull Context context) { super(context); @@ -96,12 +98,17 @@ public class SearchResultShortcut extends FrameLayout implements adapterItemWithPayload.setSelectionHandler(this::handleSelection); } + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + private void handleSelection(int eventType) { WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) mBubbleTextView.getTag(); ItemClickHandler.onClickAppShortcut(this, itemInfo, Launcher.getLauncher(getContext())); - SearchTargetEvent searchTargetEvent = new SearchTargetEvent( - SearchTarget.ItemType.SHORTCUT, eventType); + SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.SHORTCUT, + eventType); searchTargetEvent.shortcut = mShortcutInfo; if (mPlugin != null) { mPlugin.notifySearchTargetEvent(searchTargetEvent); diff --git a/src/com/android/launcher3/views/SearchSectionHeaderView.java b/src/com/android/launcher3/views/SearchSectionHeaderView.java index d439ee3d68..0fe0a43ff5 100644 --- a/src/com/android/launcher3/views/SearchSectionHeaderView.java +++ b/src/com/android/launcher3/views/SearchSectionHeaderView.java @@ -52,4 +52,9 @@ public class SearchSectionHeaderView extends TextView implements setVisibility(INVISIBLE); } } + + @Override + public Object[] getTargetInfo() { + return null; + } } diff --git a/src/com/android/launcher3/views/SearchSettingsRowView.java b/src/com/android/launcher3/views/SearchSettingsRowView.java index 93bcee2585..a1a0172547 100644 --- a/src/com/android/launcher3/views/SearchSettingsRowView.java +++ b/src/com/android/launcher3/views/SearchSettingsRowView.java @@ -48,6 +48,8 @@ public class SearchSettingsRowView extends LinearLayout implements private TextView mBreadcrumbsView; private Intent mIntent; private AllAppsSearchPlugin mPlugin; + private final Object[] mTargetInfo = createTargetInfo(); + public SearchSettingsRowView(@NonNull Context context) { super(context); @@ -87,6 +89,11 @@ public class SearchSettingsRowView extends LinearLayout implements adapterItemWithPayload.setSelectionHandler(this::handleSelection); } + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + private void showIfAvailable(TextView view, @Nullable String string) { if (TextUtils.isEmpty(string)) { view.setVisibility(GONE); @@ -108,7 +115,7 @@ public class SearchSettingsRowView extends LinearLayout implements Launcher launcher = Launcher.getLauncher(getContext()); launcher.startActivityForResult(mIntent, 0); - SearchTargetEvent searchTargetEvent = new SearchTargetEvent( + SearchTargetEvent searchTargetEvent = getSearchTargetEvent( SearchTarget.ItemType.SETTINGS_ROW, eventType); searchTargetEvent.bundle = new Bundle(); searchTargetEvent.bundle.putParcelable("intent", mIntent); diff --git a/src/com/android/launcher3/views/ThumbnailSearchResultView.java b/src/com/android/launcher3/views/ThumbnailSearchResultView.java index decc861565..1d58a063b9 100644 --- a/src/com/android/launcher3/views/ThumbnailSearchResultView.java +++ b/src/com/android/launcher3/views/ThumbnailSearchResultView.java @@ -39,8 +39,10 @@ import com.android.systemui.plugins.shared.SearchTargetEvent; public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView implements AllAppsSearchBarController.PayloadResultHandler { + private final Object[] mTargetInfo = createTargetInfo(); Intent mIntent; AllAppsSearchPlugin mPlugin; + int mPosition; public ThumbnailSearchResultView(Context context) { super(context); @@ -58,7 +60,7 @@ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppComp Launcher launcher = Launcher.getLauncher(getContext()); launcher.startActivitySafely(this, mIntent, null); - SearchTargetEvent event = new SearchTargetEvent( + SearchTargetEvent event = getSearchTargetEvent( SearchTarget.ItemType.SCREENSHOT, eventType); if (mPlugin != null) { mPlugin.notifySearchTargetEvent(event); @@ -67,6 +69,7 @@ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppComp @Override public void applyAdapterInfo(AdapterItemWithPayload adapterItem) { + mPosition = adapterItem.position; RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(null, (Bitmap) adapterItem.getPayload().getParcelable("bitmap")); drawable.setCornerRadius(Themes.getDialogCornerRadius(getContext())); @@ -78,4 +81,9 @@ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppComp mPlugin = adapterItem.getPlugin(); adapterItem.setSelectionHandler(this::handleSelection); } + + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } } diff --git a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java index 48369a4890..aa3ab8f7e0 100644 --- a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java +++ b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java @@ -32,7 +32,7 @@ import java.util.function.Consumer; @ProvidesInterface(action = AllAppsSearchPlugin.ACTION, version = AllAppsSearchPlugin.VERSION) public interface AllAppsSearchPlugin extends Plugin { String ACTION = "com.android.systemui.action.PLUGIN_ALL_APPS_SEARCH_ACTIONS"; - int VERSION = 6; + int VERSION = 7; void setup(Activity activity, View view); diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java index 9144976f98..fb8dd723bc 100644 --- a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java +++ b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java @@ -122,6 +122,7 @@ public class SearchTarget implements Comparable { public List shortcuts; public Bundle bundle; public float score; + public String mSessionId; /** * Constructor to create the search target. Bundle is currently temporary to hold @@ -130,11 +131,12 @@ public class SearchTarget implements Comparable { * */ public SearchTarget(ItemType itemType, List shortcuts, - Bundle bundle, float score) { + Bundle bundle, float score, String sessionId) { this.type = itemType; this.shortcuts = shortcuts; this.bundle = bundle; this.score = score; + this.mSessionId = sessionId; } @Override diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java index ac4bc333c6..00a78de9af 100644 --- a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java +++ b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java @@ -31,10 +31,14 @@ public class SearchTargetEvent { public ShortcutInfo shortcut; public int eventType; public Bundle bundle; - public float score; + public int index; + public String sessionIdentifier; - public SearchTargetEvent(SearchTarget.ItemType itemType, int eventType) { + public SearchTargetEvent(SearchTarget.ItemType itemType, int eventType, int index, + String sessionId) { this.type = itemType; this.eventType = eventType; + this.index = index; + this.sessionIdentifier = sessionId; } } From bf6e8ffbf030b6d419b808c28335bf8a8724e9bc Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Wed, 23 Sep 2020 12:15:43 -0700 Subject: [PATCH 18/45] Remove widgets that no longer fit the workspace in their current spans. This can happen when display size changes. We compare span sizes of widget in the db to the min sizes of the widget in the current display size. If the widget can no longer fit in its existing spans, we remove it. Bug: 168818961 Change-Id: I6b095d2eeaeda95bfa91baec89cb54660695b60b --- src/com/android/launcher3/model/LoaderTask.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 2b4520b613..c0d5882b46 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -49,6 +49,7 @@ import android.util.LongSparseArray; import android.util.TimingLogger; import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherSettings; import com.android.launcher3.Utilities; @@ -306,6 +307,7 @@ public class LoaderTask implements Runnable { final PackageManagerHelper pmHelper = new PackageManagerHelper(context); final boolean isSafeMode = pmHelper.isSafeMode(); final boolean isSdCardReady = Utilities.isBootCompleted(); + final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context); boolean clearDb = false; try { @@ -391,6 +393,7 @@ public class LoaderTask implements Runnable { WorkspaceItemInfo info; LauncherAppWidgetInfo appWidgetInfo; + LauncherAppWidgetProviderInfo widgetProviderInfo; Intent intent; String targetPkg; @@ -720,6 +723,19 @@ public class LoaderTask implements Runnable { + appWidgetInfo.spanX + "x" + appWidgetInfo.spanY); continue; } + widgetProviderInfo = + widgetHelper.getLauncherAppWidgetInfo(appWidgetId); + if (widgetProviderInfo != null + && (appWidgetInfo.spanX < widgetProviderInfo.minSpanX + || appWidgetInfo.spanY < widgetProviderInfo.minSpanY)) { + // This can happen when display size changes. + c.markDeleted("Widget removed, min sizes not met: " + + "span=" + appWidgetInfo.spanX + "x" + + appWidgetInfo.spanY + " minSpan=" + + widgetProviderInfo.minSpanX + "x" + + widgetProviderInfo.minSpanY); + continue; + } if (!c.isOnWorkspaceOrHotseat()) { c.markDeleted("Widget found where container != " + "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!"); From 350b462f24ff1fc95cad23044fbd2194fe03ea05 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Fri, 18 Sep 2020 11:16:30 -0700 Subject: [PATCH 19/45] Animate icon update from loading state. Test: manual Fixing b/129983531. Having app icons pop in without any animation from a solid placeholder color can look janky. Added a sequential fade in, fade out animation. Preview: https://drive.google.com/file/d/11NgEja7vzm3f3aH3WbEQljUWGKuuK00_/view?usp=sharing Change-Id: If77e8f480b02d5b7d29f89afa44450c83a68a276 --- src/com/android/launcher3/BubbleTextView.java | 48 +++++++++++++++++-- .../android/launcher3/FastBitmapDrawable.java | 9 +++- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 06bb263f23..fd04081198 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -23,6 +23,7 @@ import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; @@ -30,6 +31,8 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; +import android.graphics.PorterDuff.Mode; +import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -43,6 +46,8 @@ import android.view.View; import android.view.ViewDebug; import android.widget.TextView; +import androidx.core.graphics.ColorUtils; + import com.android.launcher3.Launcher.OnResumeCallback; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.dot.DotInfo; @@ -50,6 +55,7 @@ import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.graphics.IconPalette; import com.android.launcher3.graphics.IconShape; +import com.android.launcher3.graphics.PlaceHolderIconDrawable; import com.android.launcher3.graphics.PreloadIconDrawable; import com.android.launcher3.icons.DotRenderer; import com.android.launcher3.icons.IconCache.IconLoadRequest; @@ -84,6 +90,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, private final PointF mTranslationForReorderBounce = new PointF(0, 0); private final PointF mTranslationForReorderPreview = new PointF(0, 0); + private static final int ICON_UPDATE_ANIMATION_DURATION = 375; + private float mScaleForReorderBounce = 1f; private static final Property DOT_SCALE_PROPERTY @@ -636,11 +644,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, mDisableRelayout = mIcon != null; icon.setBounds(0, 0, mIconSize, mIconSize); - if (mLayoutHorizontal) { - setCompoundDrawablesRelative(icon, null, null, null); - } else { - setCompoundDrawables(null, icon, null, null); + + updateIcon(icon); + + // If the current icon is a placeholder color, animate its update. + if (mIcon != null && mIcon instanceof PlaceHolderIconDrawable) { + animateIconUpdate((PlaceHolderIconDrawable) mIcon, icon); } + mDisableRelayout = false; } @@ -776,4 +787,33 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, ((FastBitmapDrawable) mIcon).setScale(1f); } } + + private void updateIcon(Drawable newIcon) { + if (mLayoutHorizontal) { + setCompoundDrawablesRelative(newIcon, null, null, null); + } else { + setCompoundDrawables(null, newIcon, null, null); + } + } + + private static void animateIconUpdate(PlaceHolderIconDrawable oldIcon, Drawable newIcon) { + int placeholderColor = oldIcon.mPaint.getColor(); + int originalAlpha = Color.alpha(placeholderColor); + + ValueAnimator iconUpdateAnimation = ValueAnimator.ofInt(originalAlpha, 0); + iconUpdateAnimation.setDuration(ICON_UPDATE_ANIMATION_DURATION); + iconUpdateAnimation.addUpdateListener(valueAnimator -> { + int newAlpha = (int) valueAnimator.getAnimatedValue(); + int newColor = ColorUtils.setAlphaComponent(placeholderColor, newAlpha); + + newIcon.setColorFilter(new PorterDuffColorFilter(newColor, Mode.SRC_ATOP)); + }); + iconUpdateAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + newIcon.setColorFilter(null); + } + }); + iconUpdateAnimation.start(); + } } diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java index d3b86ded80..139d4a85e4 100644 --- a/src/com/android/launcher3/FastBitmapDrawable.java +++ b/src/com/android/launcher3/FastBitmapDrawable.java @@ -33,6 +33,8 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.Property; +import androidx.annotation.Nullable; + import com.android.launcher3.graphics.PlaceHolderIconDrawable; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; @@ -54,6 +56,8 @@ public class FastBitmapDrawable extends Drawable { protected Bitmap mBitmap; protected final int mIconColor; + @Nullable private ColorFilter mColorFilter; + private boolean mIsPressed; private boolean mIsDisabled; private float mDisabledAlpha = 1f; @@ -115,7 +119,8 @@ public class FastBitmapDrawable extends Drawable { @Override public void setColorFilter(ColorFilter cf) { - // No op + mColorFilter = cf; + updateFilter(); } @Override @@ -265,7 +270,7 @@ public class FastBitmapDrawable extends Drawable { * Updates the paint to reflect the current brightness and saturation. */ protected void updateFilter() { - mPaint.setColorFilter(mIsDisabled ? getDisabledColorFilter() : null); + mPaint.setColorFilter(mIsDisabled ? getDisabledColorFilter() : mColorFilter); invalidateSelf(); } From 30cd4dca5fae4d5b1b9d87191bb6d22b2f4ffdc1 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 23 Sep 2020 15:33:32 -0700 Subject: [PATCH 20/45] Remove test restrictions Bug: 150303529 Change-Id: I1cfbd2bfb26fc47ee0bfb54dd174cd59ae0bfc5e --- .../src/com/android/quickstep/DigitalWellBeingToastTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java index 9a053f2f62..2a7da7eca8 100644 --- a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java +++ b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java @@ -35,8 +35,6 @@ public class DigitalWellBeingToastTest extends AbstractQuickStepTest { resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR); @Test - // b/150303529 - @TestStabilityRule.Stability(flavors = UNBUNDLED_POSTSUBMIT | PLATFORM_POSTSUBMIT) public void testToast() throws Exception { startAppFast(CALCULATOR_PACKAGE); From ceb1724376a1f7c647ced9750afa494fdfa37e8f Mon Sep 17 00:00:00 2001 From: Sreyas Date: Wed, 23 Sep 2020 16:12:21 -0700 Subject: [PATCH 21/45] Removing OAV HIDDEN_GESTURE_RUNNING flag. Overview was being hidden when gesture was running, this is unnecessary as other hidden flags cover all the use cases. Bug: 168565347 Change-Id: Ieab36783fccc0088f9cdbe0768a93c5c46b23def --- .../src/com/android/quickstep/views/OverviewActionsView.java | 4 +--- quickstep/src/com/android/quickstep/views/RecentsView.java | 3 --- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java index 2a6c9e92db..b8e07cb189 100644 --- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java @@ -54,7 +54,6 @@ public class OverviewActionsView extends FrameLayo HIDDEN_UNSUPPORTED_NAVIGATION, HIDDEN_NON_ZERO_ROTATION, HIDDEN_NO_TASKS, - HIDDEN_GESTURE_RUNNING, HIDDEN_NO_RECENTS}) @Retention(RetentionPolicy.SOURCE) public @interface ActionsHiddenFlags { } @@ -62,8 +61,7 @@ public class OverviewActionsView extends FrameLayo public static final int HIDDEN_UNSUPPORTED_NAVIGATION = 1 << 0; public static final int HIDDEN_NON_ZERO_ROTATION = 1 << 1; public static final int HIDDEN_NO_TASKS = 1 << 2; - public static final int HIDDEN_GESTURE_RUNNING = 1 << 3; - public static final int HIDDEN_NO_RECENTS = 1 << 4; + public static final int HIDDEN_NO_RECENTS = 1 << 3; @IntDef(flag = true, value = { DISABLED_SCROLLING, diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 0362377399..1ae011b2c0 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -44,7 +44,6 @@ import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType. import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW; import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId; -import static com.android.quickstep.views.OverviewActionsView.HIDDEN_GESTURE_RUNNING; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS; @@ -1129,7 +1128,6 @@ public abstract class RecentsView extends PagedView setEnableDrawingLiveTile(false); setRunningTaskHidden(true); setRunningTaskIconScaledDown(true); - mActionsView.updateHiddenFlags(HIDDEN_GESTURE_RUNNING, true); } /** @@ -1322,7 +1320,6 @@ public abstract class RecentsView extends PagedView } private void animateActionsViewIn() { - mActionsView.updateHiddenFlags(HIDDEN_GESTURE_RUNNING, false); ObjectAnimator anim = ObjectAnimator.ofFloat( mActionsView.getVisibilityAlpha(), MultiValueAlpha.VALUE, 0, 1); anim.setDuration(TaskView.SCALE_ICON_DURATION); From 69f9cae8106acce1095c6da2b5d8f565d1f989e9 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 23 Sep 2020 17:24:17 -0700 Subject: [PATCH 22/45] Remove CurveProperties#pageParentScale Test: Set TaskView#EDGE_SCALE_DOWN_FACTOR = 0.2f, then swipe down on the centermost TaskView; ensure it fills the screen. Alternatively, touch and hold the nav bar and ensure there is no jump in scale on the app window. Fixes: 169259407 Change-Id: Ib3cfba6ebafbcb90de9c6b1ab79f53605d995321 --- .../src/com/android/quickstep/util/TaskViewSimulator.java | 1 - quickstep/src/com/android/quickstep/views/RecentsView.java | 5 ++--- .../android/launcher3/touch/LandscapePagedViewHandler.java | 1 - src/com/android/launcher3/touch/PagedOrientationHandler.java | 1 - .../android/launcher3/touch/PortraitPagedViewHandler.java | 1 - 5 files changed, 2 insertions(+), 7 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java index 081413e4f3..3a54bd61aa 100644 --- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java @@ -278,7 +278,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { int start = mOrientationState.getOrientationHandler() .getPrimaryValue(mTaskRect.left, mTaskRect.top); mScrollState.screenCenter = start + mScrollState.scroll + mScrollState.halfPageSize; - mScrollState.pageParentScale = recentsViewScale.value; mScrollState.updateInterpolation(start); mCurveScale = TaskView.getCurveScaleForInterpolation(mScrollState.linearInterpolation); } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index b617817728..d319a98f9a 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -1415,13 +1415,12 @@ public abstract class RecentsView extends PagedView * Updates linearInterpolation for the provided child position */ public void updateInterpolation(float childStart) { - float scaledHalfPageSize = halfPageSize / pageParentScale; - float pageCenter = childStart + scaledHalfPageSize; + float pageCenter = childStart + halfPageSize; float distanceFromScreenCenter = screenCenter - pageCenter; // How far the page has to move from the center to be offscreen, taking into account // the EDGE_SCALE_DOWN_FACTOR that will be applied at that position. float distanceToReachEdge = halfScreenSize - + scaledHalfPageSize * (1 - TaskView.EDGE_SCALE_DOWN_FACTOR); + + halfPageSize * (1 - TaskView.EDGE_SCALE_DOWN_FACTOR); linearInterpolation = Math.min(1, Math.abs(distanceFromScreenCenter) / distanceToReachEdge); } diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index fb02f79c49..17f02be5b4 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -72,7 +72,6 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { out.halfPageSize = view.getNormalChildHeight() / 2; out.halfScreenSize = view.getMeasuredHeight() / 2; out.screenCenter = insets.top + view.getPaddingTop() + out.scroll + out.halfPageSize; - out.pageParentScale = view.getScaleY(); } @Override diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index 354d78d0ac..114b75acec 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -112,7 +112,6 @@ public interface PagedOrientationHandler { public int halfPageSize; public int screenCenter; public int halfScreenSize; - public float pageParentScale; } class ChildBounds { diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index 06479e6b6a..5f5b2d1feb 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -70,7 +70,6 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { out.halfPageSize = view.getNormalChildWidth() / 2; out.halfScreenSize = view.getMeasuredWidth() / 2; out.screenCenter = insets.left + view.getPaddingLeft() + out.scroll + out.halfPageSize; - out.pageParentScale = view.getScaleX(); } @Override From a7ddfc0722ee75fe88b022a3537f2b0f51f13543 Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Wed, 23 Sep 2020 19:40:14 -0700 Subject: [PATCH 23/45] [Live tile] Use OverviewInputConsumer in live tile mode Fixes: 169285206 Test: fling the home handle in Overview to go home Change-Id: I41eae8a5120857b653a8b261a03cd5f83f99e6bb --- .../src/com/android/quickstep/TouchInteractionService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index ebdc867190..4b5adcb6c6 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -20,6 +20,7 @@ import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_UP; +import static com.android.launcher3.config.FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.quickstep.GestureState.DEFAULT_STATE; @@ -704,8 +705,10 @@ public class TouchInteractionService extends Service implements PluginListener Date: Thu, 24 Sep 2020 10:16:44 -0700 Subject: [PATCH 24/45] Remove CurveProperties#pageParentScale Test: Set TaskView#EDGE_SCALE_DOWN_FACTOR = 0.2f, then swipe down on the centermost TaskView; ensure it fills the screen. Alternatively, touch and hold the nav bar and ensure there is no jump in scale on the app window. Fixes: 169259407 Change-Id: Ib3cfba6ebafbcb90de9c6b1ab79f53605d995321 Merged-In: Ib3cfba6ebafbcb90de9c6b1ab79f53605d995321 --- .../src/com/android/quickstep/util/TaskViewSimulator.java | 1 - .../src/com/android/quickstep/views/RecentsView.java | 5 ++--- .../android/launcher3/touch/LandscapePagedViewHandler.java | 1 - src/com/android/launcher3/touch/PagedOrientationHandler.java | 1 - .../android/launcher3/touch/PortraitPagedViewHandler.java | 1 - 5 files changed, 2 insertions(+), 7 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java index db64464a61..c0601456fc 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java @@ -250,7 +250,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { int start = mOrientationState.getOrientationHandler() .getPrimaryValue(mTaskRect.left, mTaskRect.top); mScrollState.screenCenter = start + mScrollState.scroll + mScrollState.halfPageSize; - mScrollState.pageParentScale = recentsViewScale.value; mScrollState.updateInterpolation(start); mCurveScale = TaskView.getCurveScaleForInterpolation(mScrollState.linearInterpolation); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 1d17f5af70..e86a946e59 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -1390,13 +1390,12 @@ public abstract class RecentsView extends PagedView * Updates linearInterpolation for the provided child position */ public void updateInterpolation(float childStart) { - float scaledHalfPageSize = halfPageSize / pageParentScale; - float pageCenter = childStart + scaledHalfPageSize; + float pageCenter = childStart + halfPageSize; float distanceFromScreenCenter = screenCenter - pageCenter; // How far the page has to move from the center to be offscreen, taking into account // the EDGE_SCALE_DOWN_FACTOR that will be applied at that position. float distanceToReachEdge = halfScreenSize - + scaledHalfPageSize * (1 - TaskView.EDGE_SCALE_DOWN_FACTOR); + + halfPageSize * (1 - TaskView.EDGE_SCALE_DOWN_FACTOR); linearInterpolation = Math.min(1, Math.abs(distanceFromScreenCenter) / distanceToReachEdge); } diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index 4fd163360b..e64d2bb0f9 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -72,7 +72,6 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { out.halfPageSize = view.getNormalChildHeight() / 2; out.halfScreenSize = view.getMeasuredHeight() / 2; out.screenCenter = insets.top + view.getPaddingTop() + out.scroll + out.halfPageSize; - out.pageParentScale = view.getScaleY(); } @Override diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index c0d488bb45..e4a24072f0 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -111,7 +111,6 @@ public interface PagedOrientationHandler { public int halfPageSize; public int screenCenter; public int halfScreenSize; - public float pageParentScale; } class ChildBounds { diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index 9e53e5f8ec..e4662de3b3 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -70,7 +70,6 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { out.halfPageSize = view.getNormalChildWidth() / 2; out.halfScreenSize = view.getMeasuredWidth() / 2; out.screenCenter = insets.left + view.getPaddingLeft() + out.scroll + out.halfPageSize; - out.pageParentScale = view.getScaleX(); } @Override From 47644d209c97b77d3b36ea2270a64882dbe821d4 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Thu, 24 Sep 2020 12:13:08 -0700 Subject: [PATCH 25/45] Make overview to home translate faster Fixes: 169052350 Change-Id: Ia6f21f479498927a5561819fcc256b698acbd095 Merged-In: Ia6f21f479498927a5561819fcc256b698acbd095 --- .../src/com/android/quickstep/util/OverviewToHomeAnim.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java index 4a298d3bad..1031c5b080 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java @@ -18,8 +18,10 @@ package com.android.quickstep.util; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.DEACCEL; +import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.FINAL_FRAME; import static com.android.launcher3.anim.Interpolators.INSTANT; +import static com.android.launcher3.anim.Interpolators.clampToProgress; import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; @@ -110,7 +112,7 @@ public class OverviewToHomeAnim { boolean isLayoutNaturalToLauncher = recentsView.getPagedOrientationHandler() .isLayoutNaturalToLauncher(); config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, isLayoutNaturalToLauncher - ? DEACCEL : FINAL_FRAME); + ? clampToProgress(FAST_OUT_SLOW_IN, 0, 0.75f) : FINAL_FRAME); config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME); config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME); config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, INSTANT); From 02be2a43f5f2ba545c784ae671a20f7547a6539a Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Wed, 23 Sep 2020 00:45:27 -0700 Subject: [PATCH 26/45] Support Remote actions Bug: 168846477 Test: Manual Change-Id: I7b9dc96bc7a8ccb25ccb4b7135880768256f1ef3 --- res/layout/search_result_icon_row.xml | 31 ++++ res/layout/search_result_shortcut.xml | 42 ----- src/com/android/launcher3/BubbleTextView.java | 11 ++ .../launcher3/allapps/AllAppsGridAdapter.java | 14 +- .../model/data/RemoteActionItemInfo.java | 64 ++++++++ .../launcher3/touch/ItemClickHandler.java | 24 +++ .../launcher3/views/HeroSearchResultView.java | 2 +- .../launcher3/views/SearchResultIconRow.java | 154 ++++++++++++++++++ .../launcher3/views/SearchResultShortcut.java | 117 ------------- .../systemui/plugins/shared/SearchTarget.java | 15 +- .../plugins/shared/SearchTargetEvent.java | 2 + 11 files changed, 307 insertions(+), 169 deletions(-) create mode 100644 res/layout/search_result_icon_row.xml delete mode 100644 res/layout/search_result_shortcut.xml create mode 100644 src/com/android/launcher3/model/data/RemoteActionItemInfo.java create mode 100644 src/com/android/launcher3/views/SearchResultIconRow.java delete mode 100644 src/com/android/launcher3/views/SearchResultShortcut.java diff --git a/res/layout/search_result_icon_row.xml b/res/layout/search_result_icon_row.xml new file mode 100644 index 0000000000..5ecc0c27b6 --- /dev/null +++ b/res/layout/search_result_icon_row.xml @@ -0,0 +1,31 @@ + + + + \ No newline at end of file diff --git a/res/layout/search_result_shortcut.xml b/res/layout/search_result_shortcut.xml deleted file mode 100644 index c350c973da..0000000000 --- a/res/layout/search_result_shortcut.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index fd04081198..1e5a9e44d5 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -65,6 +65,7 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.model.data.PackageItemInfo; import com.android.launcher3.model.data.PromiseAppInfo; +import com.android.launcher3.model.data.RemoteActionItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.util.SafeCloseable; import com.android.launcher3.views.ActivityContext; @@ -300,6 +301,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, verifyHighRes(); } + /** + * Apply label and tag using a {@link RemoteActionItemInfo} + */ + public void applyFromRemoteActionInfo(RemoteActionItemInfo remoteActionItemInfo) { + applyIconAndLabel(remoteActionItemInfo); + setTag(remoteActionItemInfo); + } + private void applyIconAndLabel(ItemInfoWithIcon info) { FastBitmapDrawable iconDrawable = newIcon(getContext(), info); mDotParams.color = IconPalette.getMutedColor(info.bitmap.color, 0.54f); @@ -681,6 +690,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, mActivity.invalidateParent(info); } else if (info instanceof PackageItemInfo) { applyFromItemInfoWithIcon((PackageItemInfo) info); + } else if (info instanceof RemoteActionItemInfo) { + applyFromRemoteActionInfo((RemoteActionItemInfo) info); } mDisableRelayout = false; diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java index f01f90be11..2779ba773e 100644 --- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java +++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java @@ -92,7 +92,7 @@ public class AllAppsGridAdapter extends public static final int VIEW_TYPE_SEARCH_SLICE = 1 << 9; - public static final int VIEW_TYPE_SEARCH_SHORTCUT = 1 << 10; + public static final int VIEW_TYPE_SEARCH_ICON_ROW = 1 << 10; public static final int VIEW_TYPE_SEARCH_PEOPLE = 1 << 11; @@ -189,7 +189,7 @@ public class AllAppsGridAdapter extends || viewType == VIEW_TYPE_SEARCH_ROW || viewType == VIEW_TYPE_SEARCH_PEOPLE || viewType == VIEW_TYPE_SEARCH_THUMBNAIL - || viewType == VIEW_TYPE_SEARCH_SHORTCUT; + || viewType == VIEW_TYPE_SEARCH_ICON_ROW; } } @@ -458,9 +458,9 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_SLICE: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_slice, parent, false)); - case VIEW_TYPE_SEARCH_SHORTCUT: + case VIEW_TYPE_SEARCH_ICON_ROW: return new ViewHolder(mLayoutInflater.inflate( - R.layout.search_result_shortcut, parent, false)); + R.layout.search_result_icon_row, parent, false)); case VIEW_TYPE_SEARCH_PEOPLE: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_people_item, parent, false)); @@ -551,7 +551,7 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_ROW_WITH_BUTTON: case VIEW_TYPE_SEARCH_HERO_APP: case VIEW_TYPE_SEARCH_ROW: - case VIEW_TYPE_SEARCH_SHORTCUT: + case VIEW_TYPE_SEARCH_ICON_ROW: case VIEW_TYPE_SEARCH_PEOPLE: case VIEW_TYPE_SEARCH_THUMBNAIL: AdapterItemWithPayload item = @@ -571,8 +571,8 @@ public class AllAppsGridAdapter extends if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) return; if (holder.itemView instanceof BubbleTextView) { BubbleTextView icon = (BubbleTextView) holder.itemView; - icon.setOnClickListener(mOnIconClickListener); - icon.setOnLongClickListener(mOnIconLongClickListener); + icon.setOnClickListener(null); + icon.setOnLongClickListener(null); } else if (holder.itemView instanceof SliceView) { SliceView sliceView = (SliceView) holder.itemView; sliceView.setOnSliceActionListener(null); diff --git a/src/com/android/launcher3/model/data/RemoteActionItemInfo.java b/src/com/android/launcher3/model/data/RemoteActionItemInfo.java new file mode 100644 index 0000000000..81f7f3a0a2 --- /dev/null +++ b/src/com/android/launcher3/model/data/RemoteActionItemInfo.java @@ -0,0 +1,64 @@ +/* + * 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. + */ +package com.android.launcher3.model.data; + +import android.app.RemoteAction; +import android.os.Process; + +/** + * Represents a launchable {@link RemoteAction} + */ +public class RemoteActionItemInfo extends ItemInfoWithIcon { + + private final RemoteAction mRemoteAction; + private final String mToken; + private final boolean mShouldStart; + + public RemoteActionItemInfo(RemoteAction remoteAction, String token, boolean shouldStart) { + mShouldStart = shouldStart; + mToken = token; + mRemoteAction = remoteAction; + title = remoteAction.getTitle(); + user = Process.myUserHandle(); + } + + public RemoteActionItemInfo(RemoteActionItemInfo info) { + super(info); + this.mShouldStart = info.mShouldStart; + this.mRemoteAction = info.mRemoteAction; + this.mToken = info.mToken; + } + + @Override + public ItemInfoWithIcon clone() { + return new RemoteActionItemInfo(this); + } + + public RemoteAction getRemoteAction() { + return mRemoteAction; + } + + public String getToken() { + return mToken; + } + + /** + * Getter method for mShouldStart + */ + public boolean shouldStartInLauncher() { + return mShouldStart; + } +} diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java index 61d6f7d804..d56391da3d 100644 --- a/src/com/android/launcher3/touch/ItemClickHandler.java +++ b/src/com/android/launcher3/touch/ItemClickHandler.java @@ -25,7 +25,9 @@ import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SA import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED; import android.app.AlertDialog; +import android.app.PendingIntent; import android.content.Intent; +import android.content.IntentSender; import android.content.pm.LauncherApps; import android.content.pm.PackageInstaller.SessionInfo; import android.os.Process; @@ -49,6 +51,7 @@ import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.PromiseAppInfo; +import com.android.launcher3.model.data.RemoteActionItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.testing.TestLogging; @@ -236,6 +239,27 @@ public class ItemClickHandler { startAppShortcutOrInfoActivity(v, shortcut, launcher); } + /** + * Event handler for a {@link android.app.RemoteAction} click + * + */ + public static void onClickRemoteAction(Launcher launcher, + RemoteActionItemInfo remoteActionInfo) { + try { + PendingIntent pendingIntent = remoteActionInfo.getRemoteAction().getActionIntent(); + if (remoteActionInfo.shouldStartInLauncher()) { + launcher.startIntentSenderForResult(pendingIntent.getIntentSender(), 0, null, 0, 0, + 0); + } else { + pendingIntent.send(); + } + } catch (PendingIntent.CanceledException | IntentSender.SendIntentException e) { + Toast.makeText(launcher, + launcher.getResources().getText(R.string.shortcut_not_available), + Toast.LENGTH_SHORT).show(); + } + } + private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) { TestLogging.recordEvent( TestProtocol.SEQUENCE_MAIN, "start: startAppShortcutOrInfoActivity"); diff --git a/src/com/android/launcher3/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java index 94b9ca1484..dd322d921a 100644 --- a/src/com/android/launcher3/views/HeroSearchResultView.java +++ b/src/com/android/launcher3/views/HeroSearchResultView.java @@ -138,7 +138,7 @@ public class HeroSearchResultView extends LinearLayout implements DragSource, if (i < shortcutDetails.size()) { Pair p = shortcutDetails.get(i); //apply ItemInfo and prepare view - shortcutView.applyFromItemInfoWithIcon(p.second); + shortcutView.applyFromWorkspaceItem((WorkspaceItemInfo) p.second); MODEL_EXECUTOR.execute(() -> { // load unbadged shortcut in background and update view when icon ready appState.getIconCache().getUnbadgedShortcutIcon(p.second, p.first); diff --git a/src/com/android/launcher3/views/SearchResultIconRow.java b/src/com/android/launcher3/views/SearchResultIconRow.java new file mode 100644 index 0000000000..57c85cf42e --- /dev/null +++ b/src/com/android/launcher3/views/SearchResultIconRow.java @@ -0,0 +1,154 @@ +/* + * 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. + */ +package com.android.launcher3.views; + +import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; +import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; +import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; + +import android.app.RemoteAction; +import android.content.Context; +import android.content.pm.ShortcutInfo; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAppState; +import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload; +import com.android.launcher3.allapps.search.AllAppsSearchBarController; +import com.android.launcher3.icons.LauncherIcons; +import com.android.launcher3.model.data.ItemInfo; +import com.android.launcher3.model.data.ItemInfoWithIcon; +import com.android.launcher3.model.data.RemoteActionItemInfo; +import com.android.launcher3.model.data.WorkspaceItemInfo; +import com.android.launcher3.touch.ItemClickHandler; +import com.android.systemui.plugins.AllAppsSearchPlugin; +import com.android.systemui.plugins.shared.SearchTarget; +import com.android.systemui.plugins.shared.SearchTargetEvent; + +/** + * A view representing a stand alone shortcut search result + */ +public class SearchResultIconRow extends DoubleShadowBubbleTextView implements + AllAppsSearchBarController.PayloadResultHandler { + + private final Object[] mTargetInfo = createTargetInfo(); + private ShortcutInfo mShortcutInfo; + private AllAppsSearchPlugin mPlugin; + private AdapterItemWithPayload mAdapterItem; + + + public SearchResultIconRow(@NonNull Context context) { + super(context); + } + + public SearchResultIconRow(@NonNull Context context, + @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public SearchResultIconRow(@NonNull Context context, @Nullable AttributeSet attrs, + int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public void applyAdapterInfo(AdapterItemWithPayload adapterItemWithPayload) { + if (mAdapterItem != null) { + mAdapterItem.setSelectionHandler(null); + } + mAdapterItem = adapterItemWithPayload; + SearchTarget payload = adapterItemWithPayload.getPayload(); + mPlugin = adapterItemWithPayload.getPlugin(); + + if (payload.mRemoteAction != null) { + prepareUsingRemoteAction(payload.mRemoteAction, + payload.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN), + payload.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START)); + } else { + prepareUsingShortcutInfo(payload.shortcuts.get(0)); + } + setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT)); + adapterItemWithPayload.setSelectionHandler(this::handleSelection); + } + + private void prepareUsingShortcutInfo(ShortcutInfo shortcutInfo) { + mShortcutInfo = shortcutInfo; + WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mShortcutInfo, getContext()); + applyFromWorkspaceItem(workspaceItemInfo); + LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext()); + MODEL_EXECUTOR.execute(() -> { + launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, mShortcutInfo); + reapplyItemInfoAsync(workspaceItemInfo); + }); + } + + private void prepareUsingRemoteAction(RemoteAction remoteAction, String token, boolean start) { + RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(remoteAction, token, start); + + applyFromRemoteActionInfo(itemInfo); + UI_HELPER_EXECUTOR.post(() -> { + // If the Drawable from the remote action is not AdaptiveBitmap, styling will not work. + try (LauncherIcons li = LauncherIcons.obtain(getContext())) { + Drawable d = itemInfo.getRemoteAction().getIcon().loadDrawable(getContext()); + itemInfo.bitmap = li.createBadgedIconBitmap(d, itemInfo.user, + Build.VERSION.SDK_INT); + reapplyItemInfoAsync(itemInfo); + } + }); + + } + + void reapplyItemInfoAsync(ItemInfoWithIcon itemInfoWithIcon) { + MAIN_EXECUTOR.post(() -> reapplyItemInfo(itemInfoWithIcon)); + } + + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + + private void handleSelection(int eventType) { + ItemInfo itemInfo = (ItemInfo) getTag(); + Launcher launcher = Launcher.getLauncher(getContext()); + final SearchTargetEvent searchTargetEvent; + if (itemInfo instanceof WorkspaceItemInfo) { + ItemClickHandler.onClickAppShortcut(this, (WorkspaceItemInfo) itemInfo, launcher); + searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.SHORTCUT, + eventType); + searchTargetEvent.shortcut = mShortcutInfo; + } else { + RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo; + ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo); + searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.REMOTE_ACTION, + eventType); + searchTargetEvent.bundle = new Bundle(); + searchTargetEvent.remoteAction = remoteItemInfo.getRemoteAction(); + searchTargetEvent.bundle.putBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START, + remoteItemInfo.shouldStartInLauncher()); + searchTargetEvent.bundle.putString(SearchTarget.REMOTE_ACTION_TOKEN, + remoteItemInfo.getToken()); + } + if (mPlugin != null) { + mPlugin.notifySearchTargetEvent(searchTargetEvent); + } + } +} diff --git a/src/com/android/launcher3/views/SearchResultShortcut.java b/src/com/android/launcher3/views/SearchResultShortcut.java deleted file mode 100644 index a409f0807f..0000000000 --- a/src/com/android/launcher3/views/SearchResultShortcut.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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. - */ -package com.android.launcher3.views; - -import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; - -import android.content.Context; -import android.content.pm.ShortcutInfo; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.launcher3.BubbleTextView; -import com.android.launcher3.DeviceProfile; -import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherAppState; -import com.android.launcher3.R; -import com.android.launcher3.allapps.AllAppsGridAdapter; -import com.android.launcher3.allapps.search.AllAppsSearchBarController; -import com.android.launcher3.model.data.WorkspaceItemInfo; -import com.android.launcher3.touch.ItemClickHandler; -import com.android.systemui.plugins.AllAppsSearchPlugin; -import com.android.systemui.plugins.shared.SearchTarget; -import com.android.systemui.plugins.shared.SearchTargetEvent; - -/** - * A view representing a stand alone shortcut search result - */ -public class SearchResultShortcut extends FrameLayout implements - AllAppsSearchBarController.PayloadResultHandler { - - private BubbleTextView mBubbleTextView; - private View mIconView; - private ShortcutInfo mShortcutInfo; - private AllAppsSearchPlugin mPlugin; - private final Object[] mTargetInfo = createTargetInfo(); - - - public SearchResultShortcut(@NonNull Context context) { - super(context); - } - - public SearchResultShortcut(@NonNull Context context, - @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public SearchResultShortcut(@NonNull Context context, @Nullable AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - Launcher launcher = Launcher.getLauncher(getContext()); - DeviceProfile grid = launcher.getDeviceProfile(); - mIconView = findViewById(R.id.icon); - ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams(); - iconParams.height = grid.allAppsIconSizePx; - iconParams.width = grid.allAppsIconSizePx; - mBubbleTextView = findViewById(R.id.bubble_text); - setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT)); - } - - @Override - public void applyAdapterInfo( - AllAppsGridAdapter.AdapterItemWithPayload adapterItemWithPayload) { - SearchTarget payload = adapterItemWithPayload.getPayload(); - mPlugin = adapterItemWithPayload.getPlugin(); - mShortcutInfo = payload.shortcuts.get(0); - WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mShortcutInfo, getContext()); - mBubbleTextView.applyFromWorkspaceItem(workspaceItemInfo); - mIconView.setBackground(mBubbleTextView.getIcon()); - LauncherAppState launcherAppState = LauncherAppState.getInstance(getContext()); - MODEL_EXECUTOR.execute(() -> { - launcherAppState.getIconCache().getShortcutIcon(workspaceItemInfo, mShortcutInfo); - mBubbleTextView.applyFromWorkspaceItem(workspaceItemInfo); - mIconView.setBackground(mBubbleTextView.getIcon()); - }); - adapterItemWithPayload.setSelectionHandler(this::handleSelection); - } - - @Override - public Object[] getTargetInfo() { - return mTargetInfo; - } - - private void handleSelection(int eventType) { - WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) mBubbleTextView.getTag(); - ItemClickHandler.onClickAppShortcut(this, itemInfo, Launcher.getLauncher(getContext())); - - SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.SHORTCUT, - eventType); - searchTargetEvent.shortcut = mShortcutInfo; - if (mPlugin != null) { - mPlugin.notifySearchTargetEvent(searchTargetEvent); - } - } -} diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java index fb8dd723bc..9d9ccbaf6e 100644 --- a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java +++ b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java @@ -15,6 +15,7 @@ */ package com.android.systemui.plugins.shared; +import android.app.RemoteAction; import android.content.pm.ShortcutInfo; import android.os.Bundle; @@ -25,6 +26,14 @@ import java.util.List; */ public class SearchTarget implements Comparable { + + /** + * A bundle key for boolean value of whether remote action should be started in launcher or not + */ + public static final String REMOTE_ACTION_SHOULD_START = "should_start_for_result"; + public static final String REMOTE_ACTION_TOKEN = "action_token"; + + public enum ViewType { /** @@ -74,6 +83,7 @@ public class SearchTarget implements Comparable { THUMBNAIL(8); private final int mId; + ViewType(int id) { mId = id; } @@ -91,7 +101,8 @@ public class SearchTarget implements Comparable { APP_HERO(4, "", ViewType.HERO), SHORTCUT(5, "Shortcuts", ViewType.SHORTCUT), PEOPLE(6, "People", ViewType.PEOPLE), - SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL); + SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL), + REMOTE_ACTION(8, "Remote Actions", ViewType.SHORTCUT); private final int mId; @@ -123,12 +134,12 @@ public class SearchTarget implements Comparable { public Bundle bundle; public float score; public String mSessionId; + public RemoteAction mRemoteAction; /** * Constructor to create the search target. Bundle is currently temporary to hold * search target primitives that cannot be expressed as java primitive objects * or AOSP native objects. - * */ public SearchTarget(ItemType itemType, List shortcuts, Bundle bundle, float score, String sessionId) { diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java index 00a78de9af..5016abc1e9 100644 --- a/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java +++ b/src_plugins/com/android/systemui/plugins/shared/SearchTargetEvent.java @@ -15,6 +15,7 @@ */ package com.android.systemui.plugins.shared; +import android.app.RemoteAction; import android.content.pm.ShortcutInfo; import android.os.Bundle; @@ -29,6 +30,7 @@ public class SearchTargetEvent { public SearchTarget.ItemType type; public ShortcutInfo shortcut; + public RemoteAction remoteAction; public int eventType; public Bundle bundle; public int index; From ec7b1ee73bd306a0114e31fb11b419a98057392e Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Thu, 24 Sep 2020 20:23:06 -0700 Subject: [PATCH 27/45] Make SPAN_MULTIPLIER public Bug: 169294860 Change-Id: I6c32689c390de38f230cff4062889dd560afe6c3 --- src/com/android/launcher3/allapps/AllAppsGridAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java index f01f90be11..20f9372cf8 100644 --- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java +++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java @@ -334,7 +334,7 @@ public class AllAppsGridAdapter extends } // multiplier to support adapter item column count that is not mAppsPerRow. - private static final int SPAN_MULTIPLIER = 3; + public static final int SPAN_MULTIPLIER = 3; private final BaseDraggingActivity mLauncher; private final LayoutInflater mLayoutInflater; From e6477328aa8b82f516e1502e99343af265ad5fd6 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Sun, 20 Sep 2020 22:49:57 -0700 Subject: [PATCH 28/45] [DO NOT MERGE] Add component name to launcher home and overview gestures Bug: 168805198 Change-Id: Idcc7d00b0f23c2a0f9be6f0ab2600278e18cc1a3 --- protos/launcher_atom.proto | 11 +++++++++-- .../android/quickstep/BaseSwipeUpHandlerV2.java | 16 ++++++++++++++++ src/com/android/launcher3/LauncherSettings.java | 1 + .../android/launcher3/model/data/ItemInfo.java | 7 +++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto index 561196941c..1a8ab65370 100644 --- a/protos/launcher_atom.proto +++ b/protos/launcher_atom.proto @@ -55,6 +55,7 @@ message ContainerInfo { SettingsContainer settings_container = 9; PredictedHotseatContainer predicted_hotseat_container = 10; TaskSwitcherContainer task_switcher_container = 11; + TaskForegroundContainer task_foreground_container = 12; } } @@ -92,8 +93,14 @@ message ShortcutsContainer { message SettingsContainer { } -message TaskSwitcherContainer { -} +// Container for tasks in the Overview UI. +// Typically entered using either the overview gesture or overview button. +message TaskSwitcherContainer {} + +// Container for tasks from another foreground app, when not on launcher screen. +// Typically home gesture or overview gesture can be triggered from +// this container. +message TaskForegroundContainer {} enum Attribute { UNKNOWN = 0; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index 0aa14862a7..a4ea9b4145 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -47,6 +47,7 @@ import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.app.ActivityManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.PointF; @@ -62,12 +63,14 @@ import androidx.annotation.UiThread; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.UserEventDispatcher; +import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; @@ -928,12 +931,25 @@ public abstract class BaseSwipeUpHandlerV2, Q exte default: event = IGNORE; } + ComponentName componentName = mGestureState.getRunningTask().baseActivity; StatsLogManager.newInstance(mContext).logger() .withSrcState(LAUNCHER_STATE_BACKGROUND) .withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType)) + .withItemInfo(getItemInfo(componentName)) .log(event); } + /** + * Builds proto for logging + */ + public WorkspaceItemInfo getItemInfo(ComponentName componentName) { + WorkspaceItemInfo placeholderInfo = new WorkspaceItemInfo(); + placeholderInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK; + placeholderInfo.container = LauncherSettings.Favorites.CONTAINER_TASKFOREGROUND; + placeholderInfo.intent = new Intent().setComponent(componentName); + return placeholderInfo; + } + /** Animates to the given progress, where 0 is the current app and 1 is overview. */ @UiThread private void animateToProgress(float start, float end, long duration, Interpolator interpolator, diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java index 58a418edec..a1ac229ae7 100644 --- a/src/com/android/launcher3/LauncherSettings.java +++ b/src/com/android/launcher3/LauncherSettings.java @@ -164,6 +164,7 @@ public class LauncherSettings { public static final int CONTAINER_SHORTCUTS = -107; public static final int CONTAINER_SETTINGS = -108; public static final int CONTAINER_TASKSWITCHER = -109; + public static final int CONTAINER_TASKFOREGROUND = -110; public static final String containerToString(int container) { switch (container) { diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java index 0d3ddad183..b9b3d382c8 100644 --- a/src/com/android/launcher3/model/data/ItemInfo.java +++ b/src/com/android/launcher3/model/data/ItemInfo.java @@ -24,6 +24,7 @@ import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICT import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SEARCH_RESULTS; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SETTINGS; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS; +import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_TASKFOREGROUND; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_TASKSWITCHER; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; @@ -51,6 +52,7 @@ import com.android.launcher3.logger.LauncherAtom.PredictionContainer; import com.android.launcher3.logger.LauncherAtom.SearchResultContainer; import com.android.launcher3.logger.LauncherAtom.SettingsContainer; import com.android.launcher3.logger.LauncherAtom.ShortcutsContainer; +import com.android.launcher3.logger.LauncherAtom.TaskForegroundContainer; import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer; import com.android.launcher3.model.ModelWriter; import com.android.launcher3.util.ContentWriter; @@ -392,6 +394,11 @@ public class ItemInfo { return ContainerInfo.newBuilder() .setTaskSwitcherContainer(TaskSwitcherContainer.getDefaultInstance()) .build(); + case CONTAINER_TASKFOREGROUND: + return ContainerInfo.newBuilder() + .setTaskForegroundContainer(TaskForegroundContainer.getDefaultInstance()) + .build(); + } return ContainerInfo.getDefaultInstance(); From a13715bb931c0211fdadd95fbbfdd37720e6e350 Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Thu, 24 Sep 2020 22:19:16 -0700 Subject: [PATCH 29/45] [Live Tile] Switch to screenshot when any task menu option is selected - App info - Split screen - Pause app Fixes: 169385194 Test: Manual Change-Id: I7df8ac7dd89c8c7ae75d8e2e4207cd32ca7b10ea --- .../com/android/quickstep/views/TaskMenuView.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java index d47eba6408..4aff7e3211 100644 --- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java +++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java @@ -16,6 +16,7 @@ package com.android.quickstep.views; +import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA; import android.animation.Animator; @@ -229,7 +230,16 @@ public class TaskMenuView extends AbstractFloatingView { menuOptionView.findViewById(R.id.icon), menuOptionView.findViewById(R.id.text)); LayoutParams lp = (LayoutParams) menuOptionView.getLayoutParams(); mTaskView.getPagedOrientationHandler().setLayoutParamsForTaskMenuOptionItem(lp); - menuOptionView.setOnClickListener(menuOption); + menuOptionView.setOnClickListener(view -> { + if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { + RecentsView recentsView = mTaskView.getRecentsView(); + recentsView.switchToScreenshot(null, + () -> recentsView.finishRecentsAnimation(true /* toRecents */, + () -> menuOption.onClick(view))); + } else { + menuOption.onClick(view); + } + }); mOptionLayout.addView(menuOptionView); } From 2517dfd123534d3f4907700c51ff6c24ac85926a Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Fri, 25 Sep 2020 10:13:57 -0700 Subject: [PATCH 30/45] Update TutorialFragments to work without hand gesture animations. Test: manual TutorialFragments needed to implement getHandAnimationResId, however not all TutorialFragments will need a hand gesture animation. Updated TutorialFragment to remove this requirement. Change-Id: I2f75d6447dcceb226569181176deed1d5e80fa5f --- .../AssistantGestureTutorialFragment.java | 2 +- .../BackGestureTutorialFragment.java | 2 +- .../HomeGestureTutorialFragment.java | 2 +- .../OverviewGestureTutorialFragment.java | 2 +- .../interaction/TutorialController.java | 7 +++++-- .../interaction/TutorialFragment.java | 20 +++++++++++++------ 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java index 70181fb9ca..16886ec177 100644 --- a/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java @@ -24,7 +24,7 @@ import com.android.quickstep.interaction.TutorialController.TutorialType; /** Shows the Home gesture interactive tutorial. */ public class AssistantGestureTutorialFragment extends TutorialFragment { @Override - int getHandAnimationResId() { + Integer getHandAnimationResId() { return R.drawable.assistant_gesture; } diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java index bef50ea8df..41db684d44 100644 --- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java @@ -24,7 +24,7 @@ import com.android.quickstep.interaction.TutorialController.TutorialType; /** Shows the Back gesture interactive tutorial. */ public class BackGestureTutorialFragment extends TutorialFragment { @Override - int getHandAnimationResId() { + Integer getHandAnimationResId() { return R.drawable.back_gesture; } diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java index e2a9d1276c..63595a5283 100644 --- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java @@ -21,7 +21,7 @@ import com.android.quickstep.interaction.TutorialController.TutorialType; /** Shows the Home gesture interactive tutorial. */ public class HomeGestureTutorialFragment extends TutorialFragment { @Override - int getHandAnimationResId() { + Integer getHandAnimationResId() { return R.drawable.home_gesture; } diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java index 3357b70497..93200bb21d 100644 --- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java @@ -21,7 +21,7 @@ import com.android.quickstep.interaction.TutorialController.TutorialType; /** Shows the Overview gesture interactive tutorial. */ public class OverviewGestureTutorialFragment extends TutorialFragment { @Override - int getHandAnimationResId() { + Integer getHandAnimationResId() { return R.drawable.overview_gesture; } diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java index db80342673..d0a12679c0 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java @@ -52,7 +52,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, final View mFakeTaskView; final View mRippleView; final RippleDrawable mRippleDrawable; - final TutorialHandAnimation mHandCoachingAnimation; + @Nullable final TutorialHandAnimation mHandCoachingAnimation; final ImageView mHandCoachingView; final Button mActionTextButton; final Button mActionButton; @@ -145,13 +145,16 @@ abstract class TutorialController implements BackGestureAttemptCallback, void onActionTextButtonClicked(View button) {} void showHandCoachingAnimation() { - if (isComplete()) { + if (isComplete() || mHandCoachingAnimation == null) { return; } mHandCoachingAnimation.startLoopedAnimation(mTutorialType); } void hideHandCoachingAnimation() { + if (mHandCoachingAnimation == null) { + return; + } mHandCoachingAnimation.stop(); mHandCoachingView.setVisibility(View.INVISIBLE); } diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java index c90ad94b8c..559ba354d2 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java @@ -43,7 +43,7 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { TutorialType mTutorialType; @Nullable TutorialController mTutorialController = null; View mRootView; - TutorialHandAnimation mHandCoachingAnimation; + @Nullable TutorialHandAnimation mHandCoachingAnimation = null; EdgeBackGestureHandler mEdgeBackGestureHandler; NavBarGestureHandler mNavBarGestureHandler; private View mLauncherView; @@ -82,7 +82,9 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { return null; } - abstract int getHandAnimationResId(); + @Nullable Integer getHandAnimationResId() { + return null; + } abstract TutorialController createController(TutorialType type); @@ -116,8 +118,11 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { return insets; }); mRootView.setOnTouchListener(this); - mHandCoachingAnimation = - new TutorialHandAnimation(getContext(), mRootView, getHandAnimationResId()); + Integer handAnimationResId = getHandAnimationResId(); + if (handAnimationResId != null) { + mHandCoachingAnimation = + new TutorialHandAnimation(getContext(), mRootView, handAnimationResId); + } InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(getContext()); mLauncherView = new SandboxLauncherRenderer(getContext(), dp, true).getRenderedView(); ((ViewGroup) mRootView).addView(mLauncherView, 0); @@ -133,7 +138,10 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { @Override public void onPause() { super.onPause(); - mHandCoachingAnimation.stop(); + + if (mHandCoachingAnimation != null) { + mHandCoachingAnimation.stop(); + } } @Override @@ -183,7 +191,7 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { return mLauncherView; } - TutorialHandAnimation getHandAnimation() { + @Nullable TutorialHandAnimation getHandAnimation() { return mHandCoachingAnimation; } From 91ef6856d7d025d6ac811e1d2b72a34afc9bea0c Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Fri, 18 Sep 2020 17:37:06 +0800 Subject: [PATCH 31/45] Remove legacy involveSplitScreen API The onSplitScreenInvoked was used to notify system ui to reset the divider position before entering split screen. With SplitScreenTaskOrganizer, WM Shell library could know the exact time when entering/leaving split screen mode. Removes the legacy API and resets divider position when leaving split screen mode. Fix: 168869136 Test: atest WMShellTests Test: atest SystemUITests Test: manual check recents and split screen behavior Change-Id: Id14925619d1ec7c014a3e306fd99ec3734f227da (cherry picked from commit 44981eb88ecdd4782e6bf6bb89eea6e9fc667335) --- .../src/com/android/quickstep/SystemUiProxy.java | 11 ----------- .../com/android/quickstep/TaskShortcutFactory.java | 1 - 2 files changed, 12 deletions(-) diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index e4b05aec12..2666869136 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -113,17 +113,6 @@ public class SystemUiProxy implements ISystemUiProxy { } } - @Override - public void onSplitScreenInvoked() { - if (mSystemUiProxy != null) { - try { - mSystemUiProxy.onSplitScreenInvoked(); - } catch (RemoteException e) { - Log.w(TAG, "Failed call onSplitScreenInvoked", e); - } - } - } - @Override public void onOverviewShown(boolean fromHome) { onOverviewShown(fromHome, TAG); diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java index 3b245b3230..2b55b805c6 100644 --- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java +++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java @@ -228,7 +228,6 @@ public interface TaskShortcutFactory { @Override protected boolean onActivityStarted(BaseDraggingActivity activity) { - SystemUiProxy.INSTANCE.get(activity).onSplitScreenInvoked(); activity.getUserEventDispatcher().logActionOnControl(TAP, LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET); return true; From 1b17d6be20c9d1c6a4fe194b71c644f5f8a281a1 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Fri, 25 Sep 2020 12:32:08 -0700 Subject: [PATCH 32/45] Make the workspace popup menu items statically ordered. Test: manual Fixes: 160190991. Reordering the workspace's popup menu items breaks muscle memory of getting to the wallpaper and home settings. Added ArrowPopup#show and refactored ArrowPopup#reorderAndShow to allow more flexbility. Change-Id: I3fa327d08488a52312c86769bb9a065ccacb17aa --- .../android/launcher3/popup/ArrowPopup.java | 58 ++++++++++++------- .../launcher3/views/OptionsPopupView.java | 2 +- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java index d5b32fccd1..90285c470b 100644 --- a/src/com/android/launcher3/popup/ArrowPopup.java +++ b/src/com/android/launcher3/popup/ArrowPopup.java @@ -151,32 +151,52 @@ public abstract class ArrowPopup extends Abstrac * @param viewsToFlip number of views from the top to to flip in case of reverse order */ protected void reorderAndShow(int viewsToFlip) { + setupForDisplay(); + boolean reverseOrder = mIsAboveIcon; + if (reverseOrder) { + reverseOrder(viewsToFlip); + } + onInflationComplete(reverseOrder); + addArrow(); + animateOpen(); + } + + /** + * Shows the popup at the desired location. + */ + protected void show() { + setupForDisplay(); + onInflationComplete(false); + addArrow(); + animateOpen(); + } + + private void setupForDisplay() { setVisibility(View.INVISIBLE); mIsOpen = true; getPopupContainer().addView(this); orientAboutObject(); + } - boolean reverseOrder = mIsAboveIcon; - if (reverseOrder) { - int count = getChildCount(); - ArrayList allViews = new ArrayList<>(count); - for (int i = 0; i < count; i++) { - if (i == viewsToFlip) { - Collections.reverse(allViews); - } - allViews.add(getChildAt(i)); + private void reverseOrder(int viewsToFlip) { + int count = getChildCount(); + ArrayList allViews = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + if (i == viewsToFlip) { + Collections.reverse(allViews); } - Collections.reverse(allViews); - removeAllViews(); - for (int i = 0; i < count; i++) { - addView(allViews.get(i)); - } - - orientAboutObject(); + allViews.add(getChildAt(i)); + } + Collections.reverse(allViews); + removeAllViews(); + for (int i = 0; i < count; i++) { + addView(allViews.get(i)); } - onInflationComplete(reverseOrder); - // Add the arrow. + orientAboutObject(); + } + + private void addArrow() { final Resources res = getResources(); final int arrowCenterOffset = res.getDimensionPixelSize(isAlignedWithStart() ? R.dimen.popup_arrow_horizontal_center_start @@ -214,8 +234,6 @@ public abstract class ArrowPopup extends Abstrac mArrow.setPivotX(arrowLp.width / 2); mArrow.setPivotY(mIsAboveIcon ? arrowLp.height : 0); - - animateOpen(); } protected boolean isAlignedWithStart() { diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java index a8caa9ea00..80f0981af5 100644 --- a/src/com/android/launcher3/views/OptionsPopupView.java +++ b/src/com/android/launcher3/views/OptionsPopupView.java @@ -133,7 +133,7 @@ public class OptionsPopupView extends ArrowPopup view.setOnLongClickListener(popup); popup.mItemMap.put(view, item); } - popup.reorderAndShow(popup.getChildCount()); + popup.show(); } @VisibleForTesting From 95786e077daa43b96ebea34ec3035b05bf96ffce Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Tue, 15 Sep 2020 00:34:10 -0700 Subject: [PATCH 33/45] Good riddance UserEventDispatcher Bug: 165675920 Bug: 161381246 TL;DR;; - nano -> lite proto - add all the missing logs to WW - pin item related logging fix - Removed logging for assistant sgrep "com.android.launcher3.userevent.nano." | cut -f1 -d: | xargs sed -i -e 's/userevent\.nano\./userevent\./g' Change-Id: Ie2a49fdd891cacbd7ef40a1dc9e41ff0574c7517 --- Android.mk | 8 - build.gradle | 24 +- protos/launcher_log.proto | 245 ------------ .../appprediction/PredictionRowView.java | 31 +- .../HotseatPredictionController.java | 1 - .../uioverrides/states/AllAppsState.java | 4 +- .../states/BackgroundAppState.java | 5 +- .../states/OverviewModalTaskState.java | 5 +- .../uioverrides/states/OverviewState.java | 4 +- .../uioverrides/states/QuickSwitchState.java | 5 +- .../LandscapeEdgeSwipeController.java | 16 +- .../NavBarToHomeTouchController.java | 19 +- ...ButtonNavbarToOverviewTouchController.java | 5 +- .../NoButtonQuickSwitchTouchController.java | 25 +- .../OverviewToAllAppsTouchController.java | 6 - .../PortraitStatesTouchController.java | 13 +- .../QuickSwitchTouchController.java | 19 +- .../StatusBarTouchController.java | 14 +- .../TaskViewTouchController.java | 14 +- .../android/quickstep/AbsSwipeUpHandler.java | 29 +- .../quickstep/BaseActivityInterface.java | 5 - .../quickstep/FallbackActivityInterface.java | 10 - .../com/android/quickstep/GestureState.java | 12 +- .../quickstep/LauncherActivityInterface.java | 12 - .../quickstep/OverviewCommandHelper.java | 9 - .../android/quickstep/RecentsActivity.java | 1 - .../quickstep/TaskShortcutFactory.java | 4 - .../AssistantInputConsumer.java | 20 +- .../OverviewWithoutFocusInputConsumer.java | 17 +- .../quickstep/util/RecentsOrientedState.java | 11 +- .../views/DigitalWellBeingToast.java | 5 +- .../android/quickstep/views/RecentsView.java | 10 +- .../com/android/quickstep/views/TaskView.java | 14 +- res/values/config.xml | 1 - .../secondarydisplay/SDWorkModeTest.java | 5 - .../launcher3/ui/LauncherUIScrollTest.java | 5 - src/com/android/launcher3/BaseActivity.java | 12 - .../android/launcher3/ButtonDropTarget.java | 3 - .../android/launcher3/DeleteDropTarget.java | 24 +- src/com/android/launcher3/Hotseat.java | 23 +- src/com/android/launcher3/Launcher.java | 33 +- src/com/android/launcher3/LauncherState.java | 12 +- .../launcher3/SecondaryDropTarget.java | 16 - src/com/android/launcher3/Workspace.java | 33 +- .../allapps/AllAppsRecyclerView.java | 15 +- .../launcher3/allapps/DiscoveryBounce.java | 10 +- .../launcher3/anim/PendingAnimation.java | 10 +- .../launcher3/dragndrop/AddItemActivity.java | 30 +- .../launcher3/dragndrop/DragController.java | 2 - src/com/android/launcher3/folder/Folder.java | 34 +- .../android/launcher3/folder/FolderIcon.java | 1 - .../launcher3/logging/LoggerUtils.java | 190 --------- .../launcher3/logging/StatsLogManager.java | 74 ++-- .../launcher3/logging/StatsLogUtils.java | 49 --- .../logging/UserEventDispatcher.java | 373 ------------------ .../launcher3/model/data/FolderInfo.java | 119 ------ .../notification/NotificationMainView.java | 7 +- .../popup/PopupContainerWithArrow.java | 9 +- .../launcher3/popup/RemoteActionShortcut.java | 4 - .../launcher3/popup/SystemShortcut.java | 6 - .../android/launcher3/states/HintState.java | 5 +- .../launcher3/states/SpringLoadedState.java | 5 +- .../AbstractStateChangeTouchController.java | 50 +-- .../touch/AllAppsSwipeController.java | 7 - .../uioverrides/states/AllAppsState.java | 4 +- .../uioverrides/states/OverviewState.java | 5 +- 66 files changed, 232 insertions(+), 1566 deletions(-) delete mode 100644 protos/launcher_log.proto delete mode 100644 src/com/android/launcher3/logging/LoggerUtils.java delete mode 100644 src/com/android/launcher3/logging/StatsLogUtils.java delete mode 100644 src/com/android/launcher3/logging/UserEventDispatcher.java diff --git a/Android.mk b/Android.mk index 25f5412d21..349a134d75 100644 --- a/Android.mk +++ b/Android.mk @@ -36,18 +36,12 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ launcher_log_protos_lite LOCAL_SRC_FILES := \ - $(call all-proto-files-under, protos) \ - $(call all-proto-files-under, proto_overrides) \ $(call all-java-files-under, src_build_config) \ LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_PROGUARD_ENABLED := disabled -LOCAL_PROTOC_OPTIMIZE_TYPE := nano -LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/ --proto_path=$(LOCAL_PATH)/proto_overrides/ -LOCAL_PROTO_JAVA_OUTPUT_PARAMS := enum_style=java - LOCAL_SDK_VERSION := current LOCAL_MIN_SDK_VERSION := 26 LOCAL_MODULE := Launcher3CommonDepsLib @@ -135,7 +129,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_STATIC_JAVA_LIBRARIES := \ SystemUI-statsd \ SystemUISharedLib \ - launcherprotosnano \ launcher_log_protos_lite ifneq (,$(wildcard frameworks/base)) LOCAL_PRIVATE_PLATFORM_APIS := true @@ -203,7 +196,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_STATIC_JAVA_LIBRARIES := \ SystemUI-statsd \ SystemUISharedLib \ - launcherprotosnano \ launcher_log_protos_lite ifneq (,$(wildcard frameworks/base)) LOCAL_PRIVATE_PLATFORM_APIS := true diff --git a/build.gradle b/build.gradle index 534ca65115..28a05d569c 100644 --- a/build.gradle +++ b/build.gradle @@ -82,7 +82,6 @@ android { manifest.srcFile 'AndroidManifest-common.xml' proto { srcDir 'protos/' - srcDir 'proto_overrides/' } } @@ -150,7 +149,6 @@ dependencies { implementation "androidx.preference:preference:${ANDROID_X_VERSION}" implementation project(':IconLoader') withQuickstepImplementation project(':SharedLibWrapper') - implementation fileTree(dir: "${FRAMEWORK_PREBUILTS_DIR}/libs", include: 'launcher_protos.jar') // Recents lib dependency withQuickstepImplementation fileTree(dir: "${FRAMEWORK_PREBUILTS_DIR}/quickstep/libs", include: 'sysui_shared.jar') @@ -171,20 +169,16 @@ dependencies { protobuf { // Configure the protoc executable protoc { - artifact = 'com.google.protobuf:protoc:3.0.0' - - generateProtoTasks { - all().each { task -> - task.builtins { - remove java - javanano { - option "java_package=launcher_log_extension.proto|com.android.launcher3.userevent.nano" - option "java_package=launcher_log.proto|com.android.launcher3.userevent.nano" - option "java_package=launcher_dump.proto|com.android.launcher3.model.nano" - option "enum_style=java" - } + artifact = "com.google.protobuf:protoc:${protocVersion}" + } + generateProtoTasks { + all().each { task -> + task.builtins { + remove java + java { + option "lite" } } } } -} +} \ No newline at end of file diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto deleted file mode 100644 index 9423cb2642..0000000000 --- a/protos/launcher_log.proto +++ /dev/null @@ -1,245 +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. - */ -syntax = "proto2"; - -import "launcher_log_extension.proto"; - -option java_package = "com.android.launcher3.userevent"; -option java_outer_classname = "LauncherLogProto"; - -package userevent; - -message Target { - enum Type { - NONE = 0; - ITEM = 1; - CONTROL = 2; - CONTAINER = 3; - } - - optional Type type = 1; - - // For container type and item type - // Used mainly for ContainerType.FOLDER, ItemType.* - optional int32 page_index = 2; - optional int32 rank = 3; - optional int32 grid_x = 4; - optional int32 grid_y = 5; - - // For container types only - optional ContainerType container_type = 6; - optional int32 cardinality = 7; - - // For control types only - optional ControlType control_type = 8; - - // For item types only - optional ItemType item_type = 9; - optional int32 package_name_hash = 10; - optional int32 component_hash = 11; // Used for ItemType.WIDGET - optional int32 intent_hash = 12; // Used for ItemType.SHORTCUT - optional int32 span_x = 13 [default = 1];// Used for ItemType.WIDGET - optional int32 span_y = 14 [default = 1];// Used for ItemType.WIDGET - optional int32 predictedRank = 15; - optional TargetExtension extension = 16; - optional TipType tip_type = 17; - optional int32 search_query_length = 18; - optional bool is_work_app = 19; - optional FromFolderLabelState from_folder_label_state = 20; - optional ToFolderLabelState to_folder_label_state = 21; - - // Note: proto does not support duplicate enum values, even if they belong to different enum type. - // Hence "FROM" and "TO" prefix added. - enum FromFolderLabelState { - FROM_FOLDER_LABEL_STATE_UNSPECIFIED = 0; - FROM_EMPTY = 1; - FROM_CUSTOM = 2; - FROM_SUGGESTED = 3; - } - - enum ToFolderLabelState { - TO_FOLDER_LABEL_STATE_UNSPECIFIED = 0; - TO_SUGGESTION0_WITH_VALID_PRIMARY = 1; - TO_SUGGESTION1_WITH_VALID_PRIMARY = 2; - TO_SUGGESTION1_WITH_EMPTY_PRIMARY = 3; - TO_SUGGESTION2_WITH_VALID_PRIMARY = 4; - TO_SUGGESTION2_WITH_EMPTY_PRIMARY = 5; - TO_SUGGESTION3_WITH_VALID_PRIMARY = 6; - TO_SUGGESTION3_WITH_EMPTY_PRIMARY = 7; - TO_EMPTY_WITH_VALID_SUGGESTIONS = 8 [deprecated = true]; - TO_EMPTY_WITH_VALID_PRIMARY = 15; - TO_EMPTY_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY = 16; - TO_EMPTY_WITH_EMPTY_SUGGESTIONS = 9; - TO_EMPTY_WITH_SUGGESTIONS_DISABLED = 10; - TO_CUSTOM_WITH_VALID_SUGGESTIONS = 11 [deprecated = true]; - TO_CUSTOM_WITH_VALID_PRIMARY = 17; - TO_CUSTOM_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY = 18; - TO_CUSTOM_WITH_EMPTY_SUGGESTIONS = 12; - TO_CUSTOM_WITH_SUGGESTIONS_DISABLED = 13; - UNCHANGED = 14; - } -} - -// Used to define what type of item a Target would represent. -enum ItemType { - DEFAULT_ITEMTYPE = 0; - APP_ICON = 1; - SHORTCUT = 2; - WIDGET = 3; - FOLDER_ICON = 4; - DEEPSHORTCUT = 5; - SEARCHBOX = 6; - EDITTEXT = 7; - NOTIFICATION = 8; - TASK = 9; // Each page of Recents UI (QuickStep) - WEB_APP = 10; - TASK_ICON = 11; -} - -// Used to define what type of container a Target would represent. -enum ContainerType { - DEFAULT_CONTAINERTYPE = 0; - WORKSPACE = 1; - HOTSEAT = 2; - FOLDER = 3; - ALLAPPS = 4; - WIDGETS = 5; - OVERVIEW = 6; // Zoomed out workspace (without QuickStep) - PREDICTION = 7; - SEARCHRESULT = 8; - DEEPSHORTCUTS = 9; - PINITEM = 10; // confirmation screen - NAVBAR = 11; - TASKSWITCHER = 12; // Recents UI Container (QuickStep) - APP = 13; // Foreground activity is another app (QuickStep) - TIP = 14; // Onboarding texts (QuickStep) - OTHER_LAUNCHER_APP = 15; -} - -// Used to define what type of control a Target would represent. -enum ControlType { - DEFAULT_CONTROLTYPE = 0; - ALL_APPS_BUTTON = 1; - WIDGETS_BUTTON = 2; - WALLPAPER_BUTTON = 3; - SETTINGS_BUTTON = 4; - REMOVE_TARGET = 5; - UNINSTALL_TARGET = 6; - APPINFO_TARGET = 7; - RESIZE_HANDLE = 8; - VERTICAL_SCROLL = 9; - HOME_INTENT = 10; // Deprecated, use enum Command instead - BACK_BUTTON = 11; - QUICK_SCRUB_BUTTON = 12; - CLEAR_ALL_BUTTON = 13; - CANCEL_TARGET = 14; - TASK_PREVIEW = 15; - SPLIT_SCREEN_TARGET = 16; - REMOTE_ACTION_SHORTCUT = 17; - APP_USAGE_SETTINGS = 18; - BACK_GESTURE = 19; - UNDO = 20; - DISMISS_PREDICTION = 21; - HYBRID_HOTSEAT_ACCEPTED = 22; - HYBRID_HOTSEAT_CANCELED = 23; - OVERVIEW_ACTIONS_SHARE_BUTTON = 24; - OVERVIEW_ACTIONS_SCREENSHOT_BUTTON = 25; - OVERVIEW_ACTIONS_SELECT_BUTTON = 26; - SELECT_MODE_CLOSE_BUTTON = 27; - SELECT_MODE_ITEM = 28; -} - -enum TipType { - DEFAULT_NONE = 0; - BOUNCE = 1; - SWIPE_UP_TEXT = 2; - QUICK_SCRUB_TEXT = 3; - PREDICTION_TEXT = 4; - DWB_TOAST = 5; - HYBRID_HOTSEAT = 6; -} - -// Used to define the action component of the LauncherEvent. -message Action { - enum Type { - TOUCH = 0; - AUTOMATED = 1; - COMMAND = 2; - TIP = 3; - SOFT_KEYBOARD = 4; - // HARD_KEYBOARD, ASSIST - } - - enum Touch { - TAP = 0; - LONGPRESS = 1; - DRAGDROP = 2; - SWIPE = 3; - FLING = 4; - PINCH = 5; - SWIPE_NOOP = 6; - } - - enum Direction { - NONE = 0; - UP = 1; - DOWN = 2; - LEFT = 3; - RIGHT = 4; - UPRIGHT = 5; - UPLEFT = 6; - } - enum Command { - HOME_INTENT = 0; - BACK = 1; - ENTRY = 2; // Indicates entry to one of Launcher container type target - // not using the HOME_INTENT - CANCEL = 3; // Indicates that a confirmation screen was cancelled - CONFIRM = 4; // Indicates thata confirmation screen was accepted - STOP = 5; // Indicates onStop() was called (screen time out, power off) - RECENTS_BUTTON = 6; // Indicates that Recents button was pressed - RESUME = 7; // Indicates onResume() was called - } - - optional Type type = 1; - optional Touch touch = 2; - optional Direction dir = 3; - optional Command command = 4; - // Log if the action was performed on outside of the container - optional bool is_outside = 5; - optional bool is_state_change = 6; -} - -// -// Context free grammar of typical user interaction: -// Action (Touch) + Target -// Action (Touch) + Target + Target -// -message LauncherEvent { - required Action action = 1; - // List of targets that touch actions can be operated on. - repeated Target src_target = 2; - repeated Target dest_target = 3; - - optional int64 action_duration_millis = 4; - optional int64 elapsed_container_millis = 5; - optional int64 elapsed_session_millis = 6; - - optional bool is_in_multi_window_mode = 7 [deprecated = true]; - optional bool is_in_landscape_mode = 8 [deprecated = true]; - - optional LauncherEventExtension extension = 9; -} diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java index d3c4c3d62d..5b066c6be6 100644 --- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java +++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java @@ -16,11 +16,8 @@ package com.android.launcher3.appprediction; -import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound; -import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; -import static com.android.launcher3.logging.LoggerUtils.newTarget; import android.annotation.TargetApi; import android.content.Context; @@ -43,7 +40,6 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.allapps.AllAppsSectionDecorator; import com.android.launcher3.allapps.FloatingHeaderRow; @@ -53,13 +49,11 @@ import com.android.launcher3.anim.PropertySetter; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.keyboard.FocusIndicatorHelper; import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper; -import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.touch.ItemLongClickListener; -import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.Themes; import com.android.quickstep.AnimatedFloat; @@ -68,7 +62,7 @@ import java.util.List; @TargetApi(Build.VERSION_CODES.P) public class PredictionRowView extends LinearLayout implements - LogContainerProvider, OnDeviceProfileChangeListener, FloatingHeaderRow { + OnDeviceProfileChangeListener, FloatingHeaderRow { private static final IntProperty TEXT_ALPHA = new IntProperty("textAlpha") { @@ -271,29 +265,6 @@ public class PredictionRowView extends LinearLayout implements mParent.onHeightUpdated(); } - @Override - public void fillInLogContainerData(ItemInfo childInfo, LauncherLogProto.Target child, - ArrayList parents) { - for (int i = 0; i < mPredictedApps.size(); i++) { - ItemInfoWithIcon appInfo = mPredictedApps.get(i); - if (appInfo == childInfo) { - child.predictedRank = i; - break; - } - } - parents.add(newContainerTarget(LauncherLogProto.ContainerType.PREDICTION)); - - // include where the prediction is coming this used to be Launcher#modifyUserEvent - LauncherLogProto.Target parent = newTarget(LauncherLogProto.Target.Type.CONTAINER); - LauncherState state = mLauncher.getStateManager().getState(); - if (state == LauncherState.ALL_APPS) { - parent.containerType = LauncherLogProto.ContainerType.ALLAPPS; - } else if (state == OVERVIEW) { - parent.containerType = LauncherLogProto.ContainerType.TASKSWITCHER; - } - parents.add(parent); - } - public void setTextAlpha(int textAlpha) { mIconLastSetTextAlpha = textAlpha; if (getAlpha() < 1 && textAlpha > 0) { diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java index 151a113d1e..380735044d 100644 --- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java +++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java @@ -55,7 +55,6 @@ import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.touch.ItemLongClickListener; import com.android.launcher3.uioverrides.PredictedAppIcon; import com.android.launcher3.uioverrides.QuickstepLauncher; -import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.OnboardingPrefs; import com.android.launcher3.views.ArrowTipView; import com.android.launcher3.views.Snackbar; diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java index bce73cd4e4..a2e3bdf8a0 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java @@ -16,6 +16,7 @@ package com.android.launcher3.uioverrides.states; import static com.android.launcher3.anim.Interpolators.DEACCEL_2; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS; import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; import android.content.Context; @@ -23,7 +24,6 @@ import android.content.Context; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.allapps.AllAppsContainerView; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; /** * Definition for AllApps state @@ -40,7 +40,7 @@ public class AllAppsState extends LauncherState { }; public AllAppsState(int id) { - super(id, ContainerType.ALLAPPS, STATE_FLAGS); + super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS); } @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java index 8ff05f2aaa..4b4f955204 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java @@ -15,12 +15,13 @@ */ package com.android.launcher3.uioverrides.states; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND; + import android.content.Context; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Launcher; import com.android.launcher3.allapps.AllAppsTransitionController; -import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.views.RecentsView; @@ -33,7 +34,7 @@ public class BackgroundAppState extends OverviewState { | FLAG_WORKSPACE_INACCESSIBLE | FLAG_NON_INTERACTIVE | FLAG_CLOSE_POPUPS; public BackgroundAppState(int id) { - this(id, LauncherLogProto.ContainerType.TASKSWITCHER); + this(id, LAUNCHER_STATE_BACKGROUND); } protected BackgroundAppState(int id, int logContainer) { diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java index fc0dcd5119..41c689d16d 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java @@ -15,13 +15,14 @@ */ package com.android.launcher3.uioverrides.states; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW; + import android.content.Context; import android.graphics.Rect; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.quickstep.views.RecentsView; /** @@ -34,7 +35,7 @@ public class OverviewModalTaskState extends OverviewState { FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_WORKSPACE_INACCESSIBLE; public OverviewModalTaskState(int id) { - super(id, ContainerType.OVERVIEW, STATE_FLAGS); + super(id, LAUNCHER_STATE_OVERVIEW, STATE_FLAGS); } @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java index bbe7821864..525ff5816d 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java @@ -16,6 +16,7 @@ package com.android.launcher3.uioverrides.states; import static com.android.launcher3.anim.Interpolators.DEACCEL_2; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW; import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape; import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; @@ -29,7 +30,6 @@ import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.Workspace; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.quickstep.SysUINavigationMode; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.views.RecentsView; @@ -51,7 +51,7 @@ public class OverviewState extends LauncherState { } protected OverviewState(int id, int stateFlags) { - this(id, ContainerType.TASKSWITCHER, stateFlags); + this(id, LAUNCHER_STATE_OVERVIEW, stateFlags); } protected OverviewState(int id, int logContainer, int stateFlags) { diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java index 2c7373e206..51e72dacdc 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java @@ -15,8 +15,9 @@ */ package com.android.launcher3.uioverrides.states; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND; + import com.android.launcher3.Launcher; -import com.android.launcher3.userevent.nano.LauncherLogProto; /** * State to indicate we are about to launch a recent task. Note that this state is only used when @@ -26,7 +27,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto; public class QuickSwitchState extends BackgroundAppState { public QuickSwitchState(int id) { - super(id, LauncherLogProto.ContainerType.APP); + super(id, LAUNCHER_STATE_BACKGROUND); } @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java index bef191ef8f..7a0f634b45 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java @@ -12,8 +12,6 @@ import com.android.launcher3.LauncherState; import com.android.launcher3.states.StateAnimationConfig.AnimationFlags; import com.android.launcher3.touch.AbstractStateChangeTouchController; import com.android.launcher3.touch.SingleAxisSwipeDetector; -import com.android.launcher3.userevent.nano.LauncherLogProto; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.quickstep.SystemUiProxy; /** @@ -45,11 +43,6 @@ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchContro return draggingFromNav ? OVERVIEW : NORMAL; } - @Override - protected int getLogContainerTypeForNormalState(MotionEvent ev) { - return LauncherLogProto.ContainerType.NAVBAR; - } - @Override protected float getShiftRange() { return mLauncher.getDragLayer().getWidth(); @@ -65,13 +58,8 @@ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchContro } @Override - protected int getDirectionForLog() { - return mLauncher.getDeviceProfile().isSeascape() ? Direction.RIGHT : Direction.LEFT; - } - - @Override - protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { - super.onSwipeInteractionCompleted(targetState, logAction); + protected void onSwipeInteractionCompleted(LauncherState targetState) { + super.onSwipeInteractionCompleted(targetState); if (mStartState == NORMAL && targetState == OVERVIEW) { SystemUiProxy.INSTANCE.get(mLauncher).onOverviewShown(true, TAG); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java index 76168440a8..d210bc6851 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java @@ -45,12 +45,9 @@ import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.graphics.OverviewScrim; -import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.SingleAxisSwipeDetector; -import com.android.launcher3.userevent.nano.LauncherLogProto; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.TouchController; import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.AssistantUtilities; @@ -211,7 +208,6 @@ public class NavBarToHomeTouchController implements TouchController, @Override public void onDragEnd(float velocity) { boolean fling = mSwipeDetector.isFling(velocity); - final int logAction = fling ? Touch.FLING : Touch.SWIPE; float progress = mCurrentAnimation.getProgressFraction(); float interpolatedProgress = PULLBACK_INTERPOLATOR.getInterpolation(progress); boolean success = interpolatedProgress >= SUCCESS_TRANSITION_PROGRESS @@ -230,7 +226,7 @@ public class NavBarToHomeTouchController implements TouchController, () -> onSwipeInteractionCompleted(mEndState)); } if (mStartState != mEndState) { - // TODO: add to WW log + logHomeGesture(); } AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(mLauncher); if (topOpenView != null) { @@ -255,17 +251,10 @@ public class NavBarToHomeTouchController implements TouchController, AccessibilityManagerCompat.sendStateEventToTest(mLauncher, targetState.ordinal); } - private void logStateChange(int startContainerType, int logAction) { - mLauncher.getUserEventDispatcher().logStateChangeAction(logAction, - LauncherLogProto.Action.Direction.UP, - mSwipeDetector.getDownX(), mSwipeDetector.getDownY(), - LauncherLogProto.ContainerType.NAVBAR, - startContainerType, - mEndState.containerType, - mLauncher.getWorkspace().getCurrentPage()); + private void logHomeGesture() { mLauncher.getStatsLogManager().logger() - .withSrcState(StatsLogManager.containerTypeToAtomState(mStartState.containerType)) - .withDstState(StatsLogManager.containerTypeToAtomState(mEndState.containerType)) + .withSrcState(mStartState.statsLogOrdinal) + .withDstState(mEndState.statsLogOrdinal) .log(LAUNCHER_HOME_GESTURE); } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java index c78d4741d8..2a3bdbfcb8 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java @@ -49,7 +49,6 @@ import com.android.launcher3.anim.Interpolators; import com.android.launcher3.graphics.OverviewScrim; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.testing.TestProtocol; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.VibratorWrapper; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.util.AnimatorControllerWithResistance; @@ -207,7 +206,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch private void maybeSwipeInteractionToOverviewComplete() { if (mReachedOverview && mDetector.isSettlingState()) { - onSwipeInteractionCompleted(OVERVIEW, Touch.SWIPE); + onSwipeInteractionCompleted(OVERVIEW); } } @@ -251,7 +250,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch private void goToOverviewOrHomeOnDragEnd(float velocity) { boolean goToHomeInsteadOfOverview = !mMotionPauseDetector.isPaused(); if (goToHomeInsteadOfOverview) { - new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL, Touch.FLING)) + new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL)) .animateWithVelocity(velocity); } if (mReachedOverview) { diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java index a6a3497f04..f378848a71 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java @@ -57,13 +57,9 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.graphics.OverviewScrim; -import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.BaseSwipeDetector; import com.android.launcher3.touch.BothAxesSwipeDetector; -import com.android.launcher3.userevent.nano.LauncherLogProto; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.TouchController; import com.android.launcher3.util.VibratorWrapper; import com.android.quickstep.AnimatedFloat; @@ -287,7 +283,6 @@ public class NoButtonQuickSwitchTouchController implements TouchController, boolean horizontalFling = mSwipeDetector.isFling(velocity.x); boolean verticalFling = mSwipeDetector.isFling(velocity.y); boolean noFling = !horizontalFling && !verticalFling; - int logAction = noFling ? Touch.SWIPE : Touch.FLING; if (mMotionPauseDetector.isPaused() && noFling) { cancelAnimations(); @@ -298,7 +293,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, overviewAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - onAnimationToStateCompleted(OVERVIEW, logAction); + onAnimationToStateCompleted(OVERVIEW); } }); overviewAnim.start(); @@ -393,7 +388,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, } nonOverviewAnim.setDuration(Math.max(xDuration, yDuration)); - mNonOverviewAnim.setEndAction(() -> onAnimationToStateCompleted(targetState, logAction)); + mNonOverviewAnim.setEndAction(() -> onAnimationToStateCompleted(targetState)); cancelAnimations(); xOverviewAnim.start(); @@ -401,27 +396,17 @@ public class NoButtonQuickSwitchTouchController implements TouchController, nonOverviewAnim.start(); } - private void onAnimationToStateCompleted(LauncherState targetState, int logAction) { - mLauncher.getUserEventDispatcher().logStateChangeAction(logAction, - getDirectionForLog(), mSwipeDetector.getDownX(), mSwipeDetector.getDownY(), - LauncherLogProto.ContainerType.NAVBAR, - mStartState.containerType, - targetState.containerType, - mLauncher.getWorkspace().getCurrentPage()); + private void onAnimationToStateCompleted(LauncherState targetState) { mLauncher.getStatsLogManager().logger() .withSrcState(LAUNCHER_STATE_HOME) - .withDstState(StatsLogManager.containerTypeToAtomState(targetState.containerType)) - .log(getLauncherAtomEvent(mStartState.containerType, targetState.containerType, + .withDstState(targetState.statsLogOrdinal) + .log(getLauncherAtomEvent(mStartState.statsLogOrdinal, targetState.statsLogOrdinal, targetState.ordinal > mStartState.ordinal ? LAUNCHER_UNKNOWN_SWIPEUP : LAUNCHER_UNKNOWN_SWIPEDOWN)); mLauncher.getStateManager().goToState(targetState, false, this::clearState); } - private int getDirectionForLog() { - return Utilities.isRtl(mLauncher.getResources()) ? Direction.LEFT : Direction.RIGHT; - } - private void cancelAnimations() { if (mNonOverviewAnim != null) { mNonOverviewAnim.getAnimationPlayer().cancel(); diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java index 90911684ec..45e5e2fb7c 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java @@ -25,7 +25,6 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.Utilities; -import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.quickstep.TouchInteractionService; import com.android.quickstep.views.RecentsView; @@ -73,9 +72,4 @@ public class OverviewToAllAppsTouchController extends PortraitStatesTouchControl } return fromState; } - - @Override - protected int getLogContainerTypeForNormalState(MotionEvent ev) { - return LauncherLogProto.ContainerType.WORKSPACE; - } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java index 059a703075..037d9889fd 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java @@ -48,8 +48,6 @@ import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.AbstractStateChangeTouchController; import com.android.launcher3.touch.SingleAxisSwipeDetector; import com.android.launcher3.uioverrides.states.OverviewState; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TouchInteractionService; import com.android.quickstep.util.LayoutUtils; @@ -172,11 +170,6 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr return fromState; } - @Override - protected int getLogContainerTypeForNormalState(MotionEvent ev) { - return isTouchOverHotseat(mLauncher, ev) ? ContainerType.HOTSEAT : ContainerType.WORKSPACE; - } - private StateAnimationConfig getNormalToOverviewAnimation() { mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR; @@ -285,7 +278,7 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr private void cancelPendingAnim() { if (mPendingAnimation != null) { - mPendingAnimation.finish(false, Touch.SWIPE); + mPendingAnimation.finish(false); mPendingAnimation = null; } } @@ -320,8 +313,8 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr } @Override - protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { - super.onSwipeInteractionCompleted(targetState, logAction); + protected void onSwipeInteractionCompleted(LauncherState targetState) { + super.onSwipeInteractionCompleted(targetState); if (mStartState == NORMAL && targetState == OVERVIEW) { SystemUiProxy.INSTANCE.get(mLauncher).onOverviewShown(true, TAG); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java index c643858e5c..b8c2030852 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java @@ -21,6 +21,7 @@ import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.DEACCEL_2; import static com.android.launcher3.anim.Interpolators.INSTANT; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND; import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; @@ -41,8 +42,6 @@ import com.android.launcher3.Utilities; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.AbstractStateChangeTouchController; import com.android.launcher3.touch.SingleAxisSwipeDetector; -import com.android.launcher3.userevent.nano.LauncherLogProto; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.quickstep.SysUINavigationMode; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.SystemUiProxy; @@ -92,14 +91,14 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll @Override public void onDragStart(boolean start, float startDisplacement) { super.onDragStart(start, startDisplacement); - mStartContainerType = LauncherLogProto.ContainerType.NAVBAR; + mStartContainerType = LAUNCHER_STATE_BACKGROUND; ActivityManagerWrapper.getInstance() .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); } @Override - protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { - super.onSwipeInteractionCompleted(targetState, logAction); + protected void onSwipeInteractionCompleted(LauncherState targetState) { + super.onSwipeInteractionCompleted(targetState); } @Override @@ -153,14 +152,4 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll protected float getShiftRange() { return mLauncher.getDeviceProfile().widthPx / 2f; } - - @Override - protected int getLogContainerTypeForNormalState(MotionEvent ev) { - return LauncherLogProto.ContainerType.NAVBAR; - } - - @Override - protected int getDirectionForLog() { - return Utilities.isRtl(mLauncher.getResources()) ? Direction.LEFT : Direction.RIGHT; - } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java index 16bd9ed384..fe69c9b87d 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java @@ -15,10 +15,12 @@ */ package com.android.launcher3.uioverrides.touchcontrollers; +import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_UP; -import static android.view.MotionEvent.ACTION_CANCEL; + +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN; import android.graphics.PointF; import android.util.SparseArray; @@ -31,12 +33,9 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.TouchController; - import com.android.quickstep.SystemUiProxy; + import java.io.PrintWriter; /** @@ -133,9 +132,8 @@ public class StatusBarTouchController implements TouchController { int action = ev.getAction(); if (action == ACTION_UP || action == ACTION_CANCEL) { dispatchTouchEvent(ev); - mLauncher.getUserEventDispatcher().logActionOnContainer(action == ACTION_UP ? - Touch.FLING : Touch.SWIPE, Direction.DOWN, ContainerType.WORKSPACE, - mLauncher.getWorkspace().getCurrentPage()); + mLauncher.getStatsLogManager().logger() + .log(LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN); setWindowSlippery(false); return true; } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java index df6194d4b2..186caf6dc1 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java @@ -36,7 +36,6 @@ import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.touch.BaseSwipeDetector; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.touch.SingleAxisSwipeDetector; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.FlingBlockCheck; import com.android.launcher3.util.TouchController; import com.android.launcher3.views.BaseDragLayer; @@ -203,7 +202,7 @@ public abstract class TaskViewTouchController mCurrentAnimation.setPlayFraction(0); } if (mPendingAnimation != null) { - mPendingAnimation.finish(false, Touch.SWIPE); + mPendingAnimation.finish(false); mPendingAnimation = null; } @@ -285,7 +284,6 @@ public abstract class TaskViewTouchController public void onDragEnd(float velocity) { boolean fling = mDetector.isFling(velocity); final boolean goingToEnd; - final int logAction; boolean blockedFling = fling && mFlingBlockCheck.isBlocked(); if (blockedFling) { fling = false; @@ -294,11 +292,9 @@ public abstract class TaskViewTouchController float progress = mCurrentAnimation.getProgressFraction(); float interpolatedProgress = mCurrentAnimation.getInterpolatedProgress(); if (fling) { - logAction = Touch.FLING; boolean goingUp = orientationHandler.isGoingUp(velocity, mIsRtl); goingToEnd = goingUp == mCurrentAnimationIsGoingUp; } else { - logAction = Touch.SWIPE; goingToEnd = interpolatedProgress > SUCCESS_TRANSITION_PROGRESS; } long animationDuration = BaseSwipeDetector.calculateDuration( @@ -307,14 +303,14 @@ public abstract class TaskViewTouchController animationDuration *= LauncherAnimUtils.blockedFlingDurationFactor(velocity); } - mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd, logAction)); + mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd)); mCurrentAnimation.startWithVelocity(mActivity, goingToEnd, velocity, mEndDisplacement, animationDuration); } - private void onCurrentAnimationEnd(boolean wasSuccess, int logAction) { + private void onCurrentAnimationEnd(boolean wasSuccess) { if (mPendingAnimation != null) { - mPendingAnimation.finish(wasSuccess, logAction); + mPendingAnimation.finish(wasSuccess); mPendingAnimation = null; } clearState(); @@ -326,7 +322,7 @@ public abstract class TaskViewTouchController mTaskBeingDragged = null; mCurrentAnimation = null; if (mPendingAnimation != null) { - mPendingAnimation.finish(false, Touch.SWIPE); + mPendingAnimation.finish(false); mPendingAnimation = null; } } diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 22e6755eb1..6774433a1f 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -75,12 +75,8 @@ import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager.StatsLogger; -import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.testing.TestProtocol; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.TraceHelper; import com.android.launcher3.util.VibratorWrapper; import com.android.launcher3.util.WindowBounds; @@ -219,8 +215,7 @@ public abstract class AbsSwipeUpHandler, Q extends private boolean mPassedOverviewThreshold; private boolean mGestureStarted; - private int mLogAction = Touch.SWIPE; - private int mLogDirection = Direction.UP; + private boolean mLogDirectionUpOrLeft = true; private PointF mDownPos; private boolean mIsLikelyToStartNewTask; @@ -745,7 +740,6 @@ public abstract class AbsSwipeUpHandler, Q extends public void onGestureCancelled() { updateDisplacement(0); mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED); - mLogAction = Touch.SWIPE_NOOP; handleNormalGestureEnd(0, false, new PointF(), true /* isCancel */); } @@ -761,13 +755,11 @@ public abstract class AbsSwipeUpHandler, Q extends boolean isFling = mGestureStarted && !mIsMotionPaused && Math.abs(endVelocity) > flingThreshold; mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED); - - mLogAction = isFling ? Touch.FLING : Touch.SWIPE; boolean isVelocityVertical = Math.abs(velocity.y) > Math.abs(velocity.x); if (isVelocityVertical) { - mLogDirection = velocity.y < 0 ? Direction.UP : Direction.DOWN; + mLogDirectionUpOrLeft = velocity.y < 0; } else { - mLogDirection = velocity.x < 0 ? Direction.LEFT : Direction.RIGHT; + mLogDirectionUpOrLeft = velocity.x < 0; } mDownPos = downPos; handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */); @@ -979,8 +971,7 @@ public abstract class AbsSwipeUpHandler, Q extends break; case LAST_TASK: case NEW_TASK: - event = (mLogDirection == Direction.LEFT) - ? LAUNCHER_QUICKSWITCH_LEFT + event = mLogDirectionUpOrLeft ? LAUNCHER_QUICKSWITCH_LEFT : LAUNCHER_QUICKSWITCH_RIGHT; break; default: @@ -988,12 +979,10 @@ public abstract class AbsSwipeUpHandler, Q extends } StatsLogger logger = StatsLogManager.newInstance(mContext).logger() .withSrcState(LAUNCHER_STATE_BACKGROUND) - .withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType)); + .withDstState(endTarget.containerType); if (targetTask != null) { logger.withItemInfo(targetTask.getItemInfo()); } - logger.log(event); - DeviceProfile dp = mDp; if (dp == null || mDownPos == null) { @@ -1003,12 +992,8 @@ public abstract class AbsSwipeUpHandler, Q extends int pageIndex = endTarget == LAST_TASK ? LOG_NO_OP_PAGE_INDEX : mRecentsView.getNextPage(); - UserEventDispatcher.newInstance(mContext).logStateChangeAction( - mLogAction, mLogDirection, - (int) mDownPos.x, (int) mDownPos.y, - ContainerType.NAVBAR, ContainerType.APP, - endTarget.containerType, - pageIndex); + // TODO: set correct container using the pageIndex + logger.log(event); } /** Animates to the given progress, where 0 is the current app and 1 is overview. */ diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index 8b108ac299..d35e270dd5 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -152,11 +152,6 @@ public abstract class BaseActivityInterface mAnimationProvider; private final long mToggleClickedTime = SystemClock.uptimeMillis(); - private boolean mUserEventLogged; private ActivityInitListener mListener; public RecentsActivityCommand() { @@ -212,13 +210,6 @@ public class OverviewCommandHelper { private boolean onActivityReady(Boolean wasVisible) { final T activity = mActivityInterface.getCreatedActivity(); - if (!mUserEventLogged) { - activity.getUserEventDispatcher().logActionCommand( - LauncherLogProto.Action.Command.RECENTS_BUTTON, - mActivityInterface.getContainerType(), - LauncherLogProto.ContainerType.TASKSWITCHER); - mUserEventLogged = true; - } return mAnimationProvider.onActivityReady(activity, wasVisible); } diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index 6f2f9fb523..0e32c95199 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -118,7 +118,6 @@ public final class RecentsActivity extends StatefulActivity { * etc.) */ protected void onHandleConfigChanged() { - mUserEventDispatcher = null; initDeviceProfile(); AbstractFloatingView.closeOpenViews(this, true, diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java index 2b55b805c6..65bb0f35d1 100644 --- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java +++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java @@ -21,7 +21,6 @@ import static android.view.Display.DEFAULT_DISPLAY; import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SELECTIONS; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP; -import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP; import android.app.Activity; import android.app.ActivityOptions; @@ -39,7 +38,6 @@ import com.android.launcher3.logging.StatsLogManager.LauncherEvent; import com.android.launcher3.model.WellbeingModel; import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.popup.SystemShortcut.AppInfo; -import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.Executors; import com.android.launcher3.util.InstantAppResolver; import com.android.quickstep.views.RecentsView; @@ -228,8 +226,6 @@ public interface TaskShortcutFactory { @Override protected boolean onActivityStarted(BaseDraggingActivity activity) { - activity.getUserEventDispatcher().logActionOnControl(TAP, - LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET); return true; } }; diff --git a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java index 89e6931ed9..580e4ec807 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java @@ -25,12 +25,6 @@ import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_UP; import static com.android.launcher3.Utilities.squaredHypot; -import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPLEFT; -import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPRIGHT; -import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.FLING; -import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE; -import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE_NOOP; -import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.NAVBAR; import android.animation.ValueAnimator; import android.content.Context; @@ -47,7 +41,6 @@ import android.view.ViewConfiguration; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; -import com.android.launcher3.logging.UserEventDispatcher; import com.android.quickstep.BaseActivityInterface; import com.android.quickstep.GestureState; import com.android.quickstep.InputConsumer; @@ -80,7 +73,6 @@ public class AssistantInputConsumer extends DelegateInputConsumer { private float mTimeFraction; private long mDragTime; private float mLastProgress; - private int mDirection; private BaseActivityInterface mActivityInterface; private final float mDragDistThreshold; @@ -197,8 +189,6 @@ public class AssistantInputConsumer extends DelegateInputConsumer { if (mState != STATE_DELEGATE_ACTIVE && !mLaunchedAssistant) { ValueAnimator animator = ValueAnimator.ofFloat(mLastProgress, 0) .setDuration(RETRACT_ANIMATION_DURATION_MS); - UserEventDispatcher.newInstance(mContext).logActionOnContainer( - SWIPE_NOOP, mDirection, NAVBAR); animator.addUpdateListener(valueAnimator -> { float progress = (float) valueAnimator.getAnimatedValue(); SystemUiProxy.INSTANCE.get(mContext).onAssistantProgress(progress); @@ -223,7 +213,7 @@ public class AssistantInputConsumer extends DelegateInputConsumer { mLastProgress = Math.min(mDistance * 1f / mDragDistThreshold, 1) * mTimeFraction; if (mDistance >= mDragDistThreshold && mTimeFraction >= 1) { SystemUiProxy.INSTANCE.get(mContext).onAssistantGestureCompletion(0); - startAssistantInternal(SWIPE); + startAssistantInternal(); Bundle args = new Bundle(); args.putInt(OPA_BUNDLE_TRIGGER, OPA_BUNDLE_TRIGGER_DIAG_SWIPE_GESTURE); @@ -236,10 +226,7 @@ public class AssistantInputConsumer extends DelegateInputConsumer { } } - private void startAssistantInternal(int gestureType) { - UserEventDispatcher.newInstance(mContext) - .logActionOnContainer(gestureType, mDirection, NAVBAR); - + private void startAssistantInternal() { BaseDraggingActivity launcherActivity = mActivityInterface.getCreatedActivity(); if (launcherActivity != null) { launcherActivity.getRootView().performHapticFeedback( @@ -253,7 +240,6 @@ public class AssistantInputConsumer extends DelegateInputConsumer { */ private boolean isValidAssistantGestureAngle(float deltaX, float deltaY) { float angle = (float) Math.toDegrees(Math.atan2(deltaY, deltaX)); - mDirection = angle > 90 ? UPLEFT : UPRIGHT; // normalize so that angle is measured clockwise from horizontal in the bottom right corner // and counterclockwise from horizontal in the bottom left corner @@ -272,7 +258,7 @@ public class AssistantInputConsumer extends DelegateInputConsumer { mLastProgress = 1; SystemUiProxy.INSTANCE.get(mContext).onAssistantGestureCompletion( (float) Math.sqrt(velocityX * velocityX + velocityY * velocityY)); - startAssistantInternal(FLING); + startAssistantInternal(); Bundle args = new Bundle(); args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_GESTURE); diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java index 1c77a0593d..924b32c015 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java @@ -15,6 +15,7 @@ */ package com.android.quickstep.inputconsumers; +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_HOME_GESTURE; @@ -27,9 +28,6 @@ import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.TestProtocol; -import com.android.launcher3.userevent.nano.LauncherLogProto; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.quickstep.GestureState; import com.android.quickstep.InputConsumer; import com.android.quickstep.RecentsAnimationDeviceState; @@ -82,17 +80,12 @@ public class OverviewWithoutFocusInputConsumer implements InputConsumer, mContext.startActivity(mGestureState.getHomeIntent()); ActiveGestureLog.INSTANCE.addLog("startQuickstep"); BaseActivity activity = BaseDraggingActivity.fromContext(mContext); - int pageIndex = -1; // This number doesn't reflect workspace page index. - // It only indicates that launcher client screen was shown. - int containerType = (mGestureState != null && mGestureState.getEndTarget() != null) + int state = (mGestureState != null && mGestureState.getEndTarget() != null) ? mGestureState.getEndTarget().containerType - : LauncherLogProto.ContainerType.WORKSPACE; - activity.getUserEventDispatcher().logActionOnContainer( - wasFling ? Touch.FLING : Touch.SWIPE, Direction.UP, containerType, pageIndex); - activity.getUserEventDispatcher().setPreviousHomeGesture(true); + : LAUNCHER_STATE_HOME; activity.getStatsLogManager().logger() - .withSrcState(LAUNCHER_STATE_HOME) - .withDstState(LAUNCHER_STATE_HOME) + .withSrcState(LAUNCHER_STATE_BACKGROUND) + .withDstState(state) .withContainerInfo(LauncherAtom.ContainerInfo.newBuilder() .setWorkspace( LauncherAtom.WorkspaceContainer.newBuilder() diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java index df9b0cf435..de44e07bae 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java +++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java @@ -23,7 +23,6 @@ import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; -import static com.android.launcher3.logging.LoggerUtils.extractObjectNameAndAddress; import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS; @@ -72,6 +71,7 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre private static final String TAG = "RecentsOrientedState"; private static final boolean DEBUG = false; + private static final String DELIMITER_DOT = "\\."; private ContentObserver mSystemAutoRotateObserver = new ContentObserver(new Handler()) { @Override @@ -534,4 +534,13 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre ? idp.landscapeProfile : idp.portraitProfile; } + + /** + * String conversion for only the helpful parts of {@link Object#toString()} method + * @param stringToExtract "foo.bar.baz.MyObject@1234" + * @return "MyObject@1234" + */ + private static String extractObjectNameAndAddress(String stringToExtract) { + return stringToExtract.substring(stringToExtract.lastIndexOf(DELIMITER_DOT)); + } } diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java index b06d4bc355..95bde801bf 100644 --- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java +++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java @@ -42,7 +42,6 @@ import androidx.annotation.StringRes; import com.android.launcher3.BaseActivity; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; -import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.systemui.shared.recents.model.Task; import java.time.Duration; @@ -217,8 +216,8 @@ public final class DigitalWellBeingToast { view, 0, 0, view.getWidth(), view.getHeight()); activity.startActivity(intent, options.toBundle()); - activity.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP, - LauncherLogProto.ControlType.APP_USAGE_SETTINGS, view); + + // TODO: add WW logging on the app usage settings click. } catch (ActivityNotFoundException e) { Log.e(TAG, "Failed to open app usage settings for task " + mTask.getTopComponent().getPackageName(), e); diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 0d1dd22ba5..4bfa4da42a 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -35,12 +35,11 @@ import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN; import static com.android.launcher3.statehandlers.DepthController.DEPTH; import static com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS; -import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP; -import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW; import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId; @@ -108,7 +107,6 @@ import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.touch.PagedOrientationHandler.CurveProperties; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.DynamicResource; import com.android.launcher3.util.MultiValueAlpha; @@ -1463,7 +1461,7 @@ public abstract class RecentsView extends PagedView public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView, boolean shouldRemoveTask, long duration) { if (mPendingAnimation != null) { - mPendingAnimation.finish(false, Touch.SWIPE); + mPendingAnimation.finish(false); } PendingAnimation anim = new PendingAnimation(duration); @@ -1625,7 +1623,7 @@ public abstract class RecentsView extends PagedView protected void runDismissAnimation(PendingAnimation pendingAnim) { AnimatorPlaybackController controller = pendingAnim.createPlaybackController(); controller.dispatchOnStart(); - controller.setEndAction(() -> pendingAnim.finish(true, Touch.SWIPE)); + controller.setEndAction(() -> pendingAnim.finish(true)); controller.getAnimationPlayer().setInterpolator(FAST_OUT_SLOW_IN); controller.start(); } @@ -1638,7 +1636,7 @@ public abstract class RecentsView extends PagedView @SuppressWarnings("unused") private void dismissAllTasks(View view) { runDismissAnimation(createAllTasksDismissAnimation(DISMISS_TASK_DURATION)); - mActivity.getUserEventDispatcher().logActionOnControl(TAP, CLEAR_ALL_BUTTON); + mActivity.getStatsLogManager().logger().log(LAUNCHER_TASK_CLEAR_ALL); } private void dismissCurrentTask() { diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 6a2ab5a304..034d9fb7f7 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -73,15 +73,11 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.PendingAnimation; -import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.PagedOrientationHandler; -import com.android.launcher3.userevent.nano.LauncherLogProto; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.TransformingTouchDelegate; import com.android.launcher3.util.ViewPool.Reusable; @@ -368,7 +364,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { this, RECENTS_LAUNCH_DURATION, TOUCH_RESPONSE_INTERPOLATOR); AnimatorPlaybackController currentAnimation = pendingAnimation.createPlaybackController(); currentAnimation.setEndAction(() -> { - pendingAnimation.finish(true, Touch.SWIPE); + pendingAnimation.finish(true); launchTask(false); }); return currentAnimation; @@ -483,15 +479,13 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } } - private boolean showTaskMenu(int action) { + private boolean showTaskMenu() { if (!getRecentsView().isClearAllHidden()) { getRecentsView().snapToPage(getRecentsView().indexOfChild(this)); } else { mMenuView = TaskMenuView.showForTask(this); mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo()) .log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS); - UserEventDispatcher.newInstance(getContext()).logActionOnItem(action, Direction.NONE, - LauncherLogProto.ItemType.TASK_ICON); if (mMenuView != null) { mMenuView.addOnAttachStateChangeListener(mTaskMenuStateListener); } @@ -502,10 +496,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private void setIcon(Drawable icon) { if (icon != null) { mIconView.setDrawable(icon); - mIconView.setOnClickListener(v -> showTaskMenu(Touch.TAP)); + mIconView.setOnClickListener(v -> showTaskMenu()); mIconView.setOnLongClickListener(v -> { requestDisallowInterceptTouchEvent(true); - return showTaskMenu(Touch.LONGPRESS); + return showTaskMenu(); }); } else { mIconView.setDrawable(null); diff --git a/res/values/config.xml b/res/values/config.xml index 325b62f9dc..46b8c23a62 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -59,7 +59,6 @@ true - diff --git a/robolectric_tests/src/com/android/launcher3/secondarydisplay/SDWorkModeTest.java b/robolectric_tests/src/com/android/launcher3/secondarydisplay/SDWorkModeTest.java index 0ca5ce6f44..baae2a6a80 100644 --- a/robolectric_tests/src/com/android/launcher3/secondarydisplay/SDWorkModeTest.java +++ b/robolectric_tests/src/com/android/launcher3/secondarydisplay/SDWorkModeTest.java @@ -21,7 +21,6 @@ import static com.android.launcher3.util.Preconditions.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; import android.content.Context; import android.os.UserManager; @@ -30,8 +29,6 @@ import android.provider.Settings; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.allapps.AllAppsPagedView; import com.android.launcher3.allapps.AllAppsRecyclerView; -import com.android.launcher3.logging.UserEventDispatcher; -import com.android.launcher3.shadows.ShadowOverrides; import com.android.launcher3.util.LauncherLayoutBuilder; import com.android.launcher3.util.LauncherModelHelper; @@ -69,8 +66,6 @@ public class SDWorkModeTest { mModelHelper = new LauncherModelHelper(); mTargetContext = RuntimeEnvironment.application; mIdp = InvariantDeviceProfile.INSTANCE.get(mTargetContext); - ShadowOverrides.setProvider(UserEventDispatcher.class, - c -> mock(UserEventDispatcher.class)); Settings.Global.putFloat(mTargetContext.getContentResolver(), Settings.Global.WINDOW_ANIMATION_SCALE, 0); diff --git a/robolectric_tests/src/com/android/launcher3/ui/LauncherUIScrollTest.java b/robolectric_tests/src/com/android/launcher3/ui/LauncherUIScrollTest.java index d330d10133..957ae77eee 100644 --- a/robolectric_tests/src/com/android/launcher3/ui/LauncherUIScrollTest.java +++ b/robolectric_tests/src/com/android/launcher3/ui/LauncherUIScrollTest.java @@ -20,7 +20,6 @@ import static com.android.launcher3.util.LauncherUIHelper.doLayout; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import static org.mockito.Mockito.mock; import android.content.Context; import android.os.SystemClock; @@ -36,8 +35,6 @@ import com.android.launcher3.LauncherState; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.FolderPagedView; -import com.android.launcher3.logging.UserEventDispatcher; -import com.android.launcher3.shadows.ShadowOverrides; import com.android.launcher3.util.LauncherLayoutBuilder; import com.android.launcher3.util.LauncherLayoutBuilder.FolderBuilder; import com.android.launcher3.util.LauncherModelHelper; @@ -70,8 +67,6 @@ public class LauncherUIScrollTest { mModelHelper = new LauncherModelHelper(); mTargetContext = RuntimeEnvironment.application; mIdp = InvariantDeviceProfile.INSTANCE.get(mTargetContext); - ShadowOverrides.setProvider(UserEventDispatcher.class, - c -> mock(UserEventDispatcher.class)); Settings.Global.putFloat(mTargetContext.getContentResolver(), Settings.Global.WINDOW_ANIMATION_SCALE, 0); diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java index 310c306f19..5e50e278f0 100644 --- a/src/com/android/launcher3/BaseActivity.java +++ b/src/com/android/launcher3/BaseActivity.java @@ -37,8 +37,6 @@ import androidx.annotation.IntDef; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.logging.StatsLogManager; -import com.android.launcher3.logging.UserEventDispatcher; -import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.ViewCache; import com.android.launcher3.views.ActivityContext; @@ -82,7 +80,6 @@ public abstract class BaseActivity extends Activity implements ActivityContext { new ArrayList<>(); protected DeviceProfile mDeviceProfile; - protected UserEventDispatcher mUserEventDispatcher; protected StatsLogManager mStatsLogManager; protected SystemUiController mSystemUiController; @@ -144,8 +141,6 @@ public abstract class BaseActivity extends Activity implements ActivityContext { return mDeviceProfile; } - public void modifyUserEvent(LauncherLogProto.LauncherEvent event) {} - public final StatsLogManager getStatsLogManager() { if (mStatsLogManager == null) { mStatsLogManager = StatsLogManager.newInstance(this); @@ -153,13 +148,6 @@ public abstract class BaseActivity extends Activity implements ActivityContext { return mStatsLogManager; } - public final UserEventDispatcher getUserEventDispatcher() { - if (mUserEventDispatcher == null) { - mUserEventDispatcher = UserEventDispatcher.newInstance(this); - } - return mUserEventDispatcher; - } - public SystemUiController getSystemUiController() { if (mSystemUiController == null) { mSystemUiController = new SystemUiController(getWindow()); diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java index 09827d664b..df005e6357 100644 --- a/src/com/android/launcher3/ButtonDropTarget.java +++ b/src/com/android/launcher3/ButtonDropTarget.java @@ -47,7 +47,6 @@ import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import com.android.launcher3.util.Themes; import com.android.launcher3.util.Thunk; @@ -395,6 +394,4 @@ public abstract class ButtonDropTarget extends TextView TextUtils.TruncateAt.END); return !mText.equals(displayedText); } - - public abstract Target getDropTargetForLogging(); } diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java index 28574972ad..cc119c9361 100644 --- a/src/com/android/launcher3/DeleteDropTarget.java +++ b/src/com/android/launcher3/DeleteDropTarget.java @@ -18,8 +18,7 @@ package com.android.launcher3; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_CANCEL; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_REMOVE; -import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP; -import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.UNDO; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNDO; import android.content.Context; import android.text.TextUtils; @@ -28,22 +27,19 @@ import android.view.View; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.dragndrop.DragOptions; -import com.android.launcher3.logging.LoggerUtils; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.ModelWriter; import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; -import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; -import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import com.android.launcher3.views.Snackbar; public class DeleteDropTarget extends ButtonDropTarget { private final StatsLogManager mStatsLogManager; - private int mControlType = ControlType.DEFAULT_CONTROLTYPE; + private StatsLogManager.LauncherEvent mLauncherEvent; public DeleteDropTarget(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -115,8 +111,8 @@ public class DeleteDropTarget extends ButtonDropTarget { * Set mControlType depending on the drag item. */ private void setControlTypeBasedOnDragSource(ItemInfo item) { - mControlType = item.id != ItemInfo.NO_ID ? ControlType.REMOVE_TARGET - : ControlType.CANCEL_TARGET; + mLauncherEvent = item.id != ItemInfo.NO_ID ? LAUNCHER_ITEM_DROPPED_ON_REMOVE + : LAUNCHER_ITEM_DROPPED_ON_CANCEL; } @Override @@ -127,8 +123,7 @@ public class DeleteDropTarget extends ButtonDropTarget { } super.onDrop(d, options); mStatsLogManager.logger().withInstanceId(d.logInstanceId) - .log(mControlType == ControlType.REMOVE_TARGET ? LAUNCHER_ITEM_DROPPED_ON_REMOVE - : LAUNCHER_ITEM_DROPPED_ON_CANCEL); + .log(mLauncherEvent); } @Override @@ -141,7 +136,7 @@ public class DeleteDropTarget extends ButtonDropTarget { Runnable onUndoClicked = () -> { mLauncher.setPageToBindSynchronously(itemPage); modelWriter.abortDelete(); - mLauncher.getUserEventDispatcher().logActionOnControl(TAP, UNDO); + mLauncher.getStatsLogManager().logger().log(LAUNCHER_UNDO); }; Snackbar.show(mLauncher, R.string.item_removed, R.string.undo, modelWriter::commitDelete, onUndoClicked); @@ -161,11 +156,4 @@ public class DeleteDropTarget extends ButtonDropTarget { mLauncher.getDragLayer() .announceForAccessibility(getContext().getString(R.string.item_removed)); } - - @Override - public Target getDropTargetForLogging() { - Target t = LoggerUtils.newTarget(Target.Type.CONTROL); - t.controlType = mControlType; - return t; - } } diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index 51f3819460..6547b53940 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -16,8 +16,6 @@ package com.android.launcher3; -import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; - import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; @@ -27,14 +25,10 @@ import android.view.ViewDebug; import android.view.ViewGroup; import android.widget.FrameLayout; -import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider; -import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.userevent.nano.LauncherLogProto; -import com.android.launcher3.userevent.nano.LauncherLogProto.Target; - -import java.util.ArrayList; - -public class Hotseat extends CellLayout implements LogContainerProvider, Insettable { +/** + * View class that represents the bottom row of the home screen. + */ +public class Hotseat extends CellLayout implements Insettable { @ViewDebug.ExportedProperty(category = "launcher") private boolean mHasVerticalHotseat; @@ -78,15 +72,6 @@ public class Hotseat extends CellLayout implements LogContainerProvider, Insetta } } - @Override - public void fillInLogContainerData(ItemInfo childInfo, Target child, - ArrayList parents) { - child.rank = childInfo.rank; - child.gridX = childInfo.cellX; - child.gridY = childInfo.cellY; - parents.add(newContainerTarget(LauncherLogProto.ContainerType.HOTSEAT)); - } - @Override public void setInsets(Rect insets) { FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 1cf2e89e44..4b75a33fc1 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -37,11 +37,10 @@ import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.SPRING_LOADED; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD; -import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; 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_ONRESUME; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONSTOP; -import static com.android.launcher3.logging.StatsLogManager.containerTypeToAtomState; import static com.android.launcher3.model.ItemInstallQueue.FLAG_ACTIVITY_PAUSED; import static com.android.launcher3.model.ItemInstallQueue.FLAG_DRAG_AND_DROP; import static com.android.launcher3.model.ItemInstallQueue.FLAG_LOADER_RUNNING; @@ -127,7 +126,6 @@ import com.android.launcher3.keyboard.ViewGroupFocusHelper; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logging.FileLog; import com.android.launcher3.logging.StatsLogManager; -import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.ItemInstallQueue; import com.android.launcher3.model.ModelUtils; @@ -155,9 +153,6 @@ import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.AllAppsSwipeController; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; -import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import com.android.launcher3.util.ActivityResultInfo; import com.android.launcher3.util.ActivityTracker; import com.android.launcher3.util.ComponentKey; @@ -561,7 +556,6 @@ public class Launcher extends StatefulActivity implements Launche } private void onIdpChanged(InvariantDeviceProfile idp) { - mUserEventDispatcher = null; initDeviceProfile(idp); dispatchDeviceProfileChanged(); @@ -917,7 +911,7 @@ public class Launcher extends StatefulActivity implements Launche mOverlayManager.onActivityStopped(this); } - logStopAndResume(Action.Command.STOP); + logStopAndResume(false /* isResume */); mAppWidgetHost.setListenIfResumed(false); NotificationListener.removeNotificationsChangedListener(); } @@ -939,7 +933,7 @@ public class Launcher extends StatefulActivity implements Launche @Override @CallSuper protected void onDeferredResumed() { - logStopAndResume(Action.Command.RESUME); + logStopAndResume(true /* isResume */); // Process any items that were added while Launcher was away. ItemInstallQueue.INSTANCE.get(this) @@ -956,32 +950,28 @@ public class Launcher extends StatefulActivity implements Launche protected void handlePendingActivityRequest() { } - private void logStopAndResume(int command) { + private void logStopAndResume(boolean isResume) { if (mPendingExecutor != null) return; int pageIndex = mWorkspace.isOverlayShown() ? -1 : mWorkspace.getCurrentPage(); - int containerType = mStateManager.getState().containerType; + int statsLogOrdinal = mStateManager.getState().statsLogOrdinal; StatsLogManager.EventEnum event; StatsLogManager.StatsLogger logger = getStatsLogManager().logger(); - if (command == Action.Command.RESUME) { + if (isResume) { logger.withSrcState(LAUNCHER_STATE_BACKGROUND) - .withDstState(containerTypeToAtomState(mStateManager.getState().containerType)); + .withDstState(mStateManager.getState().statsLogOrdinal); event = LAUNCHER_ONRESUME; } else { /* command == Action.Command.STOP */ - logger.withSrcState(containerTypeToAtomState(mStateManager.getState().containerType)) + logger.withSrcState(mStateManager.getState().statsLogOrdinal) .withDstState(LAUNCHER_STATE_BACKGROUND); event = LAUNCHER_ONSTOP; } - if (containerType == ContainerType.WORKSPACE && mWorkspace != null) { - getUserEventDispatcher().logActionCommand(command, - containerType, -1, pageIndex); + if (statsLogOrdinal == LAUNCHER_STATE_HOME && mWorkspace != null) { logger.withContainerInfo(LauncherAtom.ContainerInfo.newBuilder() .setWorkspace( LauncherAtom.WorkspaceContainer.newBuilder() .setPageIndex(pageIndex)).build()); - } else { - getUserEventDispatcher().logActionCommand(command, containerType, -1); } logger.log(event); } @@ -1483,11 +1473,6 @@ public class Launcher extends StatefulActivity implements Launche } // Handle HOME_INTENT - UserEventDispatcher ued = getUserEventDispatcher(); - Target target = newContainerTarget(mStateManager.getState().containerType); - target.pageIndex = mWorkspace.getCurrentPage(); - ued.logActionCommand(Action.Command.HOME_INTENT, target, - newContainerTarget(ContainerType.WORKSPACE)); hideKeyboard(); if (mLauncherCallbacks != null) { diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index b6bc500a58..eba0ac9633 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -16,6 +16,7 @@ package com.android.launcher3; import static com.android.launcher3.anim.Interpolators.ACCEL_2; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME; import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL; @@ -35,7 +36,6 @@ import com.android.launcher3.states.SpringLoadedState; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.uioverrides.states.AllAppsState; import com.android.launcher3.uioverrides.states.OverviewState; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import java.util.Arrays; @@ -97,7 +97,7 @@ public abstract class LauncherState implements BaseState { * TODO: Create a separate class for NORMAL state. */ public static final LauncherState NORMAL = new LauncherState(NORMAL_STATE_ORDINAL, - ContainerType.WORKSPACE, + LAUNCHER_STATE_HOME, FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON | FLAG_HAS_SYS_UI_SCRIM) { @Override @@ -126,9 +126,9 @@ public abstract class LauncherState implements BaseState { public final int ordinal; /** - * Used for containerType in {@link com.android.launcher3.logging.UserEventDispatcher} + * Used for {@link com.android.launcher3.logging.StatsLogManager} */ - public final int containerType; + public final int statsLogOrdinal; /** * True if the state has overview panel visible. @@ -137,8 +137,8 @@ public abstract class LauncherState implements BaseState { private final int mFlags; - public LauncherState(int id, int containerType, int flags) { - this.containerType = containerType; + public LauncherState(int id, int statsLogOrdinal, int flags) { + this.statsLogOrdinal = statsLogOrdinal; this.mFlags = flags; this.overviewUi = (flags & FLAG_OVERVIEW_UI) != 0; this.ordinal = id; diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java index 2df7f5ad20..92b88e6186 100644 --- a/src/com/android/launcher3/SecondaryDropTarget.java +++ b/src/com/android/launcher3/SecondaryDropTarget.java @@ -37,14 +37,11 @@ import com.android.launcher3.Launcher.OnResumeCallback; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.logging.FileLog; -import com.android.launcher3.logging.LoggerUtils; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager.StatsLogger; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.model.data.LauncherAppWidgetInfo; -import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; -import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.Themes; @@ -134,19 +131,6 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList return mCurrentAccessibilityAction; } - @Override - public Target getDropTargetForLogging() { - Target t = LoggerUtils.newTarget(Target.Type.CONTROL); - if (mCurrentAccessibilityAction == UNINSTALL) { - t.controlType = ControlType.UNINSTALL_TARGET; - } else if (mCurrentAccessibilityAction == DISMISS_PREDICTION) { - t.controlType = ControlType.DISMISS_PREDICTION; - } else { - t.controlType = ControlType.SETTINGS_BUTTON; - } - return t; - } - @Override protected boolean supportsDrop(ItemInfo info) { return supportsAccessibilityDrop(info, getViewUnderDrag(info)); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index e7ded363a2..98328cf8af 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -85,7 +85,6 @@ import com.android.launcher3.icons.BitmapRenderer; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager.LauncherEvent; -import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; @@ -97,8 +96,6 @@ import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.statemanager.StateManager.StateHandler; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.WorkspaceTouchListener; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.Executors; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSparseArrayMap; @@ -1004,8 +1001,6 @@ public class Workspace extends PagedView public void onOverlayScrollChanged(float scroll) { if (Float.compare(scroll, 1f) == 0) { if (!mOverlayShown) { - mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE, - Action.Direction.LEFT, ContainerType.WORKSPACE, 0); mLauncher.getStatsLogManager().logger() .withSrcState(LAUNCHER_STATE_HOME) .withDstState(LAUNCHER_STATE_HOME) @@ -1020,20 +1015,16 @@ public class Workspace extends PagedView // Not announcing the overlay page for accessibility since it announces itself. } else if (Float.compare(scroll, 0f) == 0) { if (mOverlayShown) { - UserEventDispatcher ued = mLauncher.getUserEventDispatcher(); - if (!ued.isPreviousHomeGesture()) { - mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE, - Action.Direction.RIGHT, ContainerType.WORKSPACE, -1); - mLauncher.getStatsLogManager().logger() - .withSrcState(LAUNCHER_STATE_HOME) - .withDstState(LAUNCHER_STATE_HOME) - .withContainerInfo(LauncherAtom.ContainerInfo.newBuilder() - .setWorkspace( - LauncherAtom.WorkspaceContainer.newBuilder() - .setPageIndex(-1)) - .build()) - .log(LAUNCHER_SWIPERIGHT); - } + // TODO: this is logged unnecessarily on home gesture. + mLauncher.getStatsLogManager().logger() + .withSrcState(LAUNCHER_STATE_HOME) + .withDstState(LAUNCHER_STATE_HOME) + .withContainerInfo(LauncherAtom.ContainerInfo.newBuilder() + .setWorkspace( + LauncherAtom.WorkspaceContainer.newBuilder() + .setPageIndex(-1)) + .build()) + .log(LAUNCHER_SWIPERIGHT); } else if (Float.compare(mOverlayTranslation, 0f) != 0) { // When arriving to 0 overscroll from non-zero overscroll, announce page for // accessibility since default announcements were disabled while in overscroll @@ -1124,12 +1115,8 @@ public class Workspace extends PagedView protected void notifyPageSwitchListener(int prevPage) { super.notifyPageSwitchListener(prevPage); if (prevPage != mCurrentPage) { - int swipeDirection = (prevPage < mCurrentPage) - ? Action.Direction.RIGHT : Action.Direction.LEFT; StatsLogManager.EventEnum event = (prevPage < mCurrentPage) ? LAUNCHER_SWIPERIGHT : LAUNCHER_SWIPELEFT; - mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE, - swipeDirection, ContainerType.WORKSPACE, prevPage); mLauncher.getStatsLogManager().logger() .withSrcState(LAUNCHER_STATE_HOME) .withDstState(LAUNCHER_STATE_HOME) diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java index 13a93ff0cc..72b6d94192 100644 --- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java +++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java @@ -19,8 +19,6 @@ import static android.view.View.MeasureSpec.EXACTLY; import static android.view.View.MeasureSpec.UNSPECIFIED; import static android.view.View.MeasureSpec.makeMeasureSpec; -import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; - import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; @@ -38,10 +36,6 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.allapps.AllAppsGridAdapter.AppsGridLayoutManager; -import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider; -import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; -import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import com.android.launcher3.views.RecyclerViewFastScroller; import java.util.ArrayList; @@ -50,7 +44,7 @@ import java.util.List; /** * A RecyclerView with custom fast scroll support for the all apps view. */ -public class AllAppsRecyclerView extends BaseRecyclerView implements LogContainerProvider { +public class AllAppsRecyclerView extends BaseRecyclerView { private AlphabeticalAppsList mApps; private final int mNumAppsPerRow; @@ -176,13 +170,6 @@ public class AllAppsRecyclerView extends BaseRecyclerView implements LogContaine mAutoSizedOverlays.clear(); } - @Override - public void fillInLogContainerData(ItemInfo childInfo, Target child, - ArrayList parents) { - parents.add(newContainerTarget( - getApps().hasFilter() ? ContainerType.SEARCHRESULT : ContainerType.ALLAPPS)); - } - public void onSearchResultsChanged() { // Always scroll the view to the top so the user can see the changed results scrollToTop(); diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java index 14595ca941..0005db88c8 100644 --- a/src/com/android/launcher3/allapps/DiscoveryBounce.java +++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java @@ -18,8 +18,6 @@ package com.android.launcher3.allapps; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; -import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.HOTSEAT; -import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.PREDICTION; import android.animation.Animator; import android.animation.AnimatorInflater; @@ -120,10 +118,10 @@ public class DiscoveryBounce extends AbstractFloatingView { return (type & TYPE_DISCOVERY_BOUNCE) != 0; } - private void show(int containerType) { + private void show() { mIsOpen = true; mLauncher.getDragLayer().addView(this); - mLauncher.getUserEventDispatcher().logActionBounceTip(containerType); + // TODO: add WW log for discovery bounce tip show event. } public static void showForHomeIfNeeded(Launcher launcher) { @@ -146,7 +144,7 @@ public class DiscoveryBounce extends AbstractFloatingView { } onboardingPrefs.incrementEventCount(OnboardingPrefs.HOME_BOUNCE_COUNT); - new DiscoveryBounce(launcher, 0).show(HOTSEAT); + new DiscoveryBounce(launcher, 0).show(); } public static void showForOverviewIfNeeded(Launcher launcher, @@ -179,7 +177,7 @@ public class DiscoveryBounce extends AbstractFloatingView { onboardingPrefs.incrementEventCount(OnboardingPrefs.SHELF_BOUNCE_COUNT); new DiscoveryBounce(launcher, (1 - OVERVIEW.getVerticalProgress(launcher))) - .show(PREDICTION); + .show(); } /** diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java index 53625756b8..6dd316ed60 100644 --- a/src/com/android/launcher3/anim/PendingAnimation.java +++ b/src/com/android/launcher3/anim/PendingAnimation.java @@ -73,9 +73,9 @@ public class PendingAnimation implements PropertySetter { addAnimationHoldersRecur(a, mDuration, springProperty, mAnimHolders); } - public void finish(boolean isSuccess, int logAction) { + public void finish(boolean isSuccess) { for (Consumer listeners : mEndListeners) { - listeners.accept(new EndState(isSuccess, logAction)); + listeners.accept(new EndState(isSuccess)); } mEndListeners.clear(); } @@ -164,7 +164,7 @@ public class PendingAnimation implements PropertySetter { /** * Add a listener of receiving the end state. - * Note that the listeners are called as a result of calling {@link #finish(boolean, int)} + * Note that the listeners are called as a result of calling {@link #finish(boolean)} * and not automatically */ public void addEndListener(Consumer listener) { @@ -173,11 +173,9 @@ public class PendingAnimation implements PropertySetter { public static class EndState { public boolean isSuccess; - public int logAction; - public EndState(boolean isSuccess, int logAction) { + public EndState(boolean isSuccess) { this.isSuccess = isSuccess; - this.logAction = logAction; } } } diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java index 2d625c5373..42e247aa9b 100644 --- a/src/com/android/launcher3/dragndrop/AddItemActivity.java +++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java @@ -16,10 +16,11 @@ package com.android.launcher3.dragndrop; -import static com.android.launcher3.logging.LoggerUtils.newCommandAction; -import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; -import static com.android.launcher3.logging.LoggerUtils.newItemTarget; -import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ADD_EXTERNAL_ITEM_BACK; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ADD_EXTERNAL_ITEM_CANCELLED; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ADD_EXTERNAL_ITEM_DRAGGED; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ADD_EXTERNAL_ITEM_PLACED_AUTOMATICALLY; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ADD_EXTERNAL_ITEM_START; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.annotation.TargetApi; @@ -49,11 +50,10 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetHost; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.R; +import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.ItemInstallQueue; import com.android.launcher3.model.WidgetItem; import com.android.launcher3.pm.PinRequestHelper; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.views.BaseDragLayer; import com.android.launcher3.widget.PendingAddShortcutInfo; @@ -125,7 +125,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener // savedInstanceState is null when the activity is created the first time (i.e., avoids // duplicate logging during rotation) if (savedInstanceState == null) { - logCommand(Action.Command.ENTRY); + logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_START); } } @@ -178,6 +178,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener startActivity(homeIntent, ActivityOptions.makeCustomAnimation(this, 0, android.R.anim.fade_out) .toBundle()); + logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_DRAGGED); mFinishOnPause = true; return false; } @@ -240,7 +241,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener * Called when the cancel button is clicked. */ public void onCancelClick(View v) { - logCommand(Action.Command.CANCEL); + logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_CANCELLED); finish(); } @@ -250,7 +251,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener public void onPlaceAutomaticallyClick(View v) { if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) { ItemInstallQueue.INSTANCE.get(this).queueItem(mRequest.getShortcutInfo()); - logCommand(Action.Command.CONFIRM); + logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_PLACED_AUTOMATICALLY); mRequest.accept(); finish(); return; @@ -274,13 +275,13 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener .queueItem(mRequest.getAppWidgetProviderInfo(this), widgetId); mWidgetOptions.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); mRequest.accept(mWidgetOptions); - logCommand(Action.Command.CONFIRM); + logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_PLACED_AUTOMATICALLY); finish(); } @Override public void onBackPressed() { - logCommand(Action.Command.BACK); + logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_BACK); super.onBackPressed(); } @@ -320,10 +321,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener throw new UnsupportedOperationException(); } - private void logCommand(int command) { - getUserEventDispatcher().dispatchUserEvent(newLauncherEvent( - newCommandAction(command), - newItemTarget(mWidgetCell.getWidgetView(), mInstantAppResolver), - newContainerTarget(ContainerType.PINITEM)), null); + private void logCommand(StatsLogManager.EventEnum command) { + getStatsLogManager().logger().log(command); } } diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index ef666f0acd..1cfe6acf05 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -206,7 +206,6 @@ public class DragController implements DragDriver.EventListener, TouchController } handleMoveEvent(mLastTouch.x, mLastTouch.y); - mLauncher.getUserEventDispatcher().resetActionDurationMillis(); if (!mLauncher.isTouchInProgress() && options.simulatedDndStartPoint == null) { // If it is an internal drag and the touch is already complete, cancel immediately @@ -544,7 +543,6 @@ public class DragController implements DragDriver.EventListener, TouchController } } final View dropTargetAsView = dropTarget instanceof View ? (View) dropTarget : null; - mLauncher.getUserEventDispatcher().logDragNDrop(mDragObject, dropTargetAsView); dispatchDropComplete(dropTargetAsView, accepted); } diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 281598a48b..63fa391d43 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -23,7 +23,6 @@ import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent; import static com.android.launcher3.config.FeatureFlags.ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS; -import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_CONVERTED_TO_ICON; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_LABEL_UPDATED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED; @@ -95,7 +94,6 @@ import com.android.launcher3.model.data.FolderInfo.FolderListener; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pageindicators.PageIndicatorDots; -import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.Executors; import com.android.launcher3.util.Thunk; import com.android.launcher3.views.ClipPathView; @@ -599,15 +597,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo * is played. */ private void animateOpen(List items, int pageNo) { - animateOpen(items, pageNo, false); - } - - /** - * Opens the user folder described by the specified tag. The opening of the folder - * is animated relative to the specified View. If the View is null, no animation - * is played. - */ - private void animateOpen(List items, int pageNo, boolean skipUserEventLog) { Folder openFolder = getOpen(mLauncher); if (openFolder != null && openFolder != this) { // Close any open folder before opening a folder. @@ -657,14 +646,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mState = STATE_OPEN; announceAccessibilityChanges(); - if (!skipUserEventLog) { - mLauncher.getUserEventDispatcher().logActionOnItem( - LauncherLogProto.Action.Touch.TAP, - LauncherLogProto.Action.Direction.NONE, - LauncherLogProto.ItemType.FOLDER_ICON, mInfo.cellX, mInfo.cellY); - } - - mContent.setFocusOnFirstChild(); } }); @@ -1513,7 +1494,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo } statsLogger.log(LAUNCHER_FOLDER_LABEL_UPDATED); - logFolderLabelState(mFromLabelState, toLabelState); mFolderName.dispatchBackKey(); } } @@ -1644,8 +1624,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo return true; } } else { - mLauncher.getUserEventDispatcher().logActionTapOutside( - newContainerTarget(LauncherLogProto.ContainerType.FOLDER)); + // TODO: add ww log if need to gather tap outside to close folder close(true); return true; } @@ -1680,17 +1659,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo return mContent; } - /** - * Logs current folder label info. - * - * @deprecated This method is only used for log validation and soon will be removed. - */ - @Deprecated - public void logFolderLabelState(FromState fromState, ToState toState) { - mLauncher.getUserEventDispatcher() - .logLauncherEvent(mInfo.getFolderLabelStateLauncherEvent(fromState, toState)); - } - /** Returns the height of the current folder's bottom edge from the bottom of the screen. */ private int getHeightFromBottom() { DragLayer.LayoutParams layoutParams = (DragLayer.LayoutParams) getLayoutParams(); diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 32d061cb42..3296eed5ca 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -478,7 +478,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel // event is assumed to be folder creation on the server side. .withEditText(newTitle.toString()) .log(LAUNCHER_FOLDER_AUTO_LABELED); - mFolder.logFolderLabelState(fromState, ToState.TO_SUGGESTION0); } diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java deleted file mode 100644 index cd4f034e83..0000000000 --- a/src/com/android/launcher3/logging/LoggerUtils.java +++ /dev/null @@ -1,190 +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. - */ -package com.android.launcher3.logging; - -import android.util.ArrayMap; -import android.util.SparseArray; -import android.view.View; - -import com.android.launcher3.ButtonDropTarget; -import com.android.launcher3.LauncherSettings; -import com.android.launcher3.model.data.AppInfo; -import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.userevent.nano.LauncherLogExtensions.TargetExtension; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action; -import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType; -import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent; -import com.android.launcher3.userevent.nano.LauncherLogProto.Target; -import com.android.launcher3.util.InstantAppResolver; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.ArrayList; - -/** - * Helper methods for logging. - */ -public class LoggerUtils { - private static final ArrayMap> sNameCache = new ArrayMap<>(); - private static final String UNKNOWN = "UNKNOWN"; - private static final int DEFAULT_PREDICTED_RANK = 10000; - private static final String DELIMITER_DOT = "\\."; - - public static String getFieldName(int value, Class c) { - SparseArray cache; - synchronized (sNameCache) { - cache = sNameCache.get(c); - if (cache == null) { - cache = new SparseArray<>(); - for (Field f : c.getDeclaredFields()) { - if (f.getType() == int.class && Modifier.isStatic(f.getModifiers())) { - try { - f.setAccessible(true); - cache.put(f.getInt(null), f.getName()); - } catch (IllegalAccessException e) { - // Ignore - } - } - } - sNameCache.put(c, cache); - } - } - String result = cache.get(value); - return result != null ? result : UNKNOWN; - } - - public static Target newItemTarget(int itemType) { - Target t = newTarget(Target.Type.ITEM); - t.itemType = itemType; - return t; - } - - public static Target newItemTarget(View v, InstantAppResolver instantAppResolver) { - return (v != null) && (v.getTag() instanceof ItemInfo) - ? newItemTarget((ItemInfo) v.getTag(), instantAppResolver) - : newTarget(Target.Type.ITEM); - } - - public static Target newItemTarget(ItemInfo info, InstantAppResolver instantAppResolver) { - Target t = newTarget(Target.Type.ITEM); - switch (info.itemType) { - case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: - t.itemType = (instantAppResolver != null && info instanceof AppInfo - && instantAppResolver.isInstantApp(((AppInfo) info))) - ? ItemType.WEB_APP - : ItemType.APP_ICON; - t.predictedRank = DEFAULT_PREDICTED_RANK; - break; - case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: - t.itemType = ItemType.SHORTCUT; - t.predictedRank = DEFAULT_PREDICTED_RANK; - break; - case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: - t.itemType = ItemType.FOLDER_ICON; - break; - case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: - t.itemType = ItemType.WIDGET; - break; - case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: - t.itemType = ItemType.DEEPSHORTCUT; - t.predictedRank = DEFAULT_PREDICTED_RANK; - break; - } - return t; - } - - public static Target newDropTarget(View v) { - if (!(v instanceof ButtonDropTarget)) { - return newTarget(Target.Type.CONTAINER); - } - if (v instanceof ButtonDropTarget) { - return ((ButtonDropTarget) v).getDropTargetForLogging(); - } - return newTarget(Target.Type.CONTROL); - } - - public static Target newTarget(int targetType, TargetExtension extension) { - Target t = new Target(); - t.type = targetType; - t.extension = extension; - return t; - } - - public static Target newTarget(int targetType) { - Target t = new Target(); - t.type = targetType; - return t; - } - - public static Target newControlTarget(int controlType) { - Target t = newTarget(Target.Type.CONTROL); - t.controlType = controlType; - return t; - } - - public static Target newContainerTarget(int containerType) { - Target t = newTarget(Target.Type.CONTAINER); - t.containerType = containerType; - return t; - } - - public static Action newAction(int type) { - Action a = new Action(); - a.type = type; - return a; - } - - public static Action newCommandAction(int command) { - Action a = newAction(Action.Type.COMMAND); - a.command = command; - return a; - } - - public static Action newTouchAction(int touch) { - Action a = newAction(Action.Type.TOUCH); - a.touch = touch; - return a; - } - - public static LauncherEvent newLauncherEvent(Action action, Target... srcTargets) { - LauncherEvent event = new LauncherEvent(); - event.srcTarget = srcTargets; - event.action = action; - return event; - } - - /** - * Creates LauncherEvent using Action and ArrayList of Targets - */ - public static LauncherEvent newLauncherEvent(Action action, ArrayList targets) { - Target[] targetsArray = new Target[targets.size()]; - targets.toArray(targetsArray); - return newLauncherEvent(action, targetsArray); - } - - /** - * String conversion for only the helpful parts of {@link Object#toString()} method - * @param stringToExtract "foo.bar.baz.MyObject@1234" - * @return "MyObject@1234" - */ - public static String extractObjectNameAndAddress(String stringToExtract) { - String[] superStringParts = stringToExtract.split(DELIMITER_DOT); - if (superStringParts.length == 0) { - return ""; - } - return superStringParts[superStringParts.length - 1]; - } -} diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index ec1c3ef779..2c5bf320ad 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -27,7 +27,6 @@ import com.android.launcher3.logger.LauncherAtom.ContainerInfo; import com.android.launcher3.logger.LauncherAtom.FromState; import com.android.launcher3.logger.LauncherAtom.ToState; import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.userevent.LauncherLogProto; import com.android.launcher3.util.ResourceBasedOverride; import java.util.List; @@ -51,40 +50,22 @@ public class StatsLogManager implements ResourceBasedOverride { public static final int LAUNCHER_STATE_UNCHANGED = 5; /** - * Returns proper launcher state enum for {@link StatsLogManager}(to be removed during - * UserEventDispatcher cleanup) - */ - public static int containerTypeToAtomState(int containerType) { - switch (containerType) { - case LauncherLogProto.ContainerType.ALLAPPS_VALUE: - return LAUNCHER_STATE_ALLAPPS; - case LauncherLogProto.ContainerType.OVERVIEW_VALUE: - return LAUNCHER_STATE_OVERVIEW; - case LauncherLogProto.ContainerType.WORKSPACE_VALUE: - return LAUNCHER_STATE_HOME; - case LauncherLogProto.ContainerType.APP_VALUE: - return LAUNCHER_STATE_BACKGROUND; - } - return LAUNCHER_STATE_UNSPECIFIED; - } - - /** - * Returns event enum based on the two {@link ContainerType} transition information when swipe + * Returns event enum based on the two state transition information when swipe * gesture happens(to be removed during UserEventDispatcher cleanup). */ - public static EventEnum getLauncherAtomEvent(int startContainerType, - int targetContainerType, EventEnum fallbackEvent) { - if (startContainerType == LauncherLogProto.ContainerType.WORKSPACE.getNumber() - && targetContainerType == LauncherLogProto.ContainerType.WORKSPACE.getNumber()) { + public static EventEnum getLauncherAtomEvent(int startState, + int targetState, EventEnum fallbackEvent) { + if (startState == LAUNCHER_STATE_HOME + && targetState == LAUNCHER_STATE_HOME) { return LAUNCHER_HOME_GESTURE; - } else if (startContainerType != LauncherLogProto.ContainerType.TASKSWITCHER.getNumber() - && targetContainerType == LauncherLogProto.ContainerType.TASKSWITCHER.getNumber()) { + } else if (startState != LAUNCHER_STATE_OVERVIEW + && targetState == LAUNCHER_STATE_OVERVIEW) { return LAUNCHER_OVERVIEW_GESTURE; - } else if (startContainerType != LauncherLogProto.ContainerType.ALLAPPS.getNumber() - && targetContainerType == LauncherLogProto.ContainerType.ALLAPPS.getNumber()) { + } else if (startState != LAUNCHER_STATE_ALLAPPS + && targetState == LAUNCHER_STATE_ALLAPPS) { return LAUNCHER_ALLAPPS_OPEN_UP; - } else if (startContainerType == LauncherLogProto.ContainerType.ALLAPPS.getNumber() - && targetContainerType != LauncherLogProto.ContainerType.ALLAPPS.getNumber()) { + } else if (startState == LAUNCHER_STATE_ALLAPPS + && targetState != LAUNCHER_STATE_ALLAPPS) { return LAUNCHER_ALLAPPS_CLOSE_DOWN; } return fallbackEvent; // TODO fix @@ -322,7 +303,38 @@ public class StatsLogManager implements ResourceBasedOverride { LAUNCHER_FOLDER_CONVERTED_TO_ICON(628), @UiEvent(doc = "A hotseat prediction item was pinned") - LAUNCHER_HOTSEAT_PREDICTION_PINNED(629); + LAUNCHER_HOTSEAT_PREDICTION_PINNED(629), + + @UiEvent(doc = "Activity to add external item was started") + LAUNCHER_ADD_EXTERNAL_ITEM_START(641), + + @UiEvent(doc = "Activity to add external item was cancelled") + LAUNCHER_ADD_EXTERNAL_ITEM_CANCELLED(642), + + @UiEvent(doc = "Activity to add external item was backed out") + LAUNCHER_ADD_EXTERNAL_ITEM_BACK(643), + + @UiEvent(doc = "Item was placed automatically in external item addition flow") + LAUNCHER_ADD_EXTERNAL_ITEM_PLACED_AUTOMATICALLY(644), + + @UiEvent(doc = "Item was dragged in external item addition flow") + LAUNCHER_ADD_EXTERNAL_ITEM_DRAGGED(645), + + @UiEvent(doc = "Undo event was tapped.") + LAUNCHER_UNDO(648), + + @UiEvent(doc = "Task switcher clear all target was tapped.") + LAUNCHER_TASK_CLEAR_ALL(649), + + @UiEvent(doc = "Task preview was long pressed.") + LAUNCHER_TASK_PREVIEW_LONGPRESS(650), + + @UiEvent(doc = "User swiped down on workspace (triggering noti shade to open).") + LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN(651), + + @UiEvent(doc = "Notification dismissed by swiping right.") + LAUNCHER_NOTIFICATION_DISMISSED(652), + ; // ADD MORE diff --git a/src/com/android/launcher3/logging/StatsLogUtils.java b/src/com/android/launcher3/logging/StatsLogUtils.java deleted file mode 100644 index a5cc7ea305..0000000000 --- a/src/com/android/launcher3/logging/StatsLogUtils.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.android.launcher3.logging; - -import android.view.View; -import android.view.ViewParent; - -import androidx.annotation.Nullable; - -import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.userevent.nano.LauncherLogProto.Target; - -import java.util.ArrayList; - -public class StatsLogUtils { - private final static int MAXIMUM_VIEW_HIERARCHY_LEVEL = 5; - - /** - * Implemented by containers to provide a container source for a given child. - */ - public interface LogContainerProvider { - - /** - * Populates parent container targets for an item - */ - void fillInLogContainerData(ItemInfo childInfo, Target child, ArrayList parents); - } - - /** - * Recursively finds the parent of the given child which implements IconLogInfoProvider - */ - public static LogContainerProvider getLaunchProviderRecursive(@Nullable View v) { - ViewParent parent; - if (v != null) { - parent = v.getParent(); - } else { - return null; - } - - // Optimization to only check up to 5 parents. - int count = MAXIMUM_VIEW_HIERARCHY_LEVEL; - while (parent != null && count-- > 0) { - if (parent instanceof LogContainerProvider) { - return (LogContainerProvider) parent; - } else { - parent = parent.getParent(); - } - } - return null; - } -} diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java deleted file mode 100644 index a40cc263db..0000000000 --- a/src/com/android/launcher3/logging/UserEventDispatcher.java +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (C) 2012 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.logging; - -import static com.android.launcher3.logging.LoggerUtils.newAction; -import static com.android.launcher3.logging.LoggerUtils.newCommandAction; -import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; -import static com.android.launcher3.logging.LoggerUtils.newDropTarget; -import static com.android.launcher3.logging.LoggerUtils.newItemTarget; -import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent; -import static com.android.launcher3.logging.LoggerUtils.newTarget; -import static com.android.launcher3.logging.LoggerUtils.newTouchAction; -import static com.android.launcher3.userevent.nano.LauncherLogProto.ItemType; -import static com.android.launcher3.userevent.nano.LauncherLogProto.TipType; - -import static java.util.Optional.ofNullable; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.SystemClock; -import android.util.Log; -import android.view.View; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.launcher3.DropTarget; -import com.android.launcher3.R; -import com.android.launcher3.Utilities; -import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider; -import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.userevent.LauncherLogProto; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action; -import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent; -import com.android.launcher3.userevent.nano.LauncherLogProto.Target; -import com.android.launcher3.util.InstantAppResolver; -import com.android.launcher3.util.LogConfig; -import com.android.launcher3.util.ResourceBasedOverride; - -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.nano.InvalidProtocolBufferNanoException; -import com.google.protobuf.nano.MessageNano; - -import java.util.ArrayList; -import java.util.UUID; - -/** - * Manages the creation of {@link LauncherEvent}. - * To debug this class, execute following command before side loading a new apk. - *

- * $ adb shell setprop log.tag.UserEvent VERBOSE - */ -public class UserEventDispatcher implements ResourceBasedOverride { - - private static final String TAG = "UserEvent"; - private static final boolean IS_VERBOSE = Utilities.isPropertyEnabled(LogConfig.USEREVENT); - private static final String UUID_STORAGE = "uuid"; - - /** - * A factory method for UserEventDispatcher - */ - public static UserEventDispatcher newInstance(Context context) { - SharedPreferences sharedPrefs = Utilities.getDevicePrefs(context); - String uuidStr = sharedPrefs.getString(UUID_STORAGE, null); - if (uuidStr == null) { - uuidStr = UUID.randomUUID().toString(); - sharedPrefs.edit().putString(UUID_STORAGE, uuidStr).apply(); - } - UserEventDispatcher ued = Overrides.getObject(UserEventDispatcher.class, - context.getApplicationContext(), R.string.user_event_dispatcher_class); - ued.mUuidStr = uuidStr; - ued.mInstantAppResolver = InstantAppResolver.newInstance(context); - return ued; - } - - - /** - * Fills in the container data on the given event if the given view is not null. - * - * @return whether container data was added. - */ - private boolean fillLogContainer(@Nullable View v, Target child, - @Nullable ArrayList targets) { - LogContainerProvider firstParent = StatsLogUtils.getLaunchProviderRecursive(v); - if (v == null || !(v.getTag() instanceof ItemInfo) || firstParent == null) { - return false; - } - final ItemInfo itemInfo = (ItemInfo) v.getTag(); - firstParent.fillInLogContainerData(itemInfo, child, targets); - return true; - } - - protected void onFillInLogContainerData(@NonNull ItemInfo itemInfo, @NonNull Target target, - @NonNull ArrayList targets) { - } - - private boolean mSessionStarted; - private long mElapsedContainerMillis; - private long mElapsedSessionMillis; - private long mActionDurationMillis; - private String mUuidStr; - protected InstantAppResolver mInstantAppResolver; - private boolean mAppOrTaskLaunch; - private boolean mPreviousHomeGesture; - - private void fillComponentInfo(Target target, ComponentName cn) { - if (cn != null) { - target.packageNameHash = (mUuidStr + cn.getPackageName()).hashCode(); - target.componentHash = (mUuidStr + cn.flattenToString()).hashCode(); - } - } - - public void logActionCommand(int command, int srcContainerType, int dstContainerType) { - logActionCommand(command, newContainerTarget(srcContainerType), - dstContainerType >= 0 ? newContainerTarget(dstContainerType) : null); - } - - public void logActionCommand(int command, int srcContainerType, int dstContainerType, - int pageIndex) { - Target srcTarget = newContainerTarget(srcContainerType); - srcTarget.pageIndex = pageIndex; - logActionCommand(command, srcTarget, - dstContainerType >= 0 ? newContainerTarget(dstContainerType) : null); - } - - public void logActionCommand(int command, Target srcTarget, Target dstTarget) { - LauncherEvent event = newLauncherEvent(newCommandAction(command), srcTarget); - if (command == Action.Command.STOP) { - if (mAppOrTaskLaunch || !mSessionStarted) { - mSessionStarted = false; - return; - } - } - - if (dstTarget != null) { - event.destTarget = new Target[1]; - event.destTarget[0] = dstTarget; - event.action.isStateChange = true; - } - dispatchUserEvent(event, null); - } - - public void logActionOnControl(int action, int controlType) { - logActionOnControl(action, controlType, null); - } - - public void logActionOnControl(int action, int controlType, int parentContainerType) { - logActionOnControl(action, controlType, null, parentContainerType); - } - - /** - * Logs control action with proper parent hierarchy - */ - public void logActionOnControl(int actionType, int controlType, - @Nullable View controlInContainer, int... parentTypes) { - Target control = newTarget(Target.Type.CONTROL); - control.controlType = controlType; - Action action = newAction(actionType); - - ArrayList targets = makeTargetsList(control); - if (controlInContainer != null) { - fillLogContainer(controlInContainer, control, targets); - } - for (int parentContainerType : parentTypes) { - if (parentContainerType < 0) continue; - targets.add(newContainerTarget(parentContainerType)); - } - LauncherEvent event = newLauncherEvent(action, targets); - if (actionType == Action.Touch.DRAGDROP) { - event.actionDurationMillis = SystemClock.uptimeMillis() - mActionDurationMillis; - } - dispatchUserEvent(event, null); - } - - public void logActionTapOutside(Target target) { - LauncherEvent event = newLauncherEvent(newTouchAction(Action.Type.TOUCH), - target); - event.action.isOutside = true; - dispatchUserEvent(event, null); - } - - public void logActionBounceTip(int containerType) { - LauncherEvent event = newLauncherEvent(newAction(Action.Type.TIP), - newContainerTarget(containerType)); - event.srcTarget[0].tipType = TipType.BOUNCE; - dispatchUserEvent(event, null); - } - - public void logActionOnContainer(int action, int dir, int containerType) { - logActionOnContainer(action, dir, containerType, 0); - } - - public void logActionOnContainer(int action, int dir, int containerType, int pageIndex) { - LauncherEvent event = newLauncherEvent(newTouchAction(action), - newContainerTarget(containerType)); - event.action.dir = dir; - event.srcTarget[0].pageIndex = pageIndex; - dispatchUserEvent(event, null); - } - - /** - * Used primarily for swipe up and down when state changes when swipe up happens from the - * navbar bezel, the {@param srcChildContainerType} is NAVBAR and - * {@param srcParentContainerType} is either one of the two - * (1) WORKSPACE: if the launcher is the foreground activity - * (2) APP: if another app was the foreground activity - */ - public void logStateChangeAction(int action, int dir, int downX, int downY, - int srcChildTargetType, int srcParentContainerType, int dstContainerType, - int pageIndex) { - LauncherEvent event; - if (srcChildTargetType == ItemType.TASK) { - event = newLauncherEvent(newTouchAction(action), - newItemTarget(srcChildTargetType), - newContainerTarget(srcParentContainerType)); - } else { - event = newLauncherEvent(newTouchAction(action), - newContainerTarget(srcChildTargetType), - newContainerTarget(srcParentContainerType)); - } - event.destTarget = new Target[1]; - event.destTarget[0] = newContainerTarget(dstContainerType); - event.action.dir = dir; - event.action.isStateChange = true; - event.srcTarget[0].pageIndex = pageIndex; - event.srcTarget[0].spanX = downX; - event.srcTarget[0].spanY = downY; - dispatchUserEvent(event, null); - } - - public void logActionOnItem(int action, int dir, int itemType) { - logActionOnItem(action, dir, itemType, null, null); - } - - /** - * Creates new {@link LauncherEvent} of ITEM target type with input arguments and dispatches it. - * - * @param touchAction ENUM value of {@link LauncherLogProto.Action.Touch} Action - * @param dir ENUM value of {@link LauncherLogProto.Action.Direction} Action - * @param itemType ENUM value of {@link LauncherLogProto.ItemType} - * @param gridX Nullable X coordinate of item's position on the workspace grid - * @param gridY Nullable Y coordinate of item's position on the workspace grid - */ - public void logActionOnItem(int touchAction, int dir, int itemType, - @Nullable Integer gridX, @Nullable Integer gridY) { - Target itemTarget = newTarget(Target.Type.ITEM); - itemTarget.itemType = itemType; - ofNullable(gridX).ifPresent(value -> itemTarget.gridX = value); - ofNullable(gridY).ifPresent(value -> itemTarget.gridY = value); - LauncherEvent event = newLauncherEvent(newTouchAction(touchAction), itemTarget); - event.action.dir = dir; - dispatchUserEvent(event, null); - } - - /** - * Logs proto lite version of LauncherEvent object to clearcut. - */ - public void logLauncherEvent( - com.android.launcher3.userevent.LauncherLogProto.LauncherEvent launcherEvent) { - - if (mPreviousHomeGesture) { - mPreviousHomeGesture = false; - } - mAppOrTaskLaunch = false; - launcherEvent.toBuilder() - .setElapsedContainerMillis(SystemClock.uptimeMillis() - mElapsedContainerMillis) - .setElapsedSessionMillis( - SystemClock.uptimeMillis() - mElapsedSessionMillis).build(); - try { - dispatchUserEvent(LauncherEvent.parseFrom(launcherEvent.toByteArray()), null); - } catch (InvalidProtocolBufferNanoException e) { - throw new RuntimeException("Cannot convert LauncherEvent from Lite to Nano version."); - } - } - - public void logDeepShortcutsOpen(View icon) { - ItemInfo info = (ItemInfo) icon.getTag(); - Target child = newItemTarget(info, mInstantAppResolver); - ArrayList targets = makeTargetsList(child); - fillLogContainer(icon, child, targets); - dispatchUserEvent(newLauncherEvent(newTouchAction(Action.Touch.TAP), targets), null); - } - - public void logDragNDrop(DropTarget.DragObject dragObj, View dropTargetAsView) { - Target srcChild = newItemTarget(dragObj.originalDragInfo, mInstantAppResolver); - ArrayList srcTargets = makeTargetsList(srcChild); - - - Target destChild = newItemTarget(dragObj.originalDragInfo, mInstantAppResolver); - ArrayList destTargets = makeTargetsList(destChild); - - //dragObj.dragSource.fillInLogContainerData(dragObj.originalDragInfo, srcChild, srcTargets); - if (dropTargetAsView instanceof LogContainerProvider) { - ((LogContainerProvider) dropTargetAsView).fillInLogContainerData(dragObj.dragInfo, - destChild, destTargets); - } - else { - destTargets.add(newDropTarget(dropTargetAsView)); - } - LauncherEvent event = newLauncherEvent(newTouchAction(Action.Touch.DRAGDROP), srcTargets); - Target[] destTargetsArray = new Target[destTargets.size()]; - destTargets.toArray(destTargetsArray); - event.destTarget = destTargetsArray; - - event.actionDurationMillis = SystemClock.uptimeMillis() - mActionDurationMillis; - dispatchUserEvent(event, null); - } - - public final void startSession() { - mSessionStarted = true; - mElapsedSessionMillis = SystemClock.uptimeMillis(); - mElapsedContainerMillis = SystemClock.uptimeMillis(); - } - - public final void setPreviousHomeGesture(boolean homeGesture) { - mPreviousHomeGesture = homeGesture; - } - - public final boolean isPreviousHomeGesture() { - return mPreviousHomeGesture; - } - - public final void resetActionDurationMillis() { - mActionDurationMillis = SystemClock.uptimeMillis(); - } - - public void dispatchUserEvent(LauncherEvent ev, Intent intent) { - if (mPreviousHomeGesture) { - mPreviousHomeGesture = false; - } - mAppOrTaskLaunch = false; - ev.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis; - ev.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis; - if (!IS_VERBOSE) { - return; - } - LauncherLogProto.LauncherEvent liteLauncherEvent; - try { - liteLauncherEvent = - LauncherLogProto.LauncherEvent.parseFrom(MessageNano.toByteArray(ev)); - } catch (InvalidProtocolBufferException e) { - throw new RuntimeException("Cannot parse LauncherEvent from Nano to Lite version"); - } - Log.d(TAG, liteLauncherEvent.toString()); - } - - /** - * Constructs an ArrayList with targets - */ - public static ArrayList makeTargetsList(Target... targets) { - ArrayList result = new ArrayList<>(); - for (Target target : targets) { - result.add(target); - } - return result; - } -} diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java index 41ccbd7054..06a2c92dab 100644 --- a/src/com/android/launcher3/model/data/FolderInfo.java +++ b/src/com/android/launcher3/model/data/FolderInfo.java @@ -20,15 +20,9 @@ import static android.text.TextUtils.isEmpty; import static androidx.core.util.Preconditions.checkNotNull; -import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP; -import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT; import static com.android.launcher3.logger.LauncherAtom.Attribute.EMPTY_LABEL; import static com.android.launcher3.logger.LauncherAtom.Attribute.MANUAL_LABEL; import static com.android.launcher3.logger.LauncherAtom.Attribute.SUGGESTED_LABEL; -import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_CUSTOM; -import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_EMPTY; -import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_FOLDER_LABEL_STATE_UNSPECIFIED; -import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_SUGGESTED; import android.os.Process; @@ -43,10 +37,6 @@ import com.android.launcher3.logger.LauncherAtom.Attribute; import com.android.launcher3.logger.LauncherAtom.FromState; import com.android.launcher3.logger.LauncherAtom.ToState; import com.android.launcher3.model.ModelWriter; -import com.android.launcher3.userevent.LauncherLogProto; -import com.android.launcher3.userevent.LauncherLogProto.Target; -import com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState; -import com.android.launcher3.userevent.LauncherLogProto.Target.ToFolderLabelState; import com.android.launcher3.util.ContentWriter; import java.util.ArrayList; @@ -359,113 +349,4 @@ public class FolderInfo extends ItemInfo { } return LauncherAtom.ToState.TO_STATE_UNSPECIFIED; } - - /** - * Returns {@link LauncherLogProto.LauncherEvent} to log current folder label info. - * - * @deprecated This method is used only for validation purpose and soon will be removed. - */ - @Deprecated - public LauncherLogProto.LauncherEvent getFolderLabelStateLauncherEvent(FromState fromState, - ToState toState) { - return LauncherLogProto.LauncherEvent.newBuilder() - .setAction(LauncherLogProto.Action - .newBuilder() - .setType(LauncherLogProto.Action.Type.SOFT_KEYBOARD)) - .addSrcTarget(Target - .newBuilder() - .setType(Target.Type.ITEM) - .setItemType(LauncherLogProto.ItemType.EDITTEXT) - .setFromFolderLabelState(convertFolderLabelState(fromState)) - .setToFolderLabelState(convertFolderLabelState(toState))) - .addSrcTarget(Target.newBuilder() - .setType(Target.Type.CONTAINER) - .setContainerType(LauncherLogProto.ContainerType.FOLDER) - .setPageIndex(screenId) - .setGridX(cellX) - .setGridY(cellY) - .setCardinality(contents.size())) - .addSrcTarget(newParentContainerTarget()) - .build(); - } - - /** - * @deprecated This method is used only for validation purpose and soon will be removed. - */ - @Deprecated - private Target.Builder newParentContainerTarget() { - Target.Builder builder = Target.newBuilder().setType(Target.Type.CONTAINER); - switch (container) { - case CONTAINER_HOTSEAT: - return builder.setContainerType(LauncherLogProto.ContainerType.HOTSEAT); - case CONTAINER_DESKTOP: - return builder.setContainerType(LauncherLogProto.ContainerType.WORKSPACE); - default: - throw new AssertionError(String - .format("Expected container to be either %s or %s but found %s.", - CONTAINER_HOTSEAT, - CONTAINER_DESKTOP, - container)); - } - } - - /** - * @deprecated This method is used only for validation purpose and soon will be removed. - */ - @Deprecated - private static FromFolderLabelState convertFolderLabelState(FromState fromState) { - switch (fromState) { - case FROM_EMPTY: - return FROM_EMPTY; - case FROM_SUGGESTED: - return FROM_SUGGESTED; - case FROM_CUSTOM: - return FROM_CUSTOM; - default: - return FROM_FOLDER_LABEL_STATE_UNSPECIFIED; - } - } - - /** - * @deprecated This method is used only for validation purpose and soon will be removed. - */ - @Deprecated - private static ToFolderLabelState convertFolderLabelState(ToState toState) { - switch (toState) { - case UNCHANGED: - return ToFolderLabelState.UNCHANGED; - case TO_SUGGESTION0: - return ToFolderLabelState.TO_SUGGESTION0_WITH_VALID_PRIMARY; - case TO_SUGGESTION1_WITH_VALID_PRIMARY: - return ToFolderLabelState.TO_SUGGESTION1_WITH_VALID_PRIMARY; - case TO_SUGGESTION1_WITH_EMPTY_PRIMARY: - return ToFolderLabelState.TO_SUGGESTION1_WITH_EMPTY_PRIMARY; - case TO_SUGGESTION2_WITH_VALID_PRIMARY: - return ToFolderLabelState.TO_SUGGESTION2_WITH_VALID_PRIMARY; - case TO_SUGGESTION2_WITH_EMPTY_PRIMARY: - return ToFolderLabelState.TO_SUGGESTION2_WITH_EMPTY_PRIMARY; - case TO_SUGGESTION3_WITH_VALID_PRIMARY: - return ToFolderLabelState.TO_SUGGESTION3_WITH_VALID_PRIMARY; - case TO_SUGGESTION3_WITH_EMPTY_PRIMARY: - return ToFolderLabelState.TO_SUGGESTION3_WITH_EMPTY_PRIMARY; - case TO_EMPTY_WITH_VALID_PRIMARY: - return ToFolderLabelState.TO_EMPTY_WITH_VALID_PRIMARY; - case TO_EMPTY_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY: - return ToFolderLabelState.TO_EMPTY_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY; - case TO_EMPTY_WITH_EMPTY_SUGGESTIONS: - return ToFolderLabelState.TO_EMPTY_WITH_EMPTY_SUGGESTIONS; - case TO_EMPTY_WITH_SUGGESTIONS_DISABLED: - return ToFolderLabelState.TO_EMPTY_WITH_SUGGESTIONS_DISABLED; - case TO_CUSTOM_WITH_VALID_PRIMARY: - return ToFolderLabelState.TO_CUSTOM_WITH_VALID_PRIMARY; - case TO_CUSTOM_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY: - return ToFolderLabelState.TO_CUSTOM_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY; - case TO_CUSTOM_WITH_EMPTY_SUGGESTIONS: - return ToFolderLabelState.TO_CUSTOM_WITH_EMPTY_SUGGESTIONS; - case TO_CUSTOM_WITH_SUGGESTIONS_DISABLED: - return ToFolderLabelState.TO_CUSTOM_WITH_SUGGESTIONS_DISABLED; - default: - return ToFolderLabelState.TO_FOLDER_LABEL_STATE_UNSPECIFIED; - } - } } diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java index 32f060ba85..9b065233b9 100644 --- a/src/com/android/launcher3/notification/NotificationMainView.java +++ b/src/com/android/launcher3/notification/NotificationMainView.java @@ -17,6 +17,7 @@ package com.android.launcher3.notification; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DISMISSED; import android.animation.Animator; import android.animation.ObjectAnimator; @@ -41,7 +42,6 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.touch.BaseSwipeDetector; import com.android.launcher3.touch.OverScroll; import com.android.launcher3.touch.SingleAxisSwipeDetector; -import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.Themes; /** @@ -168,10 +168,7 @@ public class NotificationMainView extends FrameLayout implements SingleAxisSwipe Launcher launcher = Launcher.getLauncher(getContext()); launcher.getPopupDataProvider().cancelNotification( mNotificationInfo.notificationKey); - launcher.getUserEventDispatcher().logActionOnItem( - LauncherLogProto.Action.Touch.SWIPE, - LauncherLogProto.Action.Direction.RIGHT, // Assume all swipes are right for logging. - LauncherLogProto.ItemType.NOTIFICATION); + launcher.getStatsLogManager().logger().log(LAUNCHER_NOTIFICATION_DISMISSED); } // SingleAxisSwipeDetector.Listener's diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index 26b32b8195..6d92b8b627 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -19,10 +19,8 @@ package com.android.launcher3.popup; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS; import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.Utilities.squaredTouchSlop; -import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS; import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS; -import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.animation.AnimatorSet; @@ -160,8 +158,7 @@ public class PopupContainerWithArrow extends Arr if (ev.getAction() == MotionEvent.ACTION_DOWN) { BaseDragLayer dl = getPopupContainer(); if (!dl.isEventOverView(this, ev)) { - mLauncher.getUserEventDispatcher().logActionTapOutside( - newContainerTarget(ContainerType.DEEPSHORTCUTS)); + // TODO: add WW log if want to log if tap closed deep shortcut container. close(true); // We let touches on the original icon go through so that users can launch @@ -435,7 +432,9 @@ public class PopupContainerWithArrow extends Arr // Make sure we keep the original icon hidden while it is being dragged. mOriginalIcon.setVisibility(INVISIBLE); } else { - mLauncher.getUserEventDispatcher().logDeepShortcutsOpen(mOriginalIcon); + // TODO: add WW logging if want to add logging for long press on popup + // container. + // mLauncher.getUserEventDispatcher().logDeepShortcutsOpen(mOriginalIcon); if (!mIsAboveIcon) { // Show the icon but keep the text hidden. mOriginalIcon.setVisibility(VISIBLE); diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java index 61829c002b..7c393ad1e2 100644 --- a/src/com/android/launcher3/popup/RemoteActionShortcut.java +++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java @@ -37,7 +37,6 @@ import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.userevent.nano.LauncherLogProto; @TargetApi(Build.VERSION_CODES.Q) public class RemoteActionShortcut extends SystemShortcut { @@ -107,9 +106,6 @@ public class RemoteActionShortcut extends SystemShortcut { Toast.LENGTH_SHORT) .show(); } - - mTarget.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP, - LauncherLogProto.ControlType.REMOTE_ACTION_SHORTCUT, view); } @Override diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java index 81302ac1f7..577fe4afaa 100644 --- a/src/com/android/launcher3/popup/SystemShortcut.java +++ b/src/com/android/launcher3/popup/SystemShortcut.java @@ -21,8 +21,6 @@ import com.android.launcher3.R; import com.android.launcher3.model.WidgetItem; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action; -import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; @@ -117,8 +115,6 @@ public abstract class SystemShortcut extends Ite (WidgetsBottomSheet) mTarget.getLayoutInflater().inflate( R.layout.widgets_bottom_sheet, mTarget.getDragLayer(), false); widgetsBottomSheet.populateAndShow(mItemInfo); - mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP, - ControlType.WIDGETS_BUTTON, view); mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo) .log(LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP); } @@ -139,8 +135,6 @@ public abstract class SystemShortcut extends Ite Rect sourceBounds = mTarget.getViewBounds(view); new PackageManagerHelper(mTarget).startDetailsActivityForInfo( mItemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle()); - mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP, - ControlType.APPINFO_TARGET, view); mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo) .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP); } diff --git a/src/com/android/launcher3/states/HintState.java b/src/com/android/launcher3/states/HintState.java index b8a184fcfc..fd1d965982 100644 --- a/src/com/android/launcher3/states/HintState.java +++ b/src/com/android/launcher3/states/HintState.java @@ -15,11 +15,12 @@ */ package com.android.launcher3.states; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME; + import android.content.Context; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; /** * Scale down workspace/hotseat to hint at going to either overview (on pause) or first home screen. @@ -30,7 +31,7 @@ public class HintState extends LauncherState { | FLAG_HAS_SYS_UI_SCRIM; public HintState(int id) { - super(id, ContainerType.DEFAULT_CONTAINERTYPE, STATE_FLAGS); + super(id, LAUNCHER_STATE_HOME, STATE_FLAGS); } @Override diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java index 2a4f887503..45172b56ef 100644 --- a/src/com/android/launcher3/states/SpringLoadedState.java +++ b/src/com/android/launcher3/states/SpringLoadedState.java @@ -15,6 +15,8 @@ */ package com.android.launcher3.states; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME; + import android.content.Context; import android.graphics.Rect; @@ -22,7 +24,6 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.Workspace; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; /** * Definition for spring loaded state used during drag and drop. @@ -35,7 +36,7 @@ public class SpringLoadedState extends LauncherState { | FLAG_HIDE_BACK_BUTTON; public SpringLoadedState(int id) { - super(id, ContainerType.WORKSPACE, STATE_FLAGS); + super(id, LAUNCHER_STATE_HOME, STATE_FLAGS); } @Override diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java index 8ee5a6e533..9fd53e2563 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -21,6 +21,9 @@ import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEDOWN; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEUP; import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS; @@ -52,9 +55,6 @@ import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.states.StateAnimationConfig.AnimationFlags; import com.android.launcher3.testing.TestProtocol; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.FlingBlockCheck; import com.android.launcher3.util.TouchController; @@ -190,11 +190,6 @@ public abstract class AbstractStateChangeTouchController protected abstract float initCurrentAnimation(@AnimationFlags int animComponents); - /** - * Returns the container that the touch started from when leaving NORMAL state. - */ - protected abstract int getLogContainerTypeForNormalState(MotionEvent ev); - private boolean reinitCurrentAnimation(boolean reachedToState, boolean isDragTowardPositive) { LauncherState newFromState = mFromState == null ? mLauncher.getStateManager().getState() : reachedToState ? mToState : mFromState; @@ -307,11 +302,11 @@ public abstract class AbstractStateChangeTouchController public boolean onDrag(float displacement, MotionEvent ev) { if (!mIsLogContainerSet) { if (mStartState == ALL_APPS) { - mStartContainerType = ContainerType.ALLAPPS; + mStartContainerType = LAUNCHER_STATE_ALLAPPS; } else if (mStartState == NORMAL) { - mStartContainerType = getLogContainerTypeForNormalState(ev); + mStartContainerType = LAUNCHER_STATE_HOME; } else if (mStartState == OVERVIEW) { - mStartContainerType = ContainerType.TASKSWITCHER; + mStartContainerType = LAUNCHER_STATE_OVERVIEW; } mIsLogContainerSet = true; } @@ -401,7 +396,6 @@ public abstract class AbstractStateChangeTouchController @Override public void onDragEnd(float velocity) { boolean fling = mDetector.isFling(velocity); - final int logAction = fling ? Touch.FLING : Touch.SWIPE; boolean blockedFling = fling && mFlingBlockCheck.isBlocked(); if (blockedFling) { @@ -458,7 +452,7 @@ public abstract class AbstractStateChangeTouchController } } - mCurrentAnimation.setEndAction(() -> onSwipeInteractionCompleted(targetState, logAction)); + mCurrentAnimation.setEndAction(() -> onSwipeInteractionCompleted(targetState)); ValueAnimator anim = mCurrentAnimation.getAnimationPlayer(); anim.setFloatValues(startProgress, endProgress); maybeUpdateAtomicAnim(mFromState, targetState, targetState == mToState ? 1f : 0f); @@ -522,11 +516,7 @@ public abstract class AbstractStateChangeTouchController .setInterpolator(scrollInterpolatorForVelocity(velocity)); } - protected int getDirectionForLog() { - return mToState.ordinal > mFromState.ordinal ? Direction.UP : Direction.DOWN; - } - - protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { + protected void onSwipeInteractionCompleted(LauncherState targetState) { if (mAtomicComponentsController != null) { mAtomicComponentsController.getAnimationPlayer().end(); mAtomicComponentsController = null; @@ -535,18 +525,18 @@ public abstract class AbstractStateChangeTouchController boolean shouldGoToTargetState = true; if (mPendingAnimation != null) { boolean reachedTarget = mToState == targetState; - mPendingAnimation.finish(reachedTarget, logAction); + mPendingAnimation.finish(reachedTarget); mPendingAnimation = null; shouldGoToTargetState = !reachedTarget; } if (shouldGoToTargetState) { - goToTargetState(targetState, logAction); + goToTargetState(targetState); } } - protected void goToTargetState(LauncherState targetState, int logAction) { + protected void goToTargetState(LauncherState targetState) { if (targetState != mStartState) { - logReachedState(logAction, targetState); + logReachedState(targetState); } if (!mLauncher.isInState(targetState)) { // If we're already in the target state, don't jump to it at the end of the animation in @@ -556,24 +546,18 @@ public abstract class AbstractStateChangeTouchController mLauncher.getDragLayer().getScrim().createSysuiMultiplierAnim(1f).setDuration(0).start(); } - private void logReachedState(int logAction, LauncherState targetState) { + private void logReachedState(LauncherState targetState) { // Transition complete. log the action - mLauncher.getUserEventDispatcher().logStateChangeAction(logAction, - getDirectionForLog(), mDetector.getDownX(), mDetector.getDownY(), - mStartContainerType /* e.g., hotseat */, - mStartState.containerType /* e.g., workspace */, - targetState.containerType, - mLauncher.getWorkspace().getCurrentPage()); mLauncher.getStatsLogManager().logger() - .withSrcState(StatsLogManager.containerTypeToAtomState(mStartState.containerType)) - .withDstState(StatsLogManager.containerTypeToAtomState(targetState.containerType)) + .withSrcState(mStartState.statsLogOrdinal) + .withDstState(targetState.statsLogOrdinal) .withContainerInfo(LauncherAtom.ContainerInfo.newBuilder() .setWorkspace( LauncherAtom.WorkspaceContainer.newBuilder() .setPageIndex(mLauncher.getWorkspace().getCurrentPage())) .build()) - .log(StatsLogManager.getLauncherAtomEvent(mStartState.containerType, - targetState.containerType, mToState.ordinal > mFromState.ordinal + .log(StatsLogManager.getLauncherAtomEvent(mStartState.statsLogOrdinal, + targetState.statsLogOrdinal, mToState.ordinal > mFromState.ordinal ? LAUNCHER_UNKNOWN_SWIPEUP : LAUNCHER_UNKNOWN_SWIPEDOWN)); } diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java index 4a202b65d8..f9dcf2d2e9 100644 --- a/src/com/android/launcher3/touch/AllAppsSwipeController.java +++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java @@ -24,7 +24,6 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.states.StateAnimationConfig.AnimationFlags; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; /** * TouchController to switch between NORMAL and ALL_APPS state. @@ -69,12 +68,6 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController { return fromState; } - @Override - protected int getLogContainerTypeForNormalState(MotionEvent ev) { - return mLauncher.getDragLayer().isEventOverView(mLauncher.getHotseat(), mTouchDownEvent) - ? ContainerType.HOTSEAT : ContainerType.WORKSPACE; - } - @Override protected float initCurrentAnimation(@AnimationFlags int animComponents) { float range = getShiftRange(); diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java index ec3f93ff1b..a4e53a1cc0 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java @@ -16,13 +16,13 @@ package com.android.launcher3.uioverrides.states; import static com.android.launcher3.anim.Interpolators.DEACCEL_2; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS; import android.content.Context; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.R; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; /** * Definition for AllApps state @@ -41,7 +41,7 @@ public class AllAppsState extends LauncherState { }; public AllAppsState(int id) { - super(id, ContainerType.ALLAPPS, STATE_FLAGS); + super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS); } @Override diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java index d102bccaad..da5a94f6fd 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java @@ -15,10 +15,11 @@ */ package com.android.launcher3.uioverrides.states; +import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW; + import android.content.Context; import com.android.launcher3.LauncherState; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; /** * Definition for overview state @@ -26,7 +27,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; public class OverviewState extends LauncherState { public OverviewState(int id) { - super(id, ContainerType.WORKSPACE, FLAG_DISABLE_RESTORE); + super(id, LAUNCHER_STATE_OVERVIEW, FLAG_DISABLE_RESTORE); } @Override From 10759887c276571b29a58843b9bb854c78731f99 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 25 Sep 2020 16:42:58 -0700 Subject: [PATCH 34/45] Fixing lock during RecentsModel initialization HandlerThread.getLooper blocks the current thread until. the final thread is initialized. Updating RecentsModel to use an executor instead of a handler thread to avoid this. Change-Id: I3b2e82a375ea65bea1526af4a32c6a2488102541 --- .../quickstep/OverviewCommandHelper.java | 4 +- .../com/android/quickstep/RecentsModel.java | 14 ++-- .../com/android/quickstep/TaskIconCache.java | 52 ++++++-------- .../android/quickstep/TaskThumbnailCache.java | 52 +++++--------- .../quickstep/util/CancellableTask.java | 68 +++++++++++++++++++ .../com/android/quickstep/views/TaskView.java | 5 +- src/com/android/launcher3/util/Executors.java | 27 ++++++++ 7 files changed, 142 insertions(+), 80 deletions(-) create mode 100644 quickstep/src/com/android/quickstep/util/CancellableTask.java diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java index 365cff576a..20484e7cdf 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java @@ -47,7 +47,6 @@ public class OverviewCommandHelper { private final Context mContext; private final RecentsAnimationDeviceState mDeviceState; - private final RecentsModel mRecentsModel; private final OverviewComponentObserver mOverviewComponentObserver; private long mLastToggleTime; @@ -56,7 +55,6 @@ public class OverviewCommandHelper { OverviewComponentObserver observer) { mContext = context; mDeviceState = deviceState; - mRecentsModel = RecentsModel.INSTANCE.get(mContext); mOverviewComponentObserver = observer; } @@ -160,7 +158,7 @@ public class OverviewCommandHelper { ActivityManagerWrapper.getInstance().getRunningTask(), mDeviceState); // Preload the plan - mRecentsModel.getTasks(null); + RecentsModel.INSTANCE.get(mContext).getTasks(null); } @Override diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java index 6c302ae5d7..d47217b770 100644 --- a/quickstep/src/com/android/quickstep/RecentsModel.java +++ b/quickstep/src/com/android/quickstep/RecentsModel.java @@ -18,7 +18,6 @@ package com.android.quickstep; import static android.os.Process.THREAD_PRIORITY_BACKGROUND; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; -import static com.android.launcher3.util.Executors.createAndStartNewLooper; import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId; import android.annotation.TargetApi; @@ -26,11 +25,11 @@ import android.app.ActivityManager; import android.content.ComponentCallbacks2; import android.content.Context; import android.os.Build; -import android.os.Looper; import android.os.Process; import android.os.UserHandle; import com.android.launcher3.icons.IconProvider; +import com.android.launcher3.util.Executors.SimpleThreadFactory; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; @@ -40,6 +39,8 @@ import com.android.systemui.shared.system.TaskStackChangeListener; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.function.Consumer; /** @@ -52,6 +53,9 @@ public class RecentsModel extends TaskStackChangeListener { public static final MainThreadInitializedObject INSTANCE = new MainThreadInitializedObject<>(RecentsModel::new); + private static final Executor RECENTS_MODEL_EXECUTOR = Executors.newSingleThreadExecutor( + new SimpleThreadFactory("TaskThumbnailIconCache-", THREAD_PRIORITY_BACKGROUND)); + private final List mThumbnailChangeListeners = new ArrayList<>(); private final Context mContext; @@ -61,12 +65,10 @@ public class RecentsModel extends TaskStackChangeListener { private RecentsModel(Context context) { mContext = context; - Looper looper = - createAndStartNewLooper("TaskThumbnailIconCache", THREAD_PRIORITY_BACKGROUND); mTaskList = new RecentTasksList(MAIN_EXECUTOR, new KeyguardManagerCompat(context), ActivityManagerWrapper.getInstance()); - mIconCache = new TaskIconCache(context, looper); - mThumbnailCache = new TaskThumbnailCache(context, looper); + mIconCache = new TaskIconCache(context, RECENTS_MODEL_EXECUTOR); + mThumbnailCache = new TaskThumbnailCache(context, RECENTS_MODEL_EXECUTOR); ActivityManagerWrapper.getInstance().registerTaskStackListener(this); IconProvider.registerIconChangeListener(context, diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java index 7ff799ec55..65e89cfa2f 100644 --- a/quickstep/src/com/android/quickstep/TaskIconCache.java +++ b/quickstep/src/com/android/quickstep/TaskIconCache.java @@ -17,7 +17,6 @@ package com.android.quickstep; import static com.android.launcher3.FastBitmapDrawable.newIcon; import static com.android.launcher3.uioverrides.QuickstepLauncher.GO_LOW_RAM_RECENTS_ENABLED; -import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import android.app.ActivityManager.TaskDescription; import android.content.Context; @@ -27,8 +26,6 @@ import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; -import android.os.Handler; -import android.os.Looper; import android.os.UserHandle; import android.util.SparseArray; import android.view.accessibility.AccessibilityManager; @@ -37,12 +34,11 @@ import androidx.annotation.WorkerThread; import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.R; -import com.android.launcher3.Utilities; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.IconProvider; import com.android.launcher3.icons.LauncherIcons; -import com.android.launcher3.icons.cache.HandlerRunnable; import com.android.launcher3.util.Preconditions; +import com.android.quickstep.util.CancellableTask; import com.android.quickstep.util.TaskKeyLruCache; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task.TaskKey; @@ -50,6 +46,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; import com.android.systemui.shared.system.TaskDescriptionCompat; +import java.util.concurrent.Executor; import java.util.function.Consumer; /** @@ -57,7 +54,7 @@ import java.util.function.Consumer; */ public class TaskIconCache { - private final Handler mBackgroundHandler; + private final Executor mBgExecutor; private final AccessibilityManager mAccessibilityManager; private final Context mContext; @@ -65,9 +62,9 @@ public class TaskIconCache { private final SparseArray mDefaultIcons = new SparseArray<>(); private final IconProvider mIconProvider; - public TaskIconCache(Context context, Looper backgroundLooper) { + public TaskIconCache(Context context, Executor bgExecutor) { mContext = context; - mBackgroundHandler = new Handler(backgroundLooper); + mBgExecutor = bgExecutor; mAccessibilityManager = context.getSystemService(AccessibilityManager.class); Resources res = context.getResources(); @@ -83,31 +80,27 @@ public class TaskIconCache { * @param callback The callback to receive the task after its data has been populated. * @return A cancelable handle to the request */ - public IconLoadRequest updateIconInBackground(Task task, Consumer callback) { + public CancellableTask updateIconInBackground(Task task, Consumer callback) { Preconditions.assertUIThread(); if (task.icon != null) { // Nothing to load, the icon is already loaded callback.accept(task); return null; } - - IconLoadRequest request = new IconLoadRequest(mBackgroundHandler) { + CancellableTask request = new CancellableTask() { @Override - public void run() { - TaskCacheEntry entry = getCacheEntry(task); - if (isCanceled()) { - // We don't call back to the provided callback in this case - return; - } - MAIN_EXECUTOR.execute(() -> { - task.icon = entry.icon; - task.titleDescription = entry.contentDescription; - callback.accept(task); - onEnd(); - }); + public TaskCacheEntry getResultOnBg() { + return getCacheEntry(task); + } + + @Override + public void handleResult(TaskCacheEntry result) { + task.icon = result.icon; + task.titleDescription = result.contentDescription; + callback.accept(task); } }; - Utilities.postAsyncCallback(mBackgroundHandler, request); + mBgExecutor.execute(request); return request; } @@ -120,9 +113,8 @@ public class TaskIconCache { } void invalidateCacheEntries(String pkg, UserHandle handle) { - Utilities.postAsyncCallback(mBackgroundHandler, - () -> mIconCache.removeAll(key -> - pkg.equals(key.getPackageName()) && handle.getIdentifier() == key.userId)); + mBgExecutor.execute(() -> mIconCache.removeAll(key -> + pkg.equals(key.getPackageName()) && handle.getIdentifier() == key.userId)); } @WorkerThread @@ -208,12 +200,6 @@ public class TaskIconCache { } } - public static abstract class IconLoadRequest extends HandlerRunnable { - IconLoadRequest(Handler handler) { - super(handler, null); - } - } - private static class TaskCacheEntry { public Drawable icon; public String contentDescription = ""; diff --git a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java index 2b7a8ec250..a8a0219594 100644 --- a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java +++ b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java @@ -15,17 +15,12 @@ */ package com.android.quickstep; -import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; - import android.content.Context; import android.content.res.Resources; -import android.os.Handler; -import android.os.Looper; import com.android.launcher3.R; -import com.android.launcher3.Utilities; -import com.android.launcher3.icons.cache.HandlerRunnable; import com.android.launcher3.util.Preconditions; +import com.android.quickstep.util.CancellableTask; import com.android.quickstep.util.TaskKeyLruCache; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task.TaskKey; @@ -33,11 +28,12 @@ import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; import java.util.ArrayList; +import java.util.concurrent.Executor; import java.util.function.Consumer; public class TaskThumbnailCache { - private final Handler mBackgroundHandler; + private final Executor mBgExecutor; private final int mCacheSize; private final TaskKeyLruCache mCache; @@ -94,8 +90,8 @@ public class TaskThumbnailCache { } } - public TaskThumbnailCache(Context context, Looper backgroundLooper) { - mBackgroundHandler = new Handler(backgroundLooper); + public TaskThumbnailCache(Context context, Executor bgExecutor) { + mBgExecutor = bgExecutor; mHighResLoadingState = new HighResLoadingState(context); Resources res = context.getResources(); @@ -130,7 +126,7 @@ public class TaskThumbnailCache { * @param callback The callback to receive the task after its data has been populated. * @return A cancelable handle to the request */ - public ThumbnailLoadRequest updateThumbnailInBackground( + public CancellableTask updateThumbnailInBackground( Task task, Consumer callback) { Preconditions.assertUIThread(); @@ -142,14 +138,13 @@ public class TaskThumbnailCache { return null; } - return updateThumbnailInBackground(task.key, !mHighResLoadingState.isEnabled(), t -> { task.thumbnail = t; callback.accept(t); }); } - private ThumbnailLoadRequest updateThumbnailInBackground(TaskKey key, boolean lowResolution, + private CancellableTask updateThumbnailInBackground(TaskKey key, boolean lowResolution, Consumer callback) { Preconditions.assertUIThread(); @@ -160,26 +155,20 @@ public class TaskThumbnailCache { return null; } - ThumbnailLoadRequest request = new ThumbnailLoadRequest(mBackgroundHandler, - lowResolution) { + CancellableTask request = new CancellableTask() { @Override - public void run() { - ThumbnailData thumbnail = ActivityManagerWrapper.getInstance().getTaskThumbnail( + public ThumbnailData getResultOnBg() { + return ActivityManagerWrapper.getInstance().getTaskThumbnail( key.id, lowResolution); + } - MAIN_EXECUTOR.execute(() -> { - if (isCanceled()) { - // We don't call back to the provided callback in this case - return; - } - - mCache.put(key, thumbnail); - callback.accept(thumbnail); - onEnd(); - }); + @Override + public void handleResult(ThumbnailData result) { + mCache.put(key, result); + callback.accept(result); } }; - Utilities.postAsyncCallback(mBackgroundHandler, request); + mBgExecutor.execute(request); return request; } @@ -218,15 +207,6 @@ public class TaskThumbnailCache { return mEnableTaskSnapshotPreloading && mHighResLoadingState.mVisible; } - public static abstract class ThumbnailLoadRequest extends HandlerRunnable { - public final boolean mLowResolution; - - ThumbnailLoadRequest(Handler handler, boolean lowResolution) { - super(handler, null); - mLowResolution = lowResolution; - } - } - /** * @return Whether device supports low-res thumbnails. Low-res files are an optimization * for faster load times of snapshots. Devices can optionally disable low-res files so that diff --git a/quickstep/src/com/android/quickstep/util/CancellableTask.java b/quickstep/src/com/android/quickstep/util/CancellableTask.java new file mode 100644 index 0000000000..a6e2e81589 --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/CancellableTask.java @@ -0,0 +1,68 @@ +/* + * 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. + */ +package com.android.quickstep.util; + +import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; + +import androidx.annotation.UiThread; +import androidx.annotation.WorkerThread; + +/** + * Utility class to executore a task on background and post the result on UI thread + */ +public abstract class CancellableTask implements Runnable { + + private boolean mCancelled = false; + + @Override + public final void run() { + if (mCancelled) { + return; + } + T result = getResultOnBg(); + if (mCancelled) { + return; + } + MAIN_EXECUTOR.execute(() -> { + if (mCancelled) { + return; + } + handleResult(result); + }); + } + + /** + * Called on the worker thread to process the request. The return object is passed to + * {@link #handleResult(Object)} + */ + @WorkerThread + public abstract T getResultOnBg(); + + /** + * Called on the UI thread to handle the final result. + * @param result + */ + @UiThread + public abstract void handleResult(T result); + + /** + * Cancels the request. If it is called before {@link #handleResult(Object)}, that method + * will not be called + */ + public void cancel() { + mCancelled = true; + } +} diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 6a2ab5a304..ada54be0db 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -90,6 +90,7 @@ import com.android.quickstep.TaskIconCache; import com.android.quickstep.TaskOverlayFactory; import com.android.quickstep.TaskThumbnailCache; import com.android.quickstep.TaskUtils; +import com.android.quickstep.util.CancellableTask; import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.util.TaskCornerRadius; import com.android.quickstep.views.RecentsView.PageCallbacks; @@ -189,8 +190,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private boolean mShowScreenshot; // The current background requests to load the task thumbnail and icon - private TaskThumbnailCache.ThumbnailLoadRequest mThumbnailLoadRequest; - private TaskIconCache.IconLoadRequest mIconLoadRequest; + private CancellableTask mThumbnailLoadRequest; + private CancellableTask mIconLoadRequest; // Order in which the footers appear. Lower order appear below higher order. public static final int INDEX_DIGITAL_WELLBEING_TOAST = 0; diff --git a/src/com/android/launcher3/util/Executors.java b/src/com/android/launcher3/util/Executors.java index 0a32734fca..a85ae458ed 100644 --- a/src/com/android/launcher3/util/Executors.java +++ b/src/com/android/launcher3/util/Executors.java @@ -20,8 +20,10 @@ import android.os.Looper; import android.os.Process; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; /** * Various different executors used in Launcher @@ -83,4 +85,29 @@ public class Executors { */ public static final LooperExecutor MODEL_EXECUTOR = new LooperExecutor(createAndStartNewLooper("launcher-loader")); + + /** + * A simple ThreadFactory to set the thread name and priority when used with executors. + */ + public static class SimpleThreadFactory implements ThreadFactory { + + private final int mPriority; + private final String mNamePrefix; + + private final AtomicInteger mCount = new AtomicInteger(0); + + public SimpleThreadFactory(String namePrefix, int priority) { + mNamePrefix = namePrefix; + mPriority = priority; + } + + @Override + public Thread newThread(Runnable runnable) { + Thread t = new Thread(() -> { + Process.setThreadPriority(mPriority); + runnable.run(); + }, mNamePrefix + mCount.incrementAndGet()); + return t; + } + } } From b8a30ef68a133c216c5af10d746808065890d024 Mon Sep 17 00:00:00 2001 From: vadimt Date: Fri, 25 Sep 2020 13:03:40 -0700 Subject: [PATCH 35/45] Adding jank tracing for some CUJs Test: checking traces Bug: 169220800 Bug: 169220955 Bug: 169221267 Bug: 169220924 Bug: 169220843 Change-Id: Ia32635764c78139f7e9a616c9fe70ae1a507c1b2 --- .../launcher3/BaseQuickstepLauncher.java | 8 ++ .../QuickstepAppTransitionManagerImpl.java | 75 ++++++++++--------- .../android/quickstep/AbsSwipeUpHandler.java | 10 +++ 3 files changed, 59 insertions(+), 34 deletions(-) diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index 68111d2632..54c2383be9 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -22,6 +22,8 @@ import static com.android.launcher3.LauncherState.NORMAL; import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY; +import com.android.systemui.shared.system.InteractionJankMonitorWrapper; + import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.content.Intent; @@ -307,4 +309,10 @@ public abstract class BaseQuickstepLauncher extends Launcher public void setHintUserWillBeActive() { addActivityFlags(ACTIVITY_STATE_USER_WILL_BE_ACTIVE); } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + InteractionJankMonitorWrapper.init(getWindow().getDecorView()); + } } diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java index dddcc865fa..d453bc3455 100644 --- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java @@ -66,6 +66,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.allapps.AllAppsTransitionController; +import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.shortcuts.DeepShortcutView; @@ -81,6 +82,7 @@ import com.android.quickstep.util.StaggeredWorkspaceAnim; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.systemui.shared.system.ActivityCompat; import com.android.systemui.shared.system.ActivityOptionsCompat; +import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; import com.android.systemui.shared.system.RemoteAnimationDefinitionCompat; @@ -791,6 +793,36 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans == PackageManager.PERMISSION_GRANTED; } + private void addCujInstrumentation(Animator anim, int cuj, String transition) { + if (Trace.isEnabled()) { + anim.addListener(new AnimationSuccessListener() { + @Override + public void onAnimationStart(Animator animation) { + Trace.beginAsyncSection(transition, 0); + InteractionJankMonitorWrapper.begin(cuj); + super.onAnimationStart(animation); + } + + @Override + public void onAnimationCancel(Animator animation) { + super.onAnimationCancel(animation); + InteractionJankMonitorWrapper.cancel(cuj); + } + + @Override + public void onAnimationSuccess(Animator animator) { + InteractionJankMonitorWrapper.end(cuj); + } + + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + Trace.endAsyncSection(TRANSITION_OPEN_LAUNCHER, 0); + } + }); + } + } + /** * Remote animation runner for animation from the app to Launcher, including recents. */ @@ -855,21 +887,9 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans // is initialized. if (launcherIsATargetWithMode(appTargets, MODE_OPENING) || mLauncher.isForceInvisible()) { - if (Trace.isEnabled()) { - anim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - Trace.beginAsyncSection(TRANSITION_OPEN_LAUNCHER, 0); - super.onAnimationStart(animation); - } - - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - Trace.endAsyncSection(TRANSITION_OPEN_LAUNCHER, 0); - } - }); - } + addCujInstrumentation( + anim, InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME, + TRANSITION_OPEN_LAUNCHER); // Only register the content animation for cancellation when state changes mLauncher.getStateManager().setCurrentAnimation(anim); @@ -938,25 +958,12 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans launcherClosing); } - if (Trace.isEnabled()) { - final String section = - launchingFromRecents - ? TRANSITION_LAUNCH_FROM_RECENTS : TRANSITION_LAUNCH_FROM_ICON; - - anim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - Trace.beginAsyncSection(section, 0); - super.onAnimationStart(animation); - } - - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - Trace.endAsyncSection(section, 0); - } - }); - } + addCujInstrumentation(anim, + launchingFromRecents + ? InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_RECENTS + : InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_ICON, + launchingFromRecents + ? TRANSITION_LAUNCH_FROM_RECENTS : TRANSITION_LAUNCH_FROM_ICON); if (launcherClosing) { anim.addListener(mForceInvisibleListener); diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 6774433a1f..5e05a7dbe1 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -97,6 +97,7 @@ import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputConsumerController; +import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.TaskInfoCompat; @@ -1130,10 +1131,12 @@ public abstract class AbsSwipeUpHandler, Q extends anim.addOnUpdateListener((r, p) -> { updateSysUiFlags(Math.max(p, mCurrentShift.value)); }); + final int cuj = InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME; anim.addAnimatorListener(new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { Trace.beginAsyncSection(TRANSITION_OPEN_LAUNCHER, 0); + InteractionJankMonitorWrapper.begin(cuj); if (mActivity != null) { removeLiveTileOverlay(); } @@ -1147,6 +1150,13 @@ public abstract class AbsSwipeUpHandler, Q extends // Make sure recents is in its final state maybeUpdateRecentsAttachedState(false); mActivityInterface.onSwipeUpToHomeComplete(mDeviceState); + InteractionJankMonitorWrapper.end(cuj); + } + + @Override + public void onAnimationCancel(Animator animation) { + super.onAnimationCancel(animation); + InteractionJankMonitorWrapper.cancel(cuj); } @Override From 9fcb45f872cd23413fafcc645001ba79fafc5087 Mon Sep 17 00:00:00 2001 From: Jonathan Miranda Date: Tue, 29 Sep 2020 02:08:10 +0000 Subject: [PATCH 36/45] Revert "Remove widgets that no longer fit the workspace in their current spans." This reverts commit bf6e8ffbf030b6d419b808c28335bf8a8724e9bc. Reason for revert: broken tests Bug: 141313472 Change-Id: I1e93e21e2c6618dea6cd099a46c9b9d2ab3ab81c --- src/com/android/launcher3/model/LoaderTask.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index c0d5882b46..2b4520b613 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -49,7 +49,6 @@ import android.util.LongSparseArray; import android.util.TimingLogger; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherSettings; import com.android.launcher3.Utilities; @@ -307,7 +306,6 @@ public class LoaderTask implements Runnable { final PackageManagerHelper pmHelper = new PackageManagerHelper(context); final boolean isSafeMode = pmHelper.isSafeMode(); final boolean isSdCardReady = Utilities.isBootCompleted(); - final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context); boolean clearDb = false; try { @@ -393,7 +391,6 @@ public class LoaderTask implements Runnable { WorkspaceItemInfo info; LauncherAppWidgetInfo appWidgetInfo; - LauncherAppWidgetProviderInfo widgetProviderInfo; Intent intent; String targetPkg; @@ -723,19 +720,6 @@ public class LoaderTask implements Runnable { + appWidgetInfo.spanX + "x" + appWidgetInfo.spanY); continue; } - widgetProviderInfo = - widgetHelper.getLauncherAppWidgetInfo(appWidgetId); - if (widgetProviderInfo != null - && (appWidgetInfo.spanX < widgetProviderInfo.minSpanX - || appWidgetInfo.spanY < widgetProviderInfo.minSpanY)) { - // This can happen when display size changes. - c.markDeleted("Widget removed, min sizes not met: " - + "span=" + appWidgetInfo.spanX + "x" - + appWidgetInfo.spanY + " minSpan=" - + widgetProviderInfo.minSpanX + "x" - + widgetProviderInfo.minSpanY); - continue; - } if (!c.isOnWorkspaceOrHotseat()) { c.markDeleted("Widget found where container != " + "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!"); From b7487f867c2ff1bd0459182934b4040a0cf1d865 Mon Sep 17 00:00:00 2001 From: jayaprakashs Date: Wed, 23 Sep 2020 22:46:36 -0700 Subject: [PATCH 37/45] [Search] [People] Pass intent to People view instead of URI. Tested: On Phone Bug: 169294622 Change-Id: I4e379a80a256e018761af2925e640745456faeec --- .../views/SearchResultPeopleView.java | 49 +++++++------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/src/com/android/launcher3/views/SearchResultPeopleView.java b/src/com/android/launcher3/views/SearchResultPeopleView.java index eacc095188..0c9a22f672 100644 --- a/src/com/android/launcher3/views/SearchResultPeopleView.java +++ b/src/com/android/launcher3/views/SearchResultPeopleView.java @@ -15,9 +15,6 @@ */ package com.android.launcher3.views; -import static android.content.Intent.URI_ALLOW_UNSAFE; -import static android.content.Intent.URI_ANDROID_APP_SCHEME; - import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; @@ -28,7 +25,6 @@ import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.net.Uri; import android.os.Bundle; import android.util.AttributeSet; import android.view.View; @@ -50,7 +46,6 @@ import com.android.systemui.plugins.AllAppsSearchPlugin; import com.android.systemui.plugins.shared.SearchTarget; import com.android.systemui.plugins.shared.SearchTargetEvent; -import java.net.URISyntaxException; import java.util.ArrayList; /** @@ -66,7 +61,7 @@ public class SearchResultPeopleView extends LinearLayout implements private TextView mTitleView; private ImageButton[] mProviderButtons = new ImageButton[3]; private AllAppsSearchPlugin mPlugin; - private Uri mContactUri; + private Intent mIntent; private final Object[] mTargetInfo = createTargetInfo(); public SearchResultPeopleView(Context context) { @@ -109,7 +104,7 @@ public class SearchResultPeopleView extends LinearLayout implements Bundle payload = adapterItemWithPayload.getPayload(); mPlugin = adapterItemWithPayload.getPlugin(); mTitleView.setText(payload.getString("title")); - mContactUri = payload.getParcelable("contact_uri"); + mIntent = payload.getParcelable("intent"); Bitmap icon = payload.getParcelable("icon"); if (icon != null) { RoundedBitmapDrawable d = RoundedBitmapDrawableFactory.create(getResources(), icon); @@ -125,25 +120,20 @@ public class SearchResultPeopleView extends LinearLayout implements for (int i = 0; i < mProviderButtons.length; i++) { ImageButton button = mProviderButtons[i]; if (providers != null && i < providers.size()) { - try { - Bundle provider = providers.get(i); - Intent intent = Intent.parseUri(provider.getString("intent_uri_str"), - URI_ANDROID_APP_SCHEME | URI_ALLOW_UNSAFE); - setupProviderButton(button, provider, intent, adapterItemWithPayload); - String pkg = provider.getString("package_name"); - UI_HELPER_EXECUTOR.post(() -> { - try { - ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo( - pkg, 0); - Drawable appIcon = applicationInfo.loadIcon(mPackageManager); - MAIN_EXECUTOR.post(() -> button.setImageDrawable(appIcon)); - } catch (PackageManager.NameNotFoundException ignored) { - } + Bundle provider = providers.get(i); + Intent intent = provider.getParcelable("intent"); + setupProviderButton(button, provider, intent, adapterItemWithPayload); + String pkg = provider.getString("package_name"); + UI_HELPER_EXECUTOR.post(() -> { + try { + ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo( + pkg, 0); + Drawable appIcon = applicationInfo.loadIcon(mPackageManager); + MAIN_EXECUTOR.post(() -> button.setImageDrawable(appIcon)); + } catch (PackageManager.NameNotFoundException ignored) { + } - }); - } catch (URISyntaxException ex) { - button.setVisibility(GONE); - } + }); } else { button.setVisibility(GONE); } @@ -165,7 +155,7 @@ public class SearchResultPeopleView extends LinearLayout implements SearchTarget.ItemType.PEOPLE, SearchTargetEvent.CHILD_SELECT); searchTargetEvent.bundle = new Bundle(); - searchTargetEvent.bundle.putParcelable("contact_uri", mContactUri); + searchTargetEvent.bundle.putParcelable("intent", mIntent); searchTargetEvent.bundle.putBundle("provider", provider); if (mPlugin != null) { mPlugin.notifySearchTargetEvent(searchTargetEvent); @@ -175,14 +165,13 @@ public class SearchResultPeopleView extends LinearLayout implements private void handleSelection(int eventType) { - if (mContactUri != null) { + if (mIntent != null) { Launcher launcher = Launcher.getLauncher(getContext()); - launcher.startActivitySafely(this, new Intent(Intent.ACTION_VIEW, mContactUri).setFlags( - Intent.FLAG_ACTIVITY_NEW_TASK), null); + launcher.startActivitySafely(this, mIntent, null); SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.PEOPLE, eventType); searchTargetEvent.bundle = new Bundle(); - searchTargetEvent.bundle.putParcelable("contact_uri", mContactUri); + searchTargetEvent.bundle.putParcelable("intent", mIntent); if (mPlugin != null) { mPlugin.notifySearchTargetEvent(searchTargetEvent); } From 907845eba549e59ed445b3981cd63c029666cb76 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 28 Sep 2020 20:04:52 -0700 Subject: [PATCH 38/45] Wrap animation runner for recents animation Bug: 160239388 Change-Id: I937c89b963b88702548daca7c0b85f7a79d5d706 --- .../launcher3/LauncherAnimationRunner.java | 3 +-- .../com/android/quickstep/RecentsActivity.java | 18 +++++++++++++++--- .../util/RemoteAnimationProvider.java | 12 ++++++++---- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java index 199cf63b92..75355c9b4e 100644 --- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java +++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java @@ -34,8 +34,7 @@ import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; @TargetApi(Build.VERSION_CODES.P) -public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat, - WrappedAnimationRunnerImpl { +public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat { private static final String TAG = "LauncherAnimationRunner"; diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index 6f2f9fb523..87ae9596e6 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -41,7 +41,10 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAnimationRunner; +import com.android.launcher3.LauncherAnimationRunner.AnimationResult; import com.android.launcher3.R; +import com.android.launcher3.WrappedAnimationRunnerImpl; +import com.android.launcher3.WrappedLauncherAnimationRunner; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.compat.AccessibilityManagerCompat; @@ -87,6 +90,9 @@ public final class RecentsActivity extends StatefulActivity { private StateManager mStateManager; + // Strong refs to runners which are cleared when the activity is destroyed + private WrappedAnimationRunnerImpl mActivityLaunchAnimationRunner; + /** * Init drag layer and overview panel views. */ @@ -170,8 +176,11 @@ public final class RecentsActivity extends StatefulActivity { } final TaskView taskView = (TaskView) v; - RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mUiHandler, - true /* startAtFrontOfQueue */) { + mActivityLaunchAnimationRunner = new WrappedAnimationRunnerImpl() { + @Override + public Handler getHandler() { + return mUiHandler; + } @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets, @@ -182,8 +191,10 @@ public final class RecentsActivity extends StatefulActivity { result.setAnimation(anim, RecentsActivity.this); } }; + final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner<>( + mActivityLaunchAnimationRunner, true /* startAtFrontOfQueue */); return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat( - runner, RECENTS_LAUNCH_DURATION, + wrapper, RECENTS_LAUNCH_DURATION, RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION - STATUS_BAR_TRANSITION_PRE_DELAY)); } @@ -288,6 +299,7 @@ public final class RecentsActivity extends StatefulActivity { protected void onDestroy() { super.onDestroy(); ACTIVITY_TRACKER.onActivityDestroyed(this); + mActivityLaunchAnimationRunner = null; } @Override diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java index 04308c80cb..19c6588877 100644 --- a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java +++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java @@ -21,6 +21,8 @@ import android.content.Context; import android.os.Handler; import com.android.launcher3.LauncherAnimationRunner; +import com.android.launcher3.LauncherAnimationRunner.AnimationResult; +import com.android.launcher3.WrappedAnimationRunnerImpl; import com.android.launcher3.WrappedLauncherAnimationRunner; import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; @@ -28,14 +30,17 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat; public abstract class RemoteAnimationProvider { - LauncherAnimationRunner mAnimationRunner; + WrappedAnimationRunnerImpl mAnimationRunner; public abstract AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets, RemoteAnimationTargetCompat[] wallpaperTargets); ActivityOptions toActivityOptions(Handler handler, long duration, Context context) { - mAnimationRunner = new LauncherAnimationRunner(handler, - false /* startAtFrontOfQueue */) { + mAnimationRunner = new WrappedAnimationRunnerImpl() { + @Override + public Handler getHandler() { + return handler; + } @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets, @@ -45,7 +50,6 @@ public abstract class RemoteAnimationProvider { }; final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner( mAnimationRunner, false /* startAtFrontOfQueue */); - return ActivityOptionsCompat.makeRemoteAnimation( new RemoteAnimationAdapterCompat(wrapper, duration, 0)); } From f2711396822430800e9f7f110fa4b26902088b8c Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Mon, 28 Sep 2020 01:53:31 -0700 Subject: [PATCH 39/45] Thumbnail/Suggest view type support remote action Bug: 169330678 Change-Id: I629d3e6b1622bf71e0174eb2489e976ef98875ad --- res/layout/search_result_suggest.xml | 38 +++++ .../launcher3/allapps/AllAppsGridAdapter.java | 9 +- .../views/SearchResultSuggestRow.java | 131 ++++++++++++++++++ .../views/ThumbnailSearchResultView.java | 53 +++++-- .../systemui/plugins/shared/SearchTarget.java | 10 +- 5 files changed, 224 insertions(+), 17 deletions(-) create mode 100644 res/layout/search_result_suggest.xml create mode 100644 src/com/android/launcher3/views/SearchResultSuggestRow.java diff --git a/res/layout/search_result_suggest.xml b/res/layout/search_result_suggest.xml new file mode 100644 index 0000000000..c5d96f03ea --- /dev/null +++ b/res/layout/search_result_suggest.xml @@ -0,0 +1,38 @@ + + + + + + \ No newline at end of file diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java index 81d94ba9e5..8bc8e53af3 100644 --- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java +++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java @@ -98,6 +98,8 @@ public class AllAppsGridAdapter extends public static final int VIEW_TYPE_SEARCH_THUMBNAIL = 1 << 12; + public static final int VIEW_TYPE_SEARCH_SUGGEST = 1 << 13; + // Common view type masks public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER; public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON; @@ -189,7 +191,8 @@ public class AllAppsGridAdapter extends || viewType == VIEW_TYPE_SEARCH_ROW || viewType == VIEW_TYPE_SEARCH_PEOPLE || viewType == VIEW_TYPE_SEARCH_THUMBNAIL - || viewType == VIEW_TYPE_SEARCH_ICON_ROW; + || viewType == VIEW_TYPE_SEARCH_ICON_ROW + || viewType == VIEW_TYPE_SEARCH_SUGGEST; } } @@ -467,6 +470,9 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_THUMBNAIL: return new ViewHolder(mLayoutInflater.inflate( R.layout.search_result_thumbnail, parent, false)); + case VIEW_TYPE_SEARCH_SUGGEST: + return new ViewHolder(mLayoutInflater.inflate( + R.layout.search_result_suggest, parent, false)); default: throw new RuntimeException("Unexpected view type"); } @@ -554,6 +560,7 @@ public class AllAppsGridAdapter extends case VIEW_TYPE_SEARCH_ICON_ROW: case VIEW_TYPE_SEARCH_PEOPLE: case VIEW_TYPE_SEARCH_THUMBNAIL: + case VIEW_TYPE_SEARCH_SUGGEST: AdapterItemWithPayload item = (AdapterItemWithPayload) mApps.getAdapterItems().get(position); PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView; diff --git a/src/com/android/launcher3/views/SearchResultSuggestRow.java b/src/com/android/launcher3/views/SearchResultSuggestRow.java new file mode 100644 index 0000000000..b5abbcc724 --- /dev/null +++ b/src/com/android/launcher3/views/SearchResultSuggestRow.java @@ -0,0 +1,131 @@ +/* + * 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. + */ +package com.android.launcher3.views; + +import static com.android.systemui.plugins.shared.SearchTarget.ItemType.SUGGEST; + +import android.content.Context; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.launcher3.Launcher; +import com.android.launcher3.R; +import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload; +import com.android.launcher3.allapps.search.AllAppsSearchBarController; +import com.android.launcher3.model.data.ItemInfo; +import com.android.launcher3.model.data.RemoteActionItemInfo; +import com.android.launcher3.touch.ItemClickHandler; +import com.android.systemui.plugins.AllAppsSearchPlugin; +import com.android.systemui.plugins.shared.SearchTarget; +import com.android.systemui.plugins.shared.SearchTargetEvent; + +/** + * A view representing a fallback search suggestion row. + */ +public class SearchResultSuggestRow extends LinearLayout implements + View.OnClickListener, AllAppsSearchBarController.PayloadResultHandler { + + private final Object[] mTargetInfo = createTargetInfo(); + private AllAppsSearchPlugin mPlugin; + private AdapterItemWithPayload mAdapterItem; + private TextView mTitle; + + + public SearchResultSuggestRow(@NonNull Context context) { + super(context); + } + + public SearchResultSuggestRow(@NonNull Context context, + @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public SearchResultSuggestRow(@NonNull Context context, @Nullable AttributeSet attrs, + int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mTitle = findViewById(R.id.title); + setOnClickListener(this); + } + @Override + public void applyAdapterInfo(AdapterItemWithPayload adapterItemWithPayload) { + mAdapterItem = adapterItemWithPayload; + SearchTarget payload = adapterItemWithPayload.getPayload(); + mPlugin = adapterItemWithPayload.getPlugin(); + + if (payload.mRemoteAction != null) { + RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(payload.mRemoteAction, + payload.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN), + payload.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START)); + setTag(itemInfo); + } + showIfAvailable(mTitle, payload.mRemoteAction.getTitle().toString()); + setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT)); + adapterItemWithPayload.setSelectionHandler(this::handleSelection); + } + + @Override + public Object[] getTargetInfo() { + return mTargetInfo; + } + + private void handleSelection(int eventType) { + ItemInfo itemInfo = (ItemInfo) getTag(); + Launcher launcher = Launcher.getLauncher(getContext()); + if (itemInfo instanceof RemoteActionItemInfo) return; + + RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo; + ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo); + SearchTargetEvent searchTargetEvent = getSearchTargetEvent(SUGGEST, eventType); + searchTargetEvent.bundle = new Bundle(); + searchTargetEvent.remoteAction = remoteItemInfo.getRemoteAction(); + searchTargetEvent.bundle.putBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START, + remoteItemInfo.shouldStartInLauncher()); + searchTargetEvent.bundle.putString(SearchTarget.REMOTE_ACTION_TOKEN, + remoteItemInfo.getToken()); + + if (mPlugin != null) { + mPlugin.notifySearchTargetEvent(searchTargetEvent); + } + } + + @Override + public void onClick(View view) { + handleSelection(SearchTargetEvent.SELECT); + } + + private void showIfAvailable(TextView view, @Nullable String string) { + System.out.println("Plugin suggest string:" + string); + if (TextUtils.isEmpty(string)) { + view.setVisibility(GONE); + } else { + System.out.println("Plugin suggest string:" + string); + view.setVisibility(VISIBLE); + view.setText(string); + } + } +} diff --git a/src/com/android/launcher3/views/ThumbnailSearchResultView.java b/src/com/android/launcher3/views/ThumbnailSearchResultView.java index 1d58a063b9..bbc47739f3 100644 --- a/src/com/android/launcher3/views/ThumbnailSearchResultView.java +++ b/src/com/android/launcher3/views/ThumbnailSearchResultView.java @@ -18,8 +18,8 @@ package com.android.launcher3.views; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; import android.net.Uri; -import android.os.Bundle; import android.util.AttributeSet; import androidx.core.graphics.drawable.RoundedBitmapDrawable; @@ -28,6 +28,10 @@ import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; import com.android.launcher3.Launcher; import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload; import com.android.launcher3.allapps.search.AllAppsSearchBarController; +import com.android.launcher3.model.data.ItemInfo; +import com.android.launcher3.model.data.RemoteActionItemInfo; +import com.android.launcher3.model.data.WorkspaceItemInfo; +import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.util.Themes; import com.android.systemui.plugins.AllAppsSearchPlugin; import com.android.systemui.plugins.shared.SearchTarget; @@ -37,10 +41,9 @@ import com.android.systemui.plugins.shared.SearchTargetEvent; * A view representing a high confidence app search result that includes shortcuts */ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppCompatImageView - implements AllAppsSearchBarController.PayloadResultHandler { + implements AllAppsSearchBarController.PayloadResultHandler { private final Object[] mTargetInfo = createTargetInfo(); - Intent mIntent; AllAppsSearchPlugin mPlugin; int mPosition; @@ -58,26 +61,48 @@ public class ThumbnailSearchResultView extends androidx.appcompat.widget.AppComp private void handleSelection(int eventType) { Launcher launcher = Launcher.getLauncher(getContext()); - launcher.startActivitySafely(this, mIntent, null); - - SearchTargetEvent event = getSearchTargetEvent( - SearchTarget.ItemType.SCREENSHOT, eventType); + ItemInfo itemInfo = (ItemInfo) getTag(); + if (itemInfo instanceof RemoteActionItemInfo) { + RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo; + ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo); + } else { + ItemClickHandler.onClickAppShortcut(this, (WorkspaceItemInfo) itemInfo, launcher); + } if (mPlugin != null) { + SearchTargetEvent event = getSearchTargetEvent( + SearchTarget.ItemType.SCREENSHOT, eventType); mPlugin.notifySearchTargetEvent(event); } } @Override - public void applyAdapterInfo(AdapterItemWithPayload adapterItem) { + public void applyAdapterInfo(AdapterItemWithPayload adapterItem) { + Launcher launcher = Launcher.getLauncher(getContext()); mPosition = adapterItem.position; - RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(null, - (Bitmap) adapterItem.getPayload().getParcelable("bitmap")); + + SearchTarget target = adapterItem.getPayload(); + Bitmap bitmap; + if (target.mRemoteAction != null) { + RemoteActionItemInfo itemInfo = new RemoteActionItemInfo(target.mRemoteAction, + target.bundle.getString(SearchTarget.REMOTE_ACTION_TOKEN), + target.bundle.getBoolean(SearchTarget.REMOTE_ACTION_SHOULD_START)); + ItemClickHandler.onClickRemoteAction(launcher, itemInfo); + bitmap = ((BitmapDrawable) target.mRemoteAction.getIcon() + .loadDrawable(getContext())).getBitmap(); + setTag(itemInfo); + } else { + bitmap = (Bitmap) target.bundle.getParcelable("bitmap"); + WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(); + itemInfo.intent = new Intent(Intent.ACTION_VIEW) + .setData(Uri.parse(target.bundle.getString("uri"))) + .setType("image/*") + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + setTag(itemInfo); + } + RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(null, bitmap); drawable.setCornerRadius(Themes.getDialogCornerRadius(getContext())); setImageDrawable(drawable); - mIntent = new Intent(Intent.ACTION_VIEW) - .setData(Uri.parse(adapterItem.getPayload().getString("uri"))) - .setType("image/*") - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + setOnClickListener(v -> handleSelection(SearchTargetEvent.SELECT)); mPlugin = adapterItem.getPlugin(); adapterItem.setSelectionHandler(this::handleSelection); } diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java index 9d9ccbaf6e..3780b20926 100644 --- a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java +++ b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java @@ -80,7 +80,12 @@ public class SearchTarget implements Comparable { * N number of 1x1 ratio thumbnail is rendered. * (current N = 3) */ - THUMBNAIL(8); + THUMBNAIL(8), + + /** + * Fallback search icon and relevant text is rendered. + */ + SUGGEST(9); private final int mId; @@ -102,7 +107,8 @@ public class SearchTarget implements Comparable { SHORTCUT(5, "Shortcuts", ViewType.SHORTCUT), PEOPLE(6, "People", ViewType.PEOPLE), SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL), - REMOTE_ACTION(8, "Remote Actions", ViewType.SHORTCUT); + REMOTE_ACTION(8, "Remote Actions", ViewType.SHORTCUT), + SUGGEST(9, "Fallback Search", ViewType.SUGGEST); private final int mId; From de9a5e109d9636bd7e0f0e390658d33214c873d2 Mon Sep 17 00:00:00 2001 From: Hilary Huo Date: Fri, 25 Sep 2020 11:12:51 -0700 Subject: [PATCH 40/45] [pixel-search] Change Nasa actions title name Change-Id: I3e44513d797d867b97664ff2ee46a8e33d020e99 --- src/com/android/launcher3/views/SearchResultIconRow.java | 3 ++- .../com/android/systemui/plugins/shared/SearchTarget.java | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/com/android/launcher3/views/SearchResultIconRow.java b/src/com/android/launcher3/views/SearchResultIconRow.java index 57c85cf42e..313ae5e611 100644 --- a/src/com/android/launcher3/views/SearchResultIconRow.java +++ b/src/com/android/launcher3/views/SearchResultIconRow.java @@ -42,6 +42,7 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.touch.ItemClickHandler; import com.android.systemui.plugins.AllAppsSearchPlugin; import com.android.systemui.plugins.shared.SearchTarget; +import com.android.systemui.plugins.shared.SearchTarget.ItemType; import com.android.systemui.plugins.shared.SearchTargetEvent; /** @@ -138,7 +139,7 @@ public class SearchResultIconRow extends DoubleShadowBubbleTextView implements } else { RemoteActionItemInfo remoteItemInfo = (RemoteActionItemInfo) itemInfo; ItemClickHandler.onClickRemoteAction(launcher, remoteItemInfo); - searchTargetEvent = getSearchTargetEvent(SearchTarget.ItemType.REMOTE_ACTION, + searchTargetEvent = getSearchTargetEvent(ItemType.ACTION, eventType); searchTargetEvent.bundle = new Bundle(); searchTargetEvent.remoteAction = remoteItemInfo.getRemoteAction(); diff --git a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java index 3780b20926..3f0dc39cc1 100644 --- a/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java +++ b/src_plugins/com/android/systemui/plugins/shared/SearchTarget.java @@ -107,8 +107,9 @@ public class SearchTarget implements Comparable { SHORTCUT(5, "Shortcuts", ViewType.SHORTCUT), PEOPLE(6, "People", ViewType.PEOPLE), SCREENSHOT(7, "Screenshots", ViewType.THUMBNAIL), - REMOTE_ACTION(8, "Remote Actions", ViewType.SHORTCUT), - SUGGEST(9, "Fallback Search", ViewType.SUGGEST); + ACTION(8, "Actions", ViewType.SHORTCUT), + SUGGEST(9, "Fallback Search", ViewType.SUGGEST), + CHROME_TAB(10, "Chrome Tab", ViewType.SHORTCUT); private final int mId; From aff3e5263e19736961886e8295aa1529dae5478d Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 3 Sep 2020 17:01:56 -0700 Subject: [PATCH 41/45] Disable batching until the initial gesture is detected - Just doing other activity since that's the most common case for now Bug: 167732711 Change-Id: Icc910dbaf057893710c5f0bc6705e57cf8e3ee22 --- .../android/quickstep/TouchInteractionService.java | 4 +++- .../inputconsumers/OtherActivityInputConsumer.java | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 4b5adcb6c6..7bf8fbafac 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -683,7 +683,7 @@ public class TouchInteractionService extends Service implements PluginListener onCompleteCallback, - InputMonitorCompat inputMonitorCompat, boolean disableHorizontalSwipe, - Factory handlerFactory) { + InputMonitorCompat inputMonitorCompat, InputEventReceiver inputEventReceiver, + boolean disableHorizontalSwipe, Factory handlerFactory) { super(base); mDeviceState = deviceState; mNavBarPosition = mDeviceState.getNavBarPosition(); @@ -154,6 +156,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mOnCompleteCallback = onCompleteCallback; mVelocityTracker = VelocityTracker.obtain(); mInputMonitorCompat = inputMonitorCompat; + mInputEventReceiver = inputEventReceiver; boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning(); mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget; @@ -215,6 +218,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC switch (ev.getActionMasked()) { case ACTION_DOWN: { + // 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); mActivePointerId = ev.getPointerId(0); @@ -351,6 +357,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC } TestLogging.recordEvent(TestProtocol.SEQUENCE_PILFER, "pilferPointers"); mInputMonitorCompat.pilferPointers(); + // Once we detect the gesture, we can enable batching to reduce further updates + mInputEventReceiver.setBatchingEnabled(true); mActivityInterface.closeOverlay(); ActivityManagerWrapper.getInstance().closeSystemWindows( From 9fa2d8812aeec1033b6912f3f373080276a644ae Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Wed, 30 Sep 2020 10:57:04 -0700 Subject: [PATCH 42/45] Resolve race condition between @Before conditions Bug: 159671700 Change-Id: I5c96c32c171b7b539ce0ea799cf45955c2bee670 --- .../src/com/android/launcher3/ui/AbstractLauncherUiTest.java | 2 ++ tests/src/com/android/launcher3/ui/WorkTabTest.java | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 5e42d9b988..e118481570 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -279,6 +279,8 @@ public abstract class AbstractLauncherUiTest { if (userManager != null) { for (UserHandle userHandle : userManager.getUserProfiles()) { if (!userHandle.isSystem()) { + Log.d(TestProtocol.WORK_PROFILE_REMOVED, + "removing user " + userHandle.getIdentifier()); mDevice.executeShellCommand("pm remove-user " + userHandle.getIdentifier()); } } diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java index 488e763f94..8d594de926 100644 --- a/tests/src/com/android/launcher3/ui/WorkTabTest.java +++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java @@ -55,7 +55,9 @@ public class WorkTabTest extends AbstractLauncherUiTest { private static final int WORK_PAGE = AllAppsContainerView.AdapterHolder.WORK; @Before - public void createWorkProfile() throws Exception { + @Override + public void setUp() throws Exception { + super.setUp(); String output = mDevice.executeShellCommand( "pm create-user --profileOf 0 --managed TestProfile"); From 5e315bc7a905be743ff7ad511ce941cd2e7bdf56 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Wed, 30 Sep 2020 12:02:50 -0700 Subject: [PATCH 43/45] Draw BubbleTextView drawable behind ClipIconView during app close animation. The BubbleTextView drawable has built in shadows. Prior to this, we waited for the FloatingIconView to finish animating into place before fading in the BubbleTextView behind it. We did this to prevent the shadow from blinking in. Now that we've refactored FloatingIconView & ClipIconView, we draw the BubbleTextView behind the ClipIconView so that the shadow is revealed when the icon finishes clipping to its final shape and it no longer has to be faded in. Bug: 168608912 Change-Id: Ic0809f74ecbbec2f6e7caf7eca2fb560a8a02dec --- .../launcher3/views/FloatingIconView.java | 88 ++++++------------- 1 file changed, 28 insertions(+), 60 deletions(-) diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index 52a82f8e93..d9a14e9e3f 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -15,7 +15,6 @@ */ package com.android.launcher3.views; -import static com.android.launcher3.LauncherAnimUtils.DRAWABLE_ALPHA; import static com.android.launcher3.Utilities.getBadge; import static com.android.launcher3.Utilities.getFullDrawable; import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM; @@ -23,9 +22,6 @@ import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import static com.android.launcher3.views.IconLabelDotView.setIconAndDotVisible; import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; import android.annotation.TargetApi; import android.content.Context; import android.graphics.Canvas; @@ -74,7 +70,6 @@ public class FloatingIconView extends FrameLayout implements private static @Nullable IconLoadResult sIconLoadResult; public static final float SHAPE_PROGRESS_DURATION = 0.10f; - private static final int FADE_DURATION_MS = 200; private static final RectF sTmpRectF = new RectF(); private static final Object[] sTmpObjArray = new Object[1]; @@ -89,6 +84,9 @@ public class FloatingIconView extends FrameLayout implements private IconLoadResult mIconLoadResult; + // Draw the drawable of the BubbleTextView behind ClipIconView to reveal the built in shadow. + private View mBtvDrawable; + private ClipIconView mClipIconView; private @Nullable Drawable mBadge; @@ -98,7 +96,6 @@ public class FloatingIconView extends FrameLayout implements private final Rect mFinalDrawableBounds = new Rect(); - private AnimatorSet mFadeAnimatorSet; private ListenerView mListenerView; private Runnable mFastFinishRunnable; @@ -116,6 +113,8 @@ public class FloatingIconView extends FrameLayout implements mIsRtl = Utilities.isRtl(getResources()); mListenerView = new ListenerView(context, attrs); mClipIconView = new ClipIconView(context, attrs); + mBtvDrawable = new ImageView(context, attrs); + addView(mBtvDrawable); addView(mClipIconView); setWillNotDraw(false); } @@ -176,6 +175,7 @@ public class FloatingIconView extends FrameLayout implements setLayoutParams(lp); mClipIconView.setLayoutParams(new FrameLayout.LayoutParams(lp.width, lp.height)); + mBtvDrawable.setLayoutParams(new FrameLayout.LayoutParams(lp.width, lp.height)); } private void updatePosition(RectF pos, InsettableFrameLayout.LayoutParams lp) { @@ -292,6 +292,8 @@ public class FloatingIconView extends FrameLayout implements drawable = drawable == null ? null : drawable.getConstantState().newDrawable(); int iconOffset = getOffsetForIconBounds(l, drawable, pos); synchronized (iconLoadResult) { + iconLoadResult.btvDrawable = btvIcon == null || drawable == btvIcon + ? null : btvIcon.getConstantState().newDrawable(); iconLoadResult.drawable = drawable; iconLoadResult.badge = badge; iconLoadResult.iconOffset = iconOffset; @@ -311,7 +313,8 @@ public class FloatingIconView extends FrameLayout implements * @param iconOffset The amount of offset needed to match this view with the original view. */ @UiThread - private void setIcon(@Nullable Drawable drawable, @Nullable Drawable badge, int iconOffset) { + private void setIcon(@Nullable Drawable drawable, @Nullable Drawable badge, + @Nullable Drawable btvIcon, int iconOffset) { final InsettableFrameLayout.LayoutParams lp = (InsettableFrameLayout.LayoutParams) getLayoutParams(); mBadge = badge; @@ -342,6 +345,10 @@ public class FloatingIconView extends FrameLayout implements mBadge.setBounds(0, 0, clipViewOgWidth, clipViewOgHeight); } } + + if (!mIsOpening && btvIcon != null) { + mBtvDrawable.setBackground(btvIcon); + } invalidate(); } @@ -360,7 +367,7 @@ public class FloatingIconView extends FrameLayout implements synchronized (mIconLoadResult) { if (mIconLoadResult.isIconLoaded) { setIcon(mIconLoadResult.drawable, mIconLoadResult.badge, - mIconLoadResult.iconOffset); + mIconLoadResult.btvDrawable, mIconLoadResult.iconOffset); setIconAndDotVisible(originalView, false); } else { mIconLoadResult.onIconLoaded = () -> { @@ -369,7 +376,7 @@ public class FloatingIconView extends FrameLayout implements } setIcon(mIconLoadResult.drawable, mIconLoadResult.badge, - mIconLoadResult.iconOffset); + mIconLoadResult.btvDrawable, mIconLoadResult.iconOffset); setVisibility(VISIBLE); setIconAndDotVisible(originalView, false); @@ -434,10 +441,6 @@ public class FloatingIconView extends FrameLayout implements mEndRunnable.run(); mEndRunnable = null; } - if (mFadeAnimatorSet != null) { - mFadeAnimatorSet.end(); - mFadeAnimatorSet = null; - } } @Override @@ -546,8 +549,16 @@ public class FloatingIconView extends FrameLayout implements setIconAndDotVisible(originalView, true); view.finish(dragLayer); } else { - view.mFadeAnimatorSet = view.createFadeAnimation(originalView, dragLayer); - view.mFadeAnimatorSet.start(); + originalView.setVisibility(VISIBLE); + if (originalView instanceof IconLabelDotView) { + setIconAndDotVisible(originalView, true); + } + if (originalView instanceof BubbleTextView) { + BubbleTextView btv = (BubbleTextView) originalView; + btv.setIconVisible(true); + btv.setForceHideDot(true); + } + view.finish(dragLayer); } } else { view.finish(dragLayer); @@ -564,47 +575,6 @@ public class FloatingIconView extends FrameLayout implements return view; } - private AnimatorSet createFadeAnimation(View originalView, DragLayer dragLayer) { - AnimatorSet fade = new AnimatorSet(); - fade.setDuration(FADE_DURATION_MS); - fade.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - originalView.setVisibility(VISIBLE); - } - - @Override - public void onAnimationEnd(Animator animation) { - finish(dragLayer); - } - }); - - if (originalView instanceof IconLabelDotView) { - fade.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - setIconAndDotVisible(originalView, true); - } - }); - } - - if (originalView instanceof BubbleTextView) { - BubbleTextView btv = (BubbleTextView) originalView; - fade.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - btv.setIconVisible(true); - btv.setForceHideDot(true); - } - }); - fade.play(ObjectAnimator.ofInt(btv.getIcon(), DRAWABLE_ALPHA, 0, 255)); - } else if (!(originalView instanceof FolderIcon)) { - fade.play(ObjectAnimator.ofFloat(originalView, ALPHA, 0f, 1f)); - } - - return fade; - } - private void finish(DragLayer dragLayer) { ((ViewGroup) dragLayer.getParent()).removeView(this); dragLayer.removeView(mListenerView); @@ -628,11 +598,7 @@ public class FloatingIconView extends FrameLayout implements mLoadIconSignal = null; mEndRunnable = null; mFinalDrawableBounds.setEmpty(); - if (mFadeAnimatorSet != null) { - mFadeAnimatorSet.cancel(); - } mPositionOut = null; - mFadeAnimatorSet = null; mListenerView.setListener(null); mOriginalIcon = null; mOnTargetChangeRunnable = null; @@ -640,11 +606,13 @@ public class FloatingIconView extends FrameLayout implements sTmpObjArray[0] = null; mIconLoadResult = null; mClipIconView.recycle(); + mBtvDrawable.setBackground(null); mFastFinishRunnable = null; } private static class IconLoadResult { final ItemInfo itemInfo; + Drawable btvDrawable; Drawable drawable; Drawable badge; int iconOffset; From 2ec0ade64a4b4228caa8881a55d3cb02e434e3a1 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Thu, 24 Sep 2020 13:27:30 -0700 Subject: [PATCH 44/45] Add sandbox mode to gesture tutorial settings. Test: manual Added a Sandbox mode tutorial fragment and controller. This fragment allows the user to try all the gesture commands and receive feedback, whether the gesture was successful or not. Preview: https://drive.google.com/file/d/1Qmn71ZHMOrv2XjUngb6S4W5jOaBIvF1_/view?usp=sharing Change-Id: I7d28ce25daa38fa6d05b18d43d02b77c1fc8a264 --- quickstep/res/values/strings.xml | 15 +++ .../SandboxModeTutorialController.java | 102 ++++++++++++++++++ .../SandboxModeTutorialFragment.java | 43 ++++++++ .../interaction/TutorialController.java | 6 +- .../interaction/TutorialFragment.java | 2 + .../settings/DeveloperOptionsFragment.java | 9 ++ 6 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java create mode 100644 quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml index 769d29838a..b913ba4480 100644 --- a/quickstep/res/values/strings.xml +++ b/quickstep/res/values/strings.xml @@ -149,6 +149,21 @@ Try swiping further + + Sandbox Mode + + Try any navigation gesture + + Back gesture successful + + Assistant gesture successful + + Home gesture successful + + Overview gesture successful + + Make sure you swipe from the left/right edge of the screen + All set diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java new file mode 100644 index 0000000000..d54efc56e5 --- /dev/null +++ b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java @@ -0,0 +1,102 @@ +/* + * 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. + */ +package com.android.quickstep.interaction; + +import android.graphics.PointF; +import android.view.View; + +import androidx.annotation.Nullable; + +import com.android.launcher3.R; +import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult; +import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult; + +/** A {@link TutorialController} for the Sandbox Mode. */ +public class SandboxModeTutorialController extends SwipeUpGestureTutorialController { + + SandboxModeTutorialController(SandboxModeTutorialFragment fragment, TutorialType tutorialType) { + super(fragment, tutorialType); + } + + @Nullable + @Override + Integer getTitleStringId() { + return R.string.sandbox_mode_title; + } + + @Nullable + @Override + Integer getSubtitleStringId() { + return R.string.sandbox_mode_subtitle; + } + + @Nullable + @Override + Integer getActionButtonStringId() { + return R.string.gesture_tutorial_action_button_label_done; + } + + @Override + void onActionButtonClicked(View button) { + mTutorialFragment.closeTutorial(); + } + + @Override + public void onBackGestureAttempted(BackGestureResult result) { + switch (result) { + case BACK_COMPLETED_FROM_LEFT: + case BACK_COMPLETED_FROM_RIGHT: + showRippleEffect(null); + showFeedback(R.string.sandbox_mode_back_gesture_feedback_successful); + break; + case BACK_CANCELLED_FROM_RIGHT: + showFeedback(R.string.back_gesture_feedback_cancelled_right_edge); + break; + case BACK_CANCELLED_FROM_LEFT: + showFeedback(R.string.back_gesture_feedback_cancelled_left_edge); + break; + case BACK_NOT_STARTED_TOO_FAR_FROM_EDGE: + showFeedback(R.string.sandbox_mode_back_gesture_feedback_swipe_too_far_from_edge); + break; + } + } + + @Override + public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) { + switch (result) { + case ASSISTANT_COMPLETED: + showRippleEffect(null); + showFeedback(R.string.sandbox_mode_assistant_gesture_feedback_successful); + break; + case HOME_GESTURE_COMPLETED: + animateFakeTaskViewHome(finalVelocity, () -> { + showFeedback(R.string.sandbox_mode_home_gesture_feedback_successful); + }); + break; + case OVERVIEW_GESTURE_COMPLETED: + fadeOutFakeTaskView(true, () -> { + showFeedback(R.string.sandbox_mode_overview_gesture_feedback_successful); + }); + break; + case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION: + case HOME_OR_OVERVIEW_CANCELLED: + case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE: + case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE: + showFeedback(R.string.home_gesture_feedback_swipe_too_far_from_edge); + break; + } + } +} diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java new file mode 100644 index 0000000000..955a2f7d2e --- /dev/null +++ b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java @@ -0,0 +1,43 @@ +/* + * 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. + */ +package com.android.quickstep.interaction; + +import android.view.MotionEvent; +import android.view.View; + +import com.android.quickstep.interaction.TutorialController.TutorialType; + +/** Shows the general navigation gesture sandbox environment. */ +public class SandboxModeTutorialFragment extends TutorialFragment { + + @Override + TutorialController createController(TutorialType type) { + return new SandboxModeTutorialController(this, type); + } + + @Override + Class getControllerClass() { + return SandboxModeTutorialController.class; + } + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + if (motionEvent.getAction() == MotionEvent.ACTION_DOWN && mTutorialController != null) { + mTutorialController.setRippleHotspot(motionEvent.getX(), motionEvent.getY()); + } + return super.onTouch(view, motionEvent); + } +} diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java index d0a12679c0..2198ade105 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java @@ -213,7 +213,8 @@ abstract class TutorialController implements BackGestureAttemptCallback, return mTutorialType == TutorialType.BACK_NAVIGATION_COMPLETE || mTutorialType == TutorialType.HOME_NAVIGATION_COMPLETE || mTutorialType == TutorialType.OVERVIEW_NAVIGATION_COMPLETE - || mTutorialType == TutorialType.ASSISTANT_COMPLETE; + || mTutorialType == TutorialType.ASSISTANT_COMPLETE + || mTutorialType == TutorialType.SANDBOX_MODE; } /** Denotes the type of the tutorial. */ @@ -226,6 +227,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, OVERVIEW_NAVIGATION, OVERVIEW_NAVIGATION_COMPLETE, ASSISTANT, - ASSISTANT_COMPLETE + ASSISTANT_COMPLETE, + SANDBOX_MODE } } diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java index 559ba354d2..f297d5a835 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java @@ -76,6 +76,8 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { case ASSISTANT: case ASSISTANT_COMPLETE: return new AssistantGestureTutorialFragment(); + case SANDBOX_MODE: + return new SandboxModeTutorialFragment(); default: Log.e(LOG_TAG, "Failed to find an appropriate fragment for " + tutorialType.name()); } diff --git a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java index 4baecb7c56..f4b059d8d8 100644 --- a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java +++ b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java @@ -306,6 +306,15 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat { return true; }); sandboxCategory.addPreference(launchAssistantTutorialPreference); + Preference launchSandboxModeTutorialPreference = new Preference(context); + launchSandboxModeTutorialPreference.setKey("launchSandboxMode"); + launchSandboxModeTutorialPreference.setTitle("Launch Sandbox Mode"); + launchSandboxModeTutorialPreference.setSummary("Practice navigation gestures"); + launchSandboxModeTutorialPreference.setOnPreferenceClickListener(preference -> { + startActivity(launchSandboxIntent.putExtra("tutorial_type", "SANDBOX_MODE")); + return true; + }); + sandboxCategory.addPreference(launchSandboxModeTutorialPreference); } private String toName(String action) { From c8cbd822b5a61cceb265821a9c7794dc9e9219aa Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Sun, 27 Sep 2020 12:10:06 -0700 Subject: [PATCH 45/45] Fix logic around launchTask in the live tile case When how things are structured changed in the past 1-2 releases, we have dup logic in launchTask. There are two cases - Swipe down from Overview: RecentsView#createTaskLaunchAnimation. In endListener, call launchTask in the non live tile case, and call finishRecentsAnimation in the live tile case - Tap on the TaskView to launch task: In the non live tile case, call launchTask as it calls startActivity with option. In the live tile, currently we call createLaunchAnimationForRunningTask, which plays the task launch animation, which calls finishRecentsAnimation at the end. But this animation is not sufficient, when the user swipes the live tile task off to the right and tries to launch it. We will need to replace this animation with createRecentsWindowAnimator Fixes: 169516051 Test: manual Change-Id: Id764d6787175bcdb1c82adb8e4743af192a1fd9d --- .../android/quickstep/views/RecentsView.java | 7 ++++++- .../com/android/quickstep/views/TaskView.java | 20 ++----------------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 4bfa4da42a..7a8e11df78 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -2161,7 +2161,12 @@ public abstract class RecentsView extends PagedView tv.notifyTaskLaunchFailed(TAG); } }; - tv.launchTask(false, onLaunchResult, getHandler()); + if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { + finishRecentsAnimation(false /* toRecents */, null); + onLaunchResult.accept(true /* success */); + } else { + tv.launchTask(false, onLaunchResult, getHandler()); + } Task task = tv.getTask(); if (task != null) { mActivity.getStatsLogManager().logger().withItemInfo(tv.getItemInfo()) diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 8fbf44b572..686f8785c5 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -217,6 +217,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { if (isRunningTask()) { + // TODO: Replace this animation with createRecentsWindowAnimator createLaunchAnimationForRunningTask().start(); } else { launchTask(true /* animate */); @@ -364,10 +365,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { final PendingAnimation pendingAnimation = getRecentsView().createTaskLaunchAnimation( this, RECENTS_LAUNCH_DURATION, TOUCH_RESPONSE_INTERPOLATOR); AnimatorPlaybackController currentAnimation = pendingAnimation.createPlaybackController(); - currentAnimation.setEndAction(() -> { - pendingAnimation.finish(true); - launchTask(false); - }); + currentAnimation.setEndAction(() -> pendingAnimation.finish(true)); return currentAnimation; } @@ -390,20 +388,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { public void launchTask(boolean animate, boolean freezeTaskList, Consumer resultCallback, Handler resultCallbackHandler) { - if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { - if (isRunningTask()) { - getRecentsView().finishRecentsAnimation(false /* toRecents */, - () -> resultCallbackHandler.post(() -> resultCallback.accept(true))); - } else { - launchTaskInternal(animate, freezeTaskList, resultCallback, resultCallbackHandler); - } - } else { - launchTaskInternal(animate, freezeTaskList, resultCallback, resultCallbackHandler); - } - } - - private void launchTaskInternal(boolean animate, boolean freezeTaskList, - Consumer resultCallback, Handler resultCallbackHandler) { if (mTask != null) { final ActivityOptions opts; TestLogging.recordEvent(