From 690543f1594723a420a036b5392e9d2a1e8df27b Mon Sep 17 00:00:00 2001 From: Andy Wickham Date: Mon, 1 Jun 2020 12:27:20 -0700 Subject: [PATCH 01/59] Removes Sandbox from launcher task. Instead, adds it to the gesture-exclusion activities to prevent normal gesture handling. Bug: 148542211 Change-Id: Ie04d2e71346a0c039e73fcc386cedc1b74fadadb --- quickstep/AndroidManifest-launcher.xml | 2 +- quickstep/AndroidManifest.xml | 1 - quickstep/res/values/config.xml | 4 +++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml index 527bfc3854..60afddb0a8 100644 --- a/quickstep/AndroidManifest-launcher.xml +++ b/quickstep/AndroidManifest-launcher.xml @@ -52,7 +52,7 @@ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" android:resizeableActivity="true" android:resumeWhilePausing="true" - android:taskAffinity="${packageName}.launcher" + android:taskAffinity="" android:enabled="true"> diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index b2286f1bd7..00b09513b5 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -99,7 +99,6 @@ android:name="com.android.quickstep.interaction.GestureSandboxActivity" android:autoRemoveFromRecents="true" android:excludeFromRecents="true" - android:taskAffinity="${packageName}.launcher" android:screenOrientation="portrait"> diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml index 2b11ca0fff..0f2955bfcf 100644 --- a/quickstep/res/values/config.xml +++ b/quickstep/res/values/config.xml @@ -17,7 +17,9 @@ - + + com.android.launcher3/com.android.quickstep.interaction.GestureSandboxActivity + com.android.quickstep.logging.StatsLogCompatManager From 45564c831ba985f1f944d4a65134df8a1011f512 Mon Sep 17 00:00:00 2001 From: vadimt Date: Wed, 10 Jun 2020 18:40:58 -0700 Subject: [PATCH 02/59] Removing debug requests from non-debug test info handlers Bug: 152629799 Bug: 153670015 Change-Id: I02776be811d1d3325b35880d19d25a6638f904ef --- Android.mk | 5 +- ext_tests/res/values/overrides.xml | 5 + .../testing/DebugTestInformationHandler.java | 141 ++++++++++++++++++ .../QuickstepTestInformationHandler.java | 38 ++--- .../testing/TestInformationHandler.java | 119 +-------------- .../launcher3/ui/AbstractLauncherUiTest.java | 3 +- .../com/android/launcher3/tapl/AllApps.java | 7 +- .../tapl/LauncherInstrumentation.java | 9 +- 8 files changed, 178 insertions(+), 149 deletions(-) create mode 100644 ext_tests/res/values/overrides.xml create mode 100644 ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java diff --git a/Android.mk b/Android.mk index fcd4a94efc..7805b32e8e 100644 --- a/Android.mk +++ b/Android.mk @@ -67,7 +67,10 @@ LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3CommonDepsLib LOCAL_SRC_FILES := \ $(call all-java-files-under, src) \ $(call all-java-files-under, src_shortcuts_overrides) \ - $(call all-java-files-under, src_ui_overrides) + $(call all-java-files-under, src_ui_overrides) \ + $(call all-java-files-under, ext_tests/src) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/ext_tests/res LOCAL_PROGUARD_FLAG_FILES := proguard.flags # Proguard is disable for testing. Derivarive prjects to keep proguard enabled diff --git a/ext_tests/res/values/overrides.xml b/ext_tests/res/values/overrides.xml new file mode 100644 index 0000000000..3f071d4219 --- /dev/null +++ b/ext_tests/res/values/overrides.xml @@ -0,0 +1,5 @@ + + + com.android.launcher3.testing.DebugTestInformationHandler + + diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java new file mode 100644 index 0000000000..b84c7aa8e8 --- /dev/null +++ b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java @@ -0,0 +1,141 @@ +/* + * 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.testing; + +import static android.graphics.Bitmap.Config.ARGB_8888; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.os.Bundle; +import android.os.Debug; +import android.system.Os; +import android.view.View; + +import androidx.annotation.Keep; + +import java.util.LinkedList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Class to handle requests from tests, including debug ones. + */ +public class DebugTestInformationHandler extends TestInformationHandler { + private static LinkedList sLeaks; + + public DebugTestInformationHandler(Context context) { + init(context); + } + + private static void runGcAndFinalizersSync() { + Runtime.getRuntime().gc(); + Runtime.getRuntime().runFinalization(); + + final CountDownLatch fence = new CountDownLatch(1); + createFinalizationObserver(fence); + try { + do { + Runtime.getRuntime().gc(); + Runtime.getRuntime().runFinalization(); + } while (!fence.await(100, TimeUnit.MILLISECONDS)); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + } + + // Create the observer in the scope of a method to minimize the chance that + // it remains live in a DEX/machine register at the point of the fence guard. + // This must be kept to avoid R8 inlining it. + @Keep + private static void createFinalizationObserver(CountDownLatch fence) { + new Object() { + @Override + protected void finalize() throws Throwable { + try { + fence.countDown(); + } finally { + super.finalize(); + } + } + }; + } + + @Override + public Bundle call(String method) { + final Bundle response = new Bundle(); + switch (method) { + case TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS: { + return getLauncherUIProperty(Bundle::putInt, + l -> l.getAppsView().getAppsStore().getDeferUpdatesFlags()); + } + + case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING: + TestProtocol.sDebugTracing = true; + return response; + + case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING: + TestProtocol.sDebugTracing = false; + return response; + + case TestProtocol.REQUEST_PID: { + response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, Os.getpid()); + return response; + } + + case TestProtocol.REQUEST_TOTAL_PSS_KB: { + runGcAndFinalizersSync(); + Debug.MemoryInfo mem = new Debug.MemoryInfo(); + Debug.getMemoryInfo(mem); + response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, mem.getTotalPss()); + return response; + } + + case TestProtocol.REQUEST_JAVA_LEAK: { + if (sLeaks == null) sLeaks = new LinkedList(); + + // Allocate and dirty the memory. + final int leakSize = 1024 * 1024; + final byte[] bytes = new byte[leakSize]; + for (int i = 0; i < leakSize; i += 239) { + bytes[i] = (byte) (i % 256); + } + sLeaks.add(bytes); + return response; + } + + case TestProtocol.REQUEST_NATIVE_LEAK: { + if (sLeaks == null) sLeaks = new LinkedList(); + + // Allocate and dirty a bitmap. + final Bitmap bitmap = Bitmap.createBitmap(512, 512, ARGB_8888); + bitmap.eraseColor(Color.RED); + sLeaks.add(bitmap); + return response; + } + + case TestProtocol.REQUEST_VIEW_LEAK: { + if (sLeaks == null) sLeaks = new LinkedList(); + sLeaks.add(new View(mContext)); + return response; + } + + default: + return super.call(method); + } + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java index a28dabc6a3..1fc7aa4eed 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java @@ -4,21 +4,18 @@ import android.app.Activity; import android.content.Context; import android.os.Bundle; +import com.android.launcher3.LauncherState; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.testing.TestInformationHandler; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController; import com.android.quickstep.util.LayoutUtils; -import com.android.systemui.shared.recents.model.Task; - -import java.util.ArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; public class QuickstepTestInformationHandler extends TestInformationHandler { - private final Context mContext; + protected final Context mContext; + public QuickstepTestInformationHandler(Context context) { mContext = context; } @@ -27,6 +24,15 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { public Bundle call(String method) { final Bundle response = new Bundle(); switch (method) { + case TestProtocol.REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT: { + return getLauncherUIProperty(Bundle::putInt, l -> { + final float progress = LauncherState.OVERVIEW.getVerticalProgress(l) + - LauncherState.ALL_APPS.getVerticalProgress(l); + final float distance = l.getAllAppsController().getShiftRange() * progress; + return (int) distance; + }); + } + case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: { final float swipeHeight = LayoutUtils.getDefaultSwipeHeight(mContext, mDeviceProfile); @@ -47,26 +53,6 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { Bundle::putInt, PortraitStatesTouchController::getHotseatTop); } - case TestProtocol.REQUEST_RECENT_TASKS_LIST: { - ArrayList taskBaseIntentComponents = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(1); - RecentsModel.INSTANCE.get(mContext).getTasks((tasks) -> { - for (Task t : tasks) { - taskBaseIntentComponents.add( - t.key.baseIntent.getComponent().flattenToString()); - } - latch.countDown(); - }); - try { - latch.await(2, TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - response.putStringArrayList(TestProtocol.TEST_INFO_RESPONSE_FIELD, - taskBaseIntentComponents); - return response; - } - case TestProtocol.REQUEST_OVERVIEW_ACTIONS_ENABLED: { response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()); diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java index e786f07237..38b3712f6e 100644 --- a/src/com/android/launcher3/testing/TestInformationHandler.java +++ b/src/com/android/launcher3/testing/TestInformationHandler.java @@ -15,27 +15,17 @@ */ package com.android.launcher3.testing; -import static android.graphics.Bitmap.Config.ARGB_8888; - import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Color; import android.graphics.Insets; import android.os.Build; import android.os.Bundle; -import android.os.Debug; -import android.system.Os; -import android.util.Log; -import android.view.View; import android.view.WindowInsets; -import androidx.annotation.Keep; - import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Launcher; @@ -44,10 +34,7 @@ import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.util.ResourceBasedOverride; -import java.util.LinkedList; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Supplier; @@ -65,7 +52,6 @@ public class TestInformationHandler implements ResourceBasedOverride { protected Context mContext; protected DeviceProfile mDeviceProfile; protected LauncherAppState mLauncherAppState; - private static LinkedList mLeaks; public void init(Context context) { mContext = context; @@ -77,15 +63,6 @@ public class TestInformationHandler implements ResourceBasedOverride { public Bundle call(String method) { final Bundle response = new Bundle(); switch (method) { - case TestProtocol.REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT: { - return getLauncherUIProperty(Bundle::putInt, l -> { - final float progress = LauncherState.OVERVIEW.getVerticalProgress(l) - - LauncherState.ALL_APPS.getVerticalProgress(l); - final float distance = l.getAllAppsController().getShiftRange() * progress; - return (int) distance; - }); - } - case TestProtocol.REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT: { return getLauncherUIProperty(Bundle::putInt, l -> { final float progress = LauncherState.NORMAL.getVerticalProgress(l) @@ -99,14 +76,6 @@ public class TestInformationHandler implements ResourceBasedOverride { return getUIProperty(Bundle::putBoolean, t -> isLauncherInitialized(), () -> true); } - case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING: - TestProtocol.sDebugTracing = true; - break; - - case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING: - TestProtocol.sDebugTracing = false; - break; - case TestProtocol.REQUEST_FREEZE_APP_LIST: return getLauncherUIProperty(Bundle::putBoolean, l -> { l.getAppsView().getAppsStore().enableDeferUpdates(DEFER_UPDATES_TEST); @@ -118,11 +87,6 @@ public class TestInformationHandler implements ResourceBasedOverride { return true; }); - case TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS: { - return getLauncherUIProperty(Bundle::putInt, - l -> l.getAppsView().getAppsStore().getDeferUpdatesFlags()); - } - case TestProtocol.REQUEST_APPS_LIST_SCROLL_Y: { return getLauncherUIProperty(Bundle::putInt, l -> l.getAppsView().getActiveRecyclerView().getCurrentScrollY()); @@ -137,59 +101,19 @@ public class TestInformationHandler implements ResourceBasedOverride { }, this::getCurrentActivity); } - case TestProtocol.REQUEST_PID: { - response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, Os.getpid()); - break; - } - - case TestProtocol.REQUEST_TOTAL_PSS_KB: { - runGcAndFinalizersSync(); - Debug.MemoryInfo mem = new Debug.MemoryInfo(); - Debug.getMemoryInfo(mem); - response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, mem.getTotalPss()); - break; - } - - case TestProtocol.REQUEST_JAVA_LEAK: { - if (mLeaks == null) mLeaks = new LinkedList(); - - // Allocate and dirty the memory. - final int leakSize = 1024 * 1024; - final byte[] bytes = new byte[leakSize]; - for (int i = 0; i < leakSize; i += 239) { - bytes[i] = (byte) (i % 256); - } - mLeaks.add(bytes); - break; - } - - case TestProtocol.REQUEST_NATIVE_LEAK: { - if (mLeaks == null) mLeaks = new LinkedList(); - - // Allocate and dirty a bitmap. - final Bitmap bitmap = Bitmap.createBitmap(512, 512, ARGB_8888); - bitmap.eraseColor(Color.RED); - mLeaks.add(bitmap); - break; - } - - case TestProtocol.REQUEST_VIEW_LEAK: { - if (mLeaks == null) mLeaks = new LinkedList(); - mLeaks.add(new View(mContext)); - break; - } - case TestProtocol.REQUEST_ICON_HEIGHT: { response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, mDeviceProfile.allAppsCellHeightPx); - break; + return response; } case TestProtocol.REQUEST_MOCK_SENSOR_ROTATION: TestProtocol.sDisableSensorRotation = true; - break; + return response; + + default: + return null; } - return response; } protected boolean isLauncherInitialized() { @@ -201,22 +125,6 @@ public class TestInformationHandler implements ResourceBasedOverride { return Launcher.ACTIVITY_TRACKER.getCreatedActivity(); } - private static void runGcAndFinalizersSync() { - Runtime.getRuntime().gc(); - Runtime.getRuntime().runFinalization(); - - final CountDownLatch fence = new CountDownLatch(1); - createFinalizationObserver(fence); - try { - do { - Runtime.getRuntime().gc(); - Runtime.getRuntime().runFinalization(); - } while (!fence.await(100, TimeUnit.MILLISECONDS)); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - } - /** * Returns the result by getting a Launcher property on UI thread */ @@ -257,21 +165,4 @@ public class TestInformationHandler implements ResourceBasedOverride { */ void set(Bundle b, String key, T value); } - - // Create the observer in the scope of a method to minimize the chance that - // it remains live in a DEX/machine register at the point of the fence guard. - // This must be kept to avoid R8 inlining it. - @Keep - private static void createFinalizationObserver(CountDownLatch fence) { - new Object() { - @Override - protected void finalize() throws Throwable { - try { - fence.countDown(); - } finally { - super.finalize(); - } - } - }; - } } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 7cce044105..3d39d254b1 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -294,7 +294,8 @@ public abstract class AbstractLauncherUiTest { // Limits UI tests affecting tests running after them. mLauncher.waitForLauncherInitialized(); if (mLauncherPid != 0) { - assertEquals("Launcher crashed, pid mismatch:", mLauncherPid, mLauncher.getPid()); + assertEquals("Launcher crashed, pid mismatch:", + mLauncherPid, mLauncher.getPid().intValue()); } checkDetectedLeaks(mLauncher); } diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index 808be6644b..b6c17df730 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -18,6 +18,7 @@ package com.android.launcher3.tapl; import android.graphics.Point; import android.graphics.Rect; +import android.os.Bundle; import android.widget.TextView; import androidx.annotation.NonNull; @@ -244,8 +245,8 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { } private void verifyNotFrozen(String message) { - mLauncher.assertEquals(message, 0, mLauncher.getTestInfo( - TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS). - getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD)); + final Bundle testInfo = mLauncher.getTestInfo(TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS); + if (testInfo == null) return; + mLauncher.assertEquals(message, 0, testInfo.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD)); } } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 7ddb49275c..9f4d9cea43 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -1309,8 +1309,9 @@ public final class LauncherInstrumentation { getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD); } - public int getPid() { - return getTestInfo(TestProtocol.REQUEST_PID).getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD); + public Integer getPid() { + final Bundle testInfo = getTestInfo(TestProtocol.REQUEST_PID); + return testInfo != null ? testInfo.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD) : null; } public void produceJavaLeak() { @@ -1338,13 +1339,13 @@ public final class LauncherInstrumentation { public Closable eventsCheck() { Assert.assertTrue("Nested event checking", !sCheckingEvents); disableSensorRotation(); - final int initialPid = getPid(); + final Integer initialPid = getPid(); if (sEventChecker == null) sEventChecker = new LogEventChecker(); sEventChecker.start(); sCheckingEvents = true; return () -> { - if (initialPid != getPid()) { + if (initialPid != null && initialPid.intValue() != getPid()) { if (mOnLauncherCrashed != null) mOnLauncherCrashed.run(); checkForAnomaly(); Assert.fail( From 9459f3101fdf6f43c8998eea03a71df1a7434d13 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 15 Jun 2020 13:30:20 -0500 Subject: [PATCH 03/59] Don't reset RecentsView in onIdpChanged() Resetting unloads visible task data and thus will leave recents blank if overview state is enabled. Instead, unload and reload visible task data to take new icon shape into account. (The reason we're getting onIdpChanged() on nav bar mode change is because the change in nav bar height causes the computed icon size to change very slightly.) Also fix InvariantDeviceProfile copy constructor by copying iconBitmapSize. Test: - Change between 0 button and 3 button nav modes, verify recents doesn't appear blank - Change icon shape in Styles and Wallpapers and go to recents, verify icon shape is reflected in task icons Bug: 156354328 Change-Id: Ife29f51e85814ff483d055005fa2645135d5ec3d --- .../src/com/android/quickstep/views/RecentsView.java | 3 ++- src/com/android/launcher3/InvariantDeviceProfile.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) 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 f27bedb8d4..f0055b1fa7 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 @@ -487,7 +487,8 @@ public abstract class RecentsView extends PagedView impl return; } mModel.getIconCache().clear(); - reset(); + unloadVisibleTaskData(); + loadVisibleTaskData(); } public void init(OverviewActionsView actionsView) { diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 60abc66b2b..e39e89c038 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -148,6 +148,7 @@ public class InvariantDeviceProfile { iconSize = p.iconSize; iconShapePath = p.iconShapePath; landscapeIconSize = p.landscapeIconSize; + iconBitmapSize = p.iconBitmapSize; iconTextSize = p.iconTextSize; numHotseatIcons = p.numHotseatIcons; numAllAppsColumns = p.numAllAppsColumns; From 8cd8d158867d415710c4a022f34371c032c6bb41 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 15 Jun 2020 13:41:41 -0700 Subject: [PATCH 04/59] Fixing sysui scrim not updating in landscape UI Bug: 156422012 Change-Id: I2e1e9149e8337dd663bf564bd1b7f661ec2864e9 --- .../android/quickstep/views/ShelfScrimView.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java index bec3050dad..19e278be3c 100644 --- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java +++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java @@ -244,13 +244,17 @@ public class ShelfScrimView extends ScrimView @Override protected void updateSysUiColors() { - // Use a light system UI (dark icons) if all apps is behind at least half of the - // status bar. - boolean forceChange = mShelfTop <= mLauncher.getDeviceProfile().getInsets().top / 2f; - if (forceChange) { - mLauncher.getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, !mIsScrimDark); + if (mDrawingFlatColor) { + super.updateSysUiColors(); } else { - mLauncher.getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, 0); + // Use a light system UI (dark icons) if all apps is behind at least half of the + // status bar. + boolean forceChange = mShelfTop <= mLauncher.getDeviceProfile().getInsets().top / 2f; + if (forceChange) { + mLauncher.getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, !mIsScrimDark); + } else { + mLauncher.getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, 0); + } } } From 80846543b58d54dcd357e2139417b2ffa6fdba01 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 15 Jun 2020 19:00:50 -0500 Subject: [PATCH 05/59] Fix qsb when flinging to home during gesture to overview from home - AllAppsTransitionController should not animate alphas for atomic components even when failing fast (we already had this check for the normal flow where mProgress != targetProgress). - Don't set state to NORMAL until both the workspace stagger anim and overview peek anim are finished Test: swipe up and hold from the nav bar on the home screen, then, without lifting finger, fling upwards to return home; ensure qsb springs in staggered formation with rest of workspace, and alpha matches accordingly Bug: 154637581 Change-Id: Iafeaeac50ee8bce05492628d443c3ca4ab3d26df --- ...ButtonNavbarToOverviewTouchController.java | 26 ++++++++++++++++--- .../util/StaggeredWorkspaceAnim.java | 5 ++++ .../allapps/AllAppsTransitionController.java | 4 ++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java index 966e25bff5..4cc8256360 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java @@ -24,6 +24,7 @@ import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK; import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC; +import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.graphics.PointF; @@ -59,6 +60,8 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo private boolean mDidTouchStartInNavBar; private boolean mReachedOverview; + private boolean mIsOverviewRehidden; + private boolean mIsHomeStaggeredAnimFinished; // The last recorded displacement before we reached overview. private PointF mStartDisplacement = new PointF(); @@ -144,6 +147,13 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo } } + // Used if flinging back to home after reaching overview + private void maybeSwipeInteractionToHomeComplete() { + if (mIsHomeStaggeredAnimFinished && mIsOverviewRehidden) { + onSwipeInteractionCompleted(NORMAL, Touch.FLING); + } + } + @Override protected boolean handlingOverviewAnim() { return mDidTouchStartInNavBar && super.handlingOverviewAnim(); @@ -180,9 +190,17 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo stateManager.goToState(NORMAL, true, () -> onSwipeInteractionCompleted(NORMAL, Touch.FLING)); } else { + mIsHomeStaggeredAnimFinished = mIsOverviewRehidden = false; + StaggeredWorkspaceAnim staggeredWorkspaceAnim = new StaggeredWorkspaceAnim( mLauncher, velocity, false /* animateOverviewScrim */); - staggeredWorkspaceAnim.start(); + staggeredWorkspaceAnim.addAnimatorListener(new AnimationSuccessListener() { + @Override + public void onAnimationSuccess(Animator animator) { + mIsHomeStaggeredAnimFinished = true; + maybeSwipeInteractionToHomeComplete(); + } + }).start(); // StaggeredWorkspaceAnim doesn't animate overview, so we handle it here. stateManager.cancelAnimation(); @@ -191,8 +209,10 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK; AnimatorSet anim = stateManager.createAtomicAnimation( stateManager.getState(), NORMAL, config); - anim.addListener(AnimationSuccessListener.forRunnable( - () -> onSwipeInteractionCompleted(NORMAL, Touch.SWIPE))); + anim.addListener(AnimationSuccessListener.forRunnable(() -> { + mIsOverviewRehidden = true; + maybeSwipeInteractionToHomeComplete(); + })); anim.start(); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java index 8daa98254a..3cafd423ca 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java @@ -175,6 +175,11 @@ public class StaggeredWorkspaceAnim { return mAnimators; } + public StaggeredWorkspaceAnim addAnimatorListener(Animator.AnimatorListener listener) { + mAnimators.addListener(listener); + return this; + } + /** * Starts the animation. */ diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index 1dd81e8305..a9b030e056 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -159,7 +159,9 @@ public class AllAppsTransitionController implements StateHandler, StateAnimationConfig config, PendingAnimation builder) { float targetProgress = toState.getVerticalProgress(mLauncher); if (Float.compare(mProgress, targetProgress) == 0) { - setAlphas(toState, config, builder); + if (!config.onlyPlayAtomicComponent()) { + setAlphas(toState, config, builder); + } // Fail fast onProgressAnimationEnd(); return; From d396e6ab66929a3db04103241a65a005f5dcbd30 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Mon, 15 Jun 2020 22:10:06 -0700 Subject: [PATCH 06/59] Change folder edit name hint opacity to 54% Bug: 157773141 Change-Id: Ia224ac429ad4225390b5d726b3385105a2494a37 --- res/values/styles.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values/styles.xml b/res/values/styles.xml index a922183b42..ac00488a08 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -50,7 +50,7 @@ #CDFFFFFF ?android:attr/colorPrimary #FF212121 - #FF616161 + #89616161 #CCFFFFFF ?android:attr/textColorSecondary #FF212121 @@ -106,7 +106,7 @@ #DD3C4043 #FF80868B @android:color/white - #FFCCCCCC + #89CCCCCC true #99FFFFFF #B3FFFFFF From 746b82e831b0f47afd47eb0e07708e6fe921a21f Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Mon, 15 Jun 2020 15:45:56 -0700 Subject: [PATCH 07/59] Updated recents oriented state on split screen Launcher defaults to sensor rotation when in split screen instead of the fixed portrait orientation. We were setting the multi window flag but never updating RecentsOrientedState's internal state to reflect it. Fixes: 158537350 Change-Id: Ib0e1cf4c2e0674a5af41ac11c532a50db0a6f0fa --- .../quickstep/LauncherActivityInterface.java | 4 +--- .../android/quickstep/views/RecentsView.java | 21 ++++++++++++------- .../quickstep/util/RecentsOrientedState.java | 2 -- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java index 675172377c..edefbe1252 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java @@ -120,9 +120,7 @@ public final class LauncherActivityInterface extends @Override public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState, boolean activityVisible, Consumer callback) { - ((RecentsView) getCreatedActivity().getOverviewPanel()) - .setLayoutRotation(deviceState.getCurrentActiveRotation(), - deviceState.getDisplayRotation()); + notifyRecentsOfOrientation(deviceState); DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) { @Override public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, 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 873c672625..a1de1fe684 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 @@ -208,7 +208,7 @@ public abstract class RecentsView extends PagedView impl } }; - protected final RecentsOrientedState mOrientationState; + protected RecentsOrientedState mOrientationState; protected final BaseActivityInterface mSizeStrategy; protected RecentsAnimationController mRecentsAnimationController; protected RecentsAnimationTargets mRecentsAnimationTargets; @@ -371,11 +371,17 @@ public abstract class RecentsView extends PagedView impl private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener = (inMultiWindowMode) -> { - if (!inMultiWindowMode && mOverviewStateEnabled) { - // TODO: Re-enable layout transitions for addition of the unpinned task - reloadIfNeeded(); - } - }; + if (mOrientationState != null) { + mOrientationState.setMultiWindowMode(inMultiWindowMode); + setLayoutRotation(mOrientationState.getTouchRotation(), + mOrientationState.getDisplayRotation()); + rotateAllChildTasks(); + } + if (!inMultiWindowMode && mOverviewStateEnabled) { + // TODO: Re-enable layout transitions for addition of the unpinned task + reloadIfNeeded(); + } + }; public RecentsView(Context context, AttributeSet attrs, int defStyleAttr, BaseActivityInterface sizeStrategy) { @@ -840,7 +846,6 @@ public abstract class RecentsView extends PagedView impl private void resetPaddingFromTaskSize() { DeviceProfile dp = mActivity.getDeviceProfile(); - mOrientationState.setMultiWindowMode(dp.isMultiWindowMode); getTaskSize(mTempRect); mTaskWidth = mTempRect.width(); mTaskHeight = mTempRect.height(); @@ -1639,7 +1644,7 @@ public abstract class RecentsView extends PagedView impl : View.LAYOUT_DIRECTION_RTL); mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated()); mActivity.getDragLayer().recreateControllers(); - boolean isInLandscape = touchRotation != 0 + boolean isInLandscape = mOrientationState.getTouchRotation() != 0 || mOrientationState.getLauncherRotation() != ROTATION_0; mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, !mOrientationState.canLauncherRotate() && isInLandscape); diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java index 8bd2281c46..7949ce9eca 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java +++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java @@ -123,7 +123,6 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre private final ContentResolver mContentResolver; private final SharedPreferences mSharedPrefs; private final OrientationEventListener mOrientationListener; - private final BaseActivityInterface mSizeStrategy; private final Matrix mTmpMatrix = new Matrix(); @@ -140,7 +139,6 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre mContext = context; mContentResolver = context.getContentResolver(); mSharedPrefs = Utilities.getPrefs(context); - mSizeStrategy = sizeStrategy; mOrientationListener = new OrientationEventListener(context) { @Override public void onOrientationChanged(int degrees) { From 826bb2e932e59c68d9771b032ebc5a0ca75cf77d Mon Sep 17 00:00:00 2001 From: Sreyas Date: Tue, 16 Jun 2020 12:20:02 -0700 Subject: [PATCH 08/59] Fixing OAV buttons not working and removing logs. Bug: 154838868 Change-Id: Icde83dc527a1aacf6a8a79325e6a33c5235a64fb --- .../src/com/android/quickstep/views/OverviewActionsView.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java index 95eb10ff2e..0c21c5de42 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java @@ -24,7 +24,6 @@ import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; import android.util.AttributeSet; -import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.FrameLayout; @@ -117,7 +116,6 @@ public class OverviewActionsView extends FrameLayo @Override public void onClick(View view) { if (mCallbacks == null) { - Log.d("OverviewActionsView", "Callbacks null onClick"); return; } int id = view.getId(); From 6a3de331afc6b16d0d5b9451debe601b862f7796 Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 16 Jun 2020 13:20:12 -0700 Subject: [PATCH 09/59] Attempt to workaround a leak on Taimen It's a flake. It was likely caused by enabling fallback tests, and we don't know what's leaked and why. Bug: 143488140 Change-Id: I0d0c88ac9b0de316861f16ba023a596c1f39cde4 --- .../tests/src/com/android/quickstep/FallbackRecentsTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java index a343e7c31c..ffe55b62e4 100644 --- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java +++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java @@ -120,6 +120,8 @@ public class FallbackRecentsTest { TestCommandReceiver.callCommand(TestCommandReceiver.DISABLE_TEST_LAUNCHER); UiDevice.getInstance(getInstrumentation()).executeShellCommand( getLauncherCommand(getLauncherInMyProcess())); + // b/143488140 + mLauncher.pressHome(); } } }; From 345f728f2ccd39bf2e0acdc366c71f0d74521dff Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Tue, 16 Jun 2020 13:22:51 -0700 Subject: [PATCH 10/59] Create hotseat predictor onCreate ModelTask posted in setupViews does not get called. Bug: 159151258 Change-Id: I45bfe7cf8ea18b09faaf3c0e612be90722e1e410 --- .../launcher3/uioverrides/QuickstepLauncher.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 77d71a3ff2..48fe4d7c87 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -29,6 +29,7 @@ import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import android.content.Intent; import android.content.res.Configuration; +import android.os.Bundle; import android.util.Log; import android.view.View; @@ -88,12 +89,19 @@ public class QuickstepLauncher extends BaseQuickstepLauncher { public static final AsyncCommand SET_SHELF_HEIGHT = (context, arg1, arg2) -> SystemUiProxy.INSTANCE.get(context).setShelfHeight(arg1 != 0, arg2); + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (mHotseatPredictionController != null) { + mHotseatPredictionController.createPredictor(); + } + } + @Override protected void setupViews() { super.setupViews(); if (FeatureFlags.ENABLE_HYBRID_HOTSEAT.get()) { mHotseatPredictionController = new HotseatPredictionController(this); - mHotseatPredictionController.createPredictor(); } } From eb957403a8633595c1147d44320fdadf5cfa0061 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Tue, 16 Jun 2020 14:33:01 -0700 Subject: [PATCH 11/59] Increase Predicted app icon sing size Bug: 159041772 Change-Id: I0b71c6a2b2da9e4b058554e60cf0c59d242368c6 --- .../src/com/android/launcher3/uioverrides/PredictedAppIcon.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java index 0ace4cc0c7..597c17b4e2 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java @@ -57,7 +57,7 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView implements LauncherAccessibilityDelegate.AccessibilityActionHandler { private static final int RING_SHADOW_COLOR = 0x99000000; - private static final float RING_EFFECT_RATIO = 0.08f; + private static final float RING_EFFECT_RATIO = 0.095f; boolean mIsDrawingDot = false; private final DeviceProfile mDeviceProfile; From 8798440600bfdf4c166b8d36f9e0bf77ca6d5d29 Mon Sep 17 00:00:00 2001 From: Becky Qiu Date: Tue, 16 Jun 2020 15:18:41 -0700 Subject: [PATCH 12/59] [Overview Actions] Disable swiping on modal recentsView for talkback. When it is select mode, disabling swiping on the parent container for a11y to avoid exiting select mode UI. This will only disable swiping and talkback on other tasks and the cleanall button, but will keep the modal task container app info and content description, also keep the action buttons description working. Test: local Bug: 155947513 Change-Id: I6d513c7eb3e7deeaa233550749f8be0d95e56daf --- .../src/com/android/quickstep/views/RecentsView.java | 2 ++ 1 file changed, 2 insertions(+) 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 2066d52c36..43e9660ba6 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 @@ -1728,6 +1728,8 @@ public abstract class RecentsView extends PagedView impl setPivotY(mTempPointF.y); setTaskModalness(mTaskModalness); updatePageOffsets(); + setImportantForAccessibility(isModal() ? IMPORTANT_FOR_ACCESSIBILITY_NO + : IMPORTANT_FOR_ACCESSIBILITY_AUTO); } private void updatePageOffsets() { From e8c0f83fb289aeb7ffae97a54bc714374df1eb86 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Tue, 16 Jun 2020 14:24:49 -0700 Subject: [PATCH 13/59] Avoid Crash when longpressing disabled predicted item If a view does not handle its long press and return true, View.java calls getParent().showContextMenuForChild(this). However, in Hybrid hotseat case, predicted icons are removed from the hotseat when user long presses an icon. This will result in getParent() returning null. Bug: 159064799 Change-Id: I80d8f27cbc20b94b0381e767584a1f6854d17e2c --- .../launcher3/hybridhotseat/HotseatPredictionController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java index 30a34e46eb..b34d3cdbf1 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java @@ -122,7 +122,7 @@ public class HotseatPredictionController implements DragController.DragListener, if (mLauncher.getWorkspace().isSwitchingState()) return false; // Start the drag mLauncher.getWorkspace().beginDragShared(v, this, new DragOptions()); - return false; + return true; }; public HotseatPredictionController(Launcher launcher) { From 8401308c147dac901e27d189f870099d2d40ce3a Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Tue, 16 Jun 2020 19:41:16 -0700 Subject: [PATCH 14/59] Don't rely on nav mode change listener for oriented state When nav mode state changes, launcher gets re-instantiated, which means the listener for nav mode changes often gets destroyed before it even gets fired. Rely on the initial setup to set the correct nav mode. The other bug with relying on the initial value was that we were initially getting the old nav mode when initFlags was called from the ctor, but then the correct updated nav mode when called from initListeners(). The first call would enable rotation but then the second call wasn't disabling it. Now we toggled based on nav mode each time. Another bug fix in RecentsView was not calling update when launcher rotation is enabled. That was added when previously we were using HOME_ROTATED and PORTRAIT as different PagedViewHandlers to differentiate when launcher rotation was enabled. HOME_ROTATED is now removed, so we no longer need to change the internal state of RecentsOrientedState. Fixes: 159176222 Change-Id: I2a37880ce3cf835ca5b9b165ce3840537facee6c --- .../android/quickstep/views/RecentsView.java | 3 +- .../quickstep/util/RecentsOrientedState.java | 29 ++----------------- 2 files changed, 4 insertions(+), 28 deletions(-) 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 873c672625..caff7135f7 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 @@ -1053,8 +1053,7 @@ public abstract class RecentsView extends PagedView impl private void animateRecentsRotationInPlace(int newRotation) { if (mOrientationState.canLauncherRotate()) { - // Update the rotation but let system take care of the rotation animation - setLayoutRotation(newRotation, mOrientationState.getDisplayRotation()); + // Let system take care of the rotation return; } AnimatorSet pa = setRecentsChangedOrientation(true); diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java index 8bd2281c46..2acc49c17a 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java +++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java @@ -116,9 +116,6 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE | FLAG_SYSTEM_ROTATION_ALLOWED | FLAG_ROTATION_WATCHER_SUPPORTED | FLAG_ROTATION_WATCHER_ENABLED; - private SysUINavigationMode.NavigationModeChangeListener mNavModeChangeListener = - newMode -> setFlag(FLAG_ROTATION_WATCHER_SUPPORTED, newMode != TWO_BUTTONS); - private final Context mContext; private final ContentResolver mContentResolver; private final SharedPreferences mSharedPrefs; @@ -268,10 +265,9 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre private void initFlags() { SysUINavigationMode.Mode currentMode = SysUINavigationMode.getMode(mContext); - if (mOrientationListener.canDetectOrientation() && - currentMode != TWO_BUTTONS) { - mFlags |= FLAG_ROTATION_WATCHER_SUPPORTED; - } + boolean rotationWatcherSupported = mOrientationListener.canDetectOrientation() && + currentMode != TWO_BUTTONS; + setFlag(FLAG_ROTATION_WATCHER_SUPPORTED, rotationWatcherSupported); // initialize external flags updateAutoRotateSetting(); @@ -288,9 +284,6 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre mContentResolver.registerContentObserver( Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), false, mSystemAutoRotateObserver); - SysUINavigationMode.Mode currentMode = - SysUINavigationMode.INSTANCE.get(mContext) - .addModeChangeListener(mNavModeChangeListener); } initFlags(); } @@ -302,8 +295,6 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre if (isMultipleOrientationSupportedByDevice()) { mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this); mContentResolver.unregisterContentObserver(mSystemAutoRotateObserver); - SysUINavigationMode.INSTANCE.get(mContext) - .removeModeChangeListener(mNavModeChangeListener); } setRotationWatcherEnabled(false); } @@ -349,20 +340,6 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre setFlag(FLAG_ROTATION_WATCHER_ENABLED, isEnabled); } - public int getTouchRotationDegrees() { - switch (mTouchRotation) { - case ROTATION_90: - return 90; - case ROTATION_180: - return 180; - case ROTATION_270: - return 270; - case ROTATION_0: - default: - return 0; - } - } - /** * Returns the scale and pivot so that the provided taskRect can fit the provided full size */ From d8405a63d23d78797b32df7ae037761591f49630 Mon Sep 17 00:00:00 2001 From: thiruram Date: Tue, 16 Jun 2020 18:01:36 -0700 Subject: [PATCH 15/59] Replace StatsLogManager with builder pattern. Follow up CLs will remove the deprecating log methods and update their references. Bug: 159170445 Change-Id: I5dfd30209eeba561df1b528a6305ca5923ba42a2 --- .../logging/StatsLogCompatManager.java | 152 ++++++++++-------- .../launcher3/logging/StatsLogManager.java | 56 +++++++ 2 files changed, 143 insertions(+), 65 deletions(-) diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java index e820b3f6c5..3dd9e8bd47 100644 --- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java +++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java @@ -47,6 +47,7 @@ import com.android.launcher3.util.LogConfig; import com.android.systemui.shared.system.SysUiStatsLog; import java.util.ArrayList; +import java.util.OptionalInt; /** * This class calls StatsLog compile time generated methods. @@ -73,12 +74,17 @@ public class StatsLogCompatManager extends StatsLogManager { sContext = context; } + @Override + public StatsLogger logger() { + return new StatsCompatLogger(); + } + /** * Logs a {@link EventEnum}. */ @Override public void log(EventEnum event) { - log(event, DEFAULT_INSTANCE_ID, (ItemInfo) null); + logger().log(event); } /** @@ -86,7 +92,7 @@ public class StatsLogCompatManager extends StatsLogManager { */ @Override public void log(EventEnum event, InstanceId instanceId) { - log(event, instanceId, (ItemInfo) null); + logger().withInstanceId(instanceId).log(event); } /** @@ -94,7 +100,7 @@ public class StatsLogCompatManager extends StatsLogManager { */ @Override public void log(EventEnum event, @Nullable ItemInfo info) { - log(event, DEFAULT_INSTANCE_ID, info); + logger().withItemInfo(info).log(event); } /** @@ -109,9 +115,8 @@ public class StatsLogCompatManager extends StatsLogManager { @Override public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) { - write(event, instanceId, atomInfo, null, - LAUNCHER_UICHANGED__DST_STATE__HOME, - LAUNCHER_UICHANGED__DST_STATE__BACKGROUND); + write(event, instanceId, atomInfo, LAUNCHER_UICHANGED__DST_STATE__HOME, + LAUNCHER_UICHANGED__DST_STATE__BACKGROUND, OptionalInt.empty()); } }); } @@ -127,9 +132,7 @@ public class StatsLogCompatManager extends StatsLogManager { int dstState) { write(event, DEFAULT_INSTANCE_ID, atomItemInfo == null ? LauncherAtom.ItemInfo.getDefaultInstance() : atomItemInfo, - null, - srcState, - dstState); + srcState, dstState, OptionalInt.empty()); } /** @@ -138,10 +141,7 @@ public class StatsLogCompatManager extends StatsLogManager { @Override public void log(EventEnum event, InstanceId instanceId, @Nullable ItemInfo info) { - logInternal(event, instanceId, info, - LAUNCHER_UICHANGED__DST_STATE__HOME, - LAUNCHER_UICHANGED__DST_STATE__BACKGROUND, - DEFAULT_PAGE_INDEX); + logger().withItemInfo(info).withInstanceId(instanceId).log(event); } /** @@ -163,65 +163,21 @@ public class StatsLogCompatManager extends StatsLogManager { */ @Override public void log(EventEnum event, int srcState, int dstState, int pageIndex) { - logInternal(event, DEFAULT_INSTANCE_ID, null, srcState, dstState, pageIndex); + logger().withSrcState(srcState).withDstState(dstState).log(event); } - /** - * Logs an event and accompanying {@link InstanceId} and {@link ItemInfo}. - */ - private void logInternal(EventEnum event, InstanceId instanceId, - @Nullable ItemInfo info, int srcState, int dstState, int pageIndex) { - - LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask( - new BaseModelUpdateTask() { - @Override - public void execute(LauncherAppState app, BgDataModel dataModel, - AllAppsList apps) { - writeEvent(event, instanceId, info, srcState, dstState, pageIndex, - dataModel.folders); - } - }); - } - - private static void writeEvent(EventEnum event, InstanceId instanceId, - @Nullable ItemInfo info, int srcState, int dstState, int pageIndex, - IntSparseArrayMap folders) { - - if (!Utilities.ATLEAST_R) { - return; - } - LauncherAtom.ItemInfo atomInfo = LauncherAtom.ItemInfo.getDefaultInstance(); - if (info != null) { - if (info.container >= 0) { - atomInfo = info.buildProto(folders.get(info.container)); - } else { - atomInfo = info.buildProto(); - } - } else { - if (srcState == LAUNCHER_UICHANGED__DST_STATE__HOME - || dstState == LAUNCHER_UICHANGED__SRC_STATE__HOME) { - atomInfo = LauncherAtom.ItemInfo.newBuilder().setContainerInfo( - LauncherAtom.ContainerInfo.newBuilder().setWorkspace( - LauncherAtom.WorkspaceContainer.newBuilder().setPageIndex(pageIndex) - )).build(); - } - } - write(event, instanceId, atomInfo, info, srcState, dstState); - } - - private static void write(EventEnum event, InstanceId instanceId, + private void write(EventEnum event, InstanceId instanceId, LauncherAtom.ItemInfo atomInfo, - @Nullable ItemInfo info, - int srcState, int dstState) { + int srcState, int dstState, OptionalInt mRank) { if (IS_VERBOSE) { String name = (event instanceof Enum) ? ((Enum) event).name() : event.getId() + ""; Log.d(TAG, instanceId == DEFAULT_INSTANCE_ID - ? String.format("\n%s (State:%s->%s) \n%s\n%s", name, getStateString(srcState), - getStateString(dstState), info, atomInfo) - : String.format("\n%s (State:%s->%s) (InstanceId:%s)\n%s\n%s", name, - getStateString(srcState), getStateString(dstState), instanceId, info, + ? String.format("\n%s (State:%s->%s)\n%s", name, getStateString(srcState), + getStateString(dstState), atomInfo) + : String.format("\n%s (State:%s->%s) (InstanceId:%s)\n%s", name, + getStateString(srcState), getStateString(dstState), instanceId, atomInfo)); } @@ -246,7 +202,7 @@ public class StatsLogCompatManager extends StatsLogManager { getPageId(atomInfo, true) /* page_id_parent */, getHierarchy(atomInfo) /* hierarchy */, atomInfo.getIsWork() /* is_work_profile */, - atomInfo.getRank() /* rank */, + mRank.orElse(atomInfo.getRank()) /* rank */, atomInfo.getFolderIcon().getFromLabelState().getNumber() /* fromState */, atomInfo.getFolderIcon().getToLabelState().getNumber() /* toState */, atomInfo.getFolderIcon().getLabelInfo() /* edittext */, @@ -319,6 +275,72 @@ public class StatsLogCompatManager extends StatsLogManager { info.getWidget().getSpanY()); } + /** + * Helps to construct and write statsd compatible log message. + */ + private class StatsCompatLogger implements StatsLogger { + private ItemInfo mItemInfo = new ItemInfo(); + private InstanceId mInstanceId = DEFAULT_INSTANCE_ID; + private OptionalInt mRank = OptionalInt.empty(); + private int mSrcState = LAUNCHER_UICHANGED__SRC_STATE__HOME; + private int mDstState = LAUNCHER_UICHANGED__DST_STATE__BACKGROUND; + + @Override + public StatsLogger withItemInfo(ItemInfo itemInfo) { + this.mItemInfo = itemInfo; + return this; + } + + @Override + public StatsLogger withInstanceId(InstanceId instanceId) { + this.mInstanceId = instanceId; + return this; + } + + @Override + public StatsLogger withRank(int rank) { + this.mRank = OptionalInt.of(rank); + return this; + } + + @Override + public StatsLogger withSrcState(int srcState) { + this.mSrcState = srcState; + return this; + } + + @Override + public StatsLogger withDstState(int dstState) { + this.mDstState = dstState; + return this; + } + + @Override + public void log(EventEnum event) { + if (!Utilities.ATLEAST_R) { + return; + } + + if (mItemInfo.container < 0) { + // Item is not within a folder. Write to StatsLog in same thread. + write(event, mInstanceId, mItemInfo.buildProto(), mSrcState, mDstState, mRank); + } else { + // Item is inside the folder, fetch folder info in a BG thread + // and then write to StatsLog. + LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask( + new BaseModelUpdateTask() { + @Override + public void execute(LauncherAppState app, BgDataModel dataModel, + AllAppsList apps) { + FolderInfo folderInfo = dataModel.folders.get(mItemInfo.container); + write(event, mInstanceId, mItemInfo.buildProto(folderInfo), + mSrcState, mDstState, mRank); + } + }); + } + } + } + private static int getCardinality(LauncherAtom.ItemInfo info) { return info.getContainerInfo().getContainerCase().equals(PREDICTED_HOTSEAT_CONTAINER) ? info.getContainerInfo().getPredictedHotseatContainer().getCardinality() diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index c84b9fe487..fac5bf4ea3 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -181,6 +181,62 @@ public class StatsLogManager implements ResourceBasedOverride { } } + /** + * Helps to construct and write the log message. + */ + public interface StatsLogger { + + /** + * Sets log fields from provided {@link ItemInfo}. + */ + default StatsLogger withItemInfo(ItemInfo itemInfo) { + return this; + } + + + /** + * Sets {@link InstanceId} of log message. + */ + default StatsLogger withInstanceId(InstanceId instanceId) { + return this; + } + + /** + * Sets rank field of log message. + */ + default StatsLogger withRank(int rank) { + return this; + } + + /** + * Sets source launcher state field of log message. + */ + default StatsLogger withSrcState(int srcState) { + return this; + } + + /** + * Sets destination launcher state field of log message. + */ + default StatsLogger withDstState(int dstState) { + return this; + } + + /** + * Builds the final message and logs it as {@link EventEnum}. + */ + default void log(EventEnum event) { + } + } + + /** + * Returns new logger object. + */ + public StatsLogger logger() { + return new StatsLogger() { + }; + } + protected LogStateProvider mStateProvider; /** From d8e5660b13efdc6c517cf628847a1c04c8e386f4 Mon Sep 17 00:00:00 2001 From: vadimt Date: Wed, 17 Jun 2020 10:19:51 -0700 Subject: [PATCH 16/59] Fixing broken tests on 2 and 3 button devices. Bug: 143488140 Change-Id: I30886da129825b800984baa08742ac4dfcf4a599 --- .../tests/src/com/android/quickstep/FallbackRecentsTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java index ffe55b62e4..bd8ab0860b 100644 --- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java +++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java @@ -121,7 +121,8 @@ public class FallbackRecentsTest { UiDevice.getInstance(getInstrumentation()).executeShellCommand( getLauncherCommand(getLauncherInMyProcess())); // b/143488140 - mLauncher.pressHome(); + mDevice.pressHome(); + mDevice.waitForIdle(); } } }; From c6a38ba5d8a3fbc1ac49f84cbfe635a6a1feaf76 Mon Sep 17 00:00:00 2001 From: thiruram Date: Tue, 16 Jun 2020 18:58:13 -0700 Subject: [PATCH 17/59] Replaces StatsLogManager.log with StatsLogManager.logger() Bug: 159170445 Change-Id: Ice6c8a9ae30d8e6b3843bfe42926053849bf9fe0 --- .../hybridhotseat/HotseatEduController.java | 2 +- .../hybridhotseat/HotseatEduDialog.java | 6 +-- .../quickstep/TaskShortcutFactory.java | 7 +-- .../quickstep/views/AllAppsEduView.java | 2 +- .../android/quickstep/views/RecentsView.java | 8 ++-- .../com/android/quickstep/views/TaskView.java | 6 ++- .../logging/StatsLogCompatManager.java | 43 ------------------- .../launcher3/BaseDraggingActivity.java | 3 +- .../android/launcher3/DeleteDropTarget.java | 8 ++-- .../launcher3/SecondaryDropTarget.java | 12 ++++-- src/com/android/launcher3/Workspace.java | 39 ++++++----------- src/com/android/launcher3/folder/Folder.java | 6 +-- .../android/launcher3/folder/FolderIcon.java | 4 +- .../launcher3/logging/StatsLogManager.java | 43 ------------------- .../notification/NotificationInfo.java | 4 +- .../launcher3/popup/RemoteActionShortcut.java | 4 +- .../launcher3/popup/SystemShortcut.java | 7 +-- .../launcher3/touch/ItemClickHandler.java | 3 +- .../touch/WorkspaceTouchListener.java | 2 +- .../launcher3/views/OptionsPopupView.java | 2 +- 20 files changed, 61 insertions(+), 150 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java index 5d807d33f8..522a2dc969 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java @@ -265,7 +265,7 @@ public class HotseatEduController { requiresMigration ? R.string.hotseat_tip_no_empty_slots : R.string.hotseat_auto_enrolled), mHotseat.getTop()); - mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_ONLY_TIP); + mLauncher.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_ONLY_TIP); finishOnboarding(); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java index 96be5dfe11..2b3f3953ea 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java @@ -112,13 +112,13 @@ public class HotseatEduDialog extends AbstractSlideInView implements Insettable mHotseatEduController.moveHotseatItems(); mHotseatEduController.finishOnboarding(); - mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_ACCEPT); + mLauncher.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_ACCEPT); } private void onDismiss(View v) { mHotseatEduController.showDimissTip(); mHotseatEduController.finishOnboarding(); - mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_DENY); + mLauncher.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_DENY); handleClose(true); } @@ -212,7 +212,7 @@ public class HotseatEduDialog extends AbstractSlideInView implements Insettable } AbstractFloatingView.closeAllOpenViews(mLauncher); attachToContainer(); - mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_SEEN); + mLauncher.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_SEEN); animateOpen(); populatePreview(predictions); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java index 4eae437f8d..ff051b6db7 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java @@ -196,7 +196,8 @@ public interface TaskShortcutFactory { WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture( future, animStartedListener, mHandler, true /* scaleUp */, taskKey.displayId); - mTarget.getStatsLogManager().log(mLauncherEvent, mTaskView.getItemInfo()); + mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo()) + .log(mLauncherEvent); } } } @@ -296,8 +297,8 @@ public interface TaskShortcutFactory { }; mTaskView.launchTask(true, resultCallback, Executors.MAIN_EXECUTOR.getHandler()); dismissTaskMenuView(mTarget); - mTarget.getStatsLogManager().log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP, - mTaskView.getItemInfo()); + mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo()) + .log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java index 6b99f904c3..0979c071bb 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java @@ -232,7 +232,7 @@ public class AllAppsEduView extends AbstractFloatingView { launcher, parent); view.init(launcher); launcher.getDragLayer().addView(view); - launcher.getStatsLogManager().log(LAUNCHER_ALL_APPS_EDU_SHOWN); + launcher.getStatsLogManager().logger().log(LAUNCHER_ALL_APPS_EDU_SHOWN); view.requestLayout(); view.playAnimation(); 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 43e9660ba6..bdfc15c63b 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 @@ -1347,8 +1347,8 @@ public abstract class RecentsView extends PagedView impl ComponentKey compKey = TaskUtils.getLaunchComponentKeyForTask(taskView.getTask().key); mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss( endState.logAction, Direction.UP, index, compKey); - mActivity.getStatsLogManager().log( - LAUNCHER_TASK_DISMISS_SWIPE_UP, taskView.getItemInfo()); + mActivity.getStatsLogManager().logger().withItemInfo(taskView.getItemInfo()) + .log(LAUNCHER_TASK_DISMISS_SWIPE_UP); } } @@ -1942,8 +1942,8 @@ public abstract class RecentsView extends PagedView impl mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss( endState.logAction, Direction.DOWN, indexOfChild(tv), TaskUtils.getLaunchComponentKeyForTask(task.key)); - mActivity.getStatsLogManager().log( - LAUNCHER_TASK_LAUNCH_SWIPE_DOWN, tv.getItemInfo()); + mActivity.getStatsLogManager().logger().withItemInfo(tv.getItemInfo()) + .log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN); } } else { onTaskLaunched(false); 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 f2e4127537..411bab49e9 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 @@ -214,7 +214,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss( Touch.TAP, Direction.NONE, getRecentsView().indexOfChild(this), TaskUtils.getLaunchComponentKeyForTask(getTask().key)); - mActivity.getStatsLogManager().log(LAUNCHER_TASK_LAUNCH_TAP, getItemInfo()); + mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo()) + .log(LAUNCHER_TASK_LAUNCH_TAP); }); mCurrentFullscreenParams = new FullscreenDrawParams(context); @@ -432,7 +433,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { getRecentsView().snapToPage(getRecentsView().indexOfChild(this)); } else { mMenuView = TaskMenuView.showForTask(this); - mActivity.getStatsLogManager().log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS, getItemInfo()); + 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) { diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java index 3dd9e8bd47..0863aa2820 100644 --- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java +++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java @@ -30,7 +30,6 @@ import android.util.Log; import androidx.annotation.Nullable; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherState; import com.android.launcher3.Utilities; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logging.InstanceId; @@ -79,30 +78,6 @@ public class StatsLogCompatManager extends StatsLogManager { return new StatsCompatLogger(); } - /** - * Logs a {@link EventEnum}. - */ - @Override - public void log(EventEnum event) { - logger().log(event); - } - - /** - * Logs an event and accompanying {@link InstanceId}. - */ - @Override - public void log(EventEnum event, InstanceId instanceId) { - logger().withInstanceId(instanceId).log(event); - } - - /** - * Logs an event and accompanying {@link ItemInfo}. - */ - @Override - public void log(EventEnum event, @Nullable ItemInfo info) { - logger().withItemInfo(info).log(event); - } - /** * Logs an event. * @@ -135,15 +110,6 @@ public class StatsLogCompatManager extends StatsLogManager { srcState, dstState, OptionalInt.empty()); } - /** - * Logs an event and accompanying {@link InstanceId} and {@link LauncherAtom.ItemInfo}. - */ - @Override - public void log(EventEnum event, InstanceId instanceId, - @Nullable ItemInfo info) { - logger().withItemInfo(info).withInstanceId(instanceId).log(event); - } - /** * Logs a ranking event and accompanying {@link InstanceId} and package name. */ @@ -157,15 +123,6 @@ public class StatsLogCompatManager extends StatsLogManager { position /* position_picked = 4; */); } - /** - * Logs an event and accompanying {@link LauncherState}s. If either of the state refers - * to workspace state, then use pageIndex to pass in index of workspace. - */ - @Override - public void log(EventEnum event, int srcState, int dstState, int pageIndex) { - logger().withSrcState(srcState).withDstState(dstState).log(event); - } - private void write(EventEnum event, InstanceId instanceId, LauncherAtom.ItemInfo atomInfo, int srcState, int dstState, OptionalInt mRank) { diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index 61ecdd7da6..9cb8cf2c51 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -202,7 +202,8 @@ public abstract class BaseDraggingActivity extends BaseActivity } protected void logAppLaunch(ItemInfo info, InstanceId instanceId) { - getStatsLogManager().log(LAUNCHER_APP_LAUNCH_TAP, instanceId, info); + getStatsLogManager().logger().withItemInfo(info).withInstanceId(instanceId) + .log(LAUNCHER_APP_LAUNCH_TAP); } private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info, diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java index d75d712280..28574972ad 100644 --- a/src/com/android/launcher3/DeleteDropTarget.java +++ b/src/com/android/launcher3/DeleteDropTarget.java @@ -126,11 +126,9 @@ public class DeleteDropTarget extends ButtonDropTarget { d.dragInfo.container = NO_ID; } super.onDrop(d, options); - mStatsLogManager.log( - mControlType == ControlType.REMOVE_TARGET - ? LAUNCHER_ITEM_DROPPED_ON_REMOVE - : LAUNCHER_ITEM_DROPPED_ON_CANCEL, - d.logInstanceId); + mStatsLogManager.logger().withInstanceId(d.logInstanceId) + .log(mControlType == ControlType.REMOVE_TARGET ? LAUNCHER_ITEM_DROPPED_ON_REMOVE + : LAUNCHER_ITEM_DROPPED_ON_CANCEL); } @Override diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java index fbac0bd32a..499b54f6d2 100644 --- a/src/com/android/launcher3/SecondaryDropTarget.java +++ b/src/com/android/launcher3/SecondaryDropTarget.java @@ -220,9 +220,11 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList d.dragSource = new DeferredOnComplete(d.dragSource, getContext()); super.onDrop(d, options); if (mCurrentAccessibilityAction == UNINSTALL) { - mStatsLogManager.log(LAUNCHER_ITEM_DROPPED_ON_UNINSTALL, d.logInstanceId); + mStatsLogManager.logger().withInstanceId(d.logInstanceId) + .log(LAUNCHER_ITEM_DROPPED_ON_UNINSTALL); } else if (mCurrentAccessibilityAction == DISMISS_PREDICTION) { - mStatsLogManager.log(LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST, d.logInstanceId); + mStatsLogManager.logger().withInstanceId(d.logInstanceId) + .log(LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST); } } @@ -348,10 +350,12 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList mDragObject.dragInfo.user, PackageManager.MATCH_UNINSTALLED_PACKAGES) == null) { mDragObject.dragSource = mOriginal; mOriginal.onDropCompleted(SecondaryDropTarget.this, mDragObject, true); - mStatsLogManager.log(LAUNCHER_ITEM_UNINSTALL_COMPLETED, mDragObject.logInstanceId); + mStatsLogManager.logger().withInstanceId(mDragObject.logInstanceId) + .log(LAUNCHER_ITEM_UNINSTALL_COMPLETED); } else { sendFailure(); - mStatsLogManager.log(LAUNCHER_ITEM_UNINSTALL_CANCELLED, mDragObject.logInstanceId); + mStatsLogManager.logger().withInstanceId(mDragObject.logInstanceId) + .log(LAUNCHER_ITEM_UNINSTALL_CANCELLED); } } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 4198e9f6e9..fb58f21344 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -415,11 +415,9 @@ public class Workspace extends PagedView // Always enter the spring loaded mode mLauncher.getStateManager().goToState(SPRING_LOADED); - mStatsLogManager.log( - LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED, - dragObject.logInstanceId, - dragObject.originalDragInfo - ); + mStatsLogManager.logger().withItemInfo(dragObject.originalDragInfo) + .withInstanceId(dragObject.logInstanceId) + .log(LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED); } public void deferRemoveExtraEmptyScreen() { @@ -1646,10 +1644,8 @@ public class Workspace extends PagedView Rect folderLocation = new Rect(); float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation); target.removeView(v); - mStatsLogManager.log( - LauncherEvent.LAUNCHER_ITEM_DROP_FOLDER_CREATED, - d.logInstanceId, - destInfo); + mStatsLogManager.logger().withItemInfo(destInfo).withInstanceId(d.logInstanceId) + .log(LauncherEvent.LAUNCHER_ITEM_DROP_FOLDER_CREATED); FolderIcon fi = mLauncher.addFolder(target, container, screenId, targetCell[0], targetCell[1]); destInfo.cellX = -1; @@ -1687,10 +1683,8 @@ public class Workspace extends PagedView if (dropOverView instanceof FolderIcon) { FolderIcon fi = (FolderIcon) dropOverView; if (fi.acceptDrop(d.dragInfo)) { - mStatsLogManager.log( - LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED, - d.logInstanceId, - fi.mInfo); + mStatsLogManager.logger().withItemInfo(fi.mInfo).withInstanceId(d.logInstanceId) + .log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED); fi.onDrop(d, false /* itemReturnedOnFailedDrop */); // if the drag started here, we need to remove it from the workspace @@ -1893,10 +1887,8 @@ public class Workspace extends PagedView mLauncher.getStateManager().goToState( NORMAL, SPRING_LOADED_EXIT_DELAY, onCompleteRunnable); - mStatsLogManager.log( - LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED, - d.logInstanceId, - d.dragInfo); + mStatsLogManager.logger().withItemInfo(d.dragInfo).withInstanceId(d.logInstanceId) + .log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED); } if (d.stateAnnouncer != null && !droppedOnOriginalCell) { @@ -2434,10 +2426,9 @@ public class Workspace extends PagedView // widgets/shortcuts/folders in a slightly different way mLauncher.addPendingItem(pendingInfo, container, screenId, mTargetCell, item.spanX, item.spanY); - mStatsLogManager.log( - LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED, - d.logInstanceId, - d.dragInfo); + mStatsLogManager.logger().withItemInfo(d.dragInfo) + .withInstanceId(d.logInstanceId) + .log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED); } }; boolean isWidget = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET @@ -2526,10 +2517,8 @@ public class Workspace extends PagedView mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, view, this); resetTransitionTransform(); } - mStatsLogManager.log( - LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED, - d.logInstanceId, - d.dragInfo); + mStatsLogManager.logger().withItemInfo(d.dragInfo).withInstanceId(d.logInstanceId) + .log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED); } } diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 530010e948..7998c2d50e 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -1337,8 +1337,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo if (d.stateAnnouncer != null) { d.stateAnnouncer.completeAction(R.string.item_moved); } - mStatsLogManager - .log(LAUNCHER_ITEM_DROP_COMPLETED, d.logInstanceId, d.dragInfo); + mStatsLogManager.logger().withItemInfo(d.dragInfo).withInstanceId(d.logInstanceId) + .log(LAUNCHER_ITEM_DROP_COMPLETED); } // This is used so the item doesn't immediately appear in the folder when added. In one case @@ -1443,7 +1443,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo if (hasFocus) { startEditingFolderName(); } else { - mStatsLogManager.log(LAUNCHER_FOLDER_LABEL_UPDATED, mInfo); + mStatsLogManager.logger().withItemInfo(mInfo).log(LAUNCHER_FOLDER_LABEL_UPDATED); logFolderLabelState(); mFolderName.dispatchBackKey(); } diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 2be5883e4a..b40b1e2ebc 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -448,8 +448,8 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel return; } mInfo.setTitle(nameInfos[0].getLabel()); - StatsLogManager.newInstance(getContext()) - .log(LAUNCHER_FOLDER_LABEL_UPDATED, instanceId, mInfo); + StatsLogManager.newInstance(getContext()).logger().withItemInfo(mInfo) + .withInstanceId(instanceId).log(LAUNCHER_FOLDER_LABEL_UPDATED); onTitleChanged(mInfo.title); mFolder.mFolderName.setText(mInfo.title); mFolder.mLauncher.getModelWriter().updateItemInDatabase(mInfo); diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index fac5bf4ea3..8fd779d924 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -253,32 +253,6 @@ public class StatsLogManager implements ResourceBasedOverride { return mgr; } - /** - * Logs an event. - * - * @param event an enum implementing EventEnum interface. - */ - public void log(EventEnum event) { - } - - /** - * Logs an event. - * - * @param event an enum implementing EventEnum interface. - * @param instanceId an identifier obtained from an InstanceIdSequence. - */ - public void log(EventEnum event, InstanceId instanceId) { - } - - /** - * Logs an event. - * - * @param event an enum implementing EventEnum interface. - * @param itemInfo item typically containing app or task launch related information. - */ - public void log(EventEnum event, @Nullable ItemInfo itemInfo) { - } - /** * Logs an event. * @@ -298,16 +272,6 @@ public class StatsLogManager implements ResourceBasedOverride { int srcState, int dstState) { } - /** - * Logs an event. - * - * @param event an enum implementing EventEnum interface. - * @param instanceId an identifier obtained from an InstanceIdSequence. - * @param itemInfo item typically containing app or task launch related information. - */ - public void log(EventEnum event, InstanceId instanceId, @Nullable ItemInfo itemInfo) { - } - /** * Log an event with ranked-choice information along with package. Does nothing if event.getId() * <= 0. @@ -321,13 +285,6 @@ public class StatsLogManager implements ResourceBasedOverride { int position) { } - /** - * Logs an event and accompanying {@link LauncherState}s. If either of the state refers - * to workspace state, then use pageIndex to pass in index of workspace. - */ - public void log(EventEnum event, int srcState, int dstState, int pageIndex) { - } - /** * Logs snapshot, or impression of the current workspace. */ diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java index f1b63f28f9..835f72d5be 100644 --- a/src/com/android/launcher3/notification/NotificationInfo.java +++ b/src/com/android/launcher3/notification/NotificationInfo.java @@ -107,8 +107,8 @@ public class NotificationInfo implements View.OnClickListener { try { intent.send(null, 0, null, null, null, null, activityOptions); launcher.getUserEventDispatcher().logNotificationLaunch(view, intent); - launcher.getStatsLogManager() - .log(LAUNCHER_NOTIFICATION_LAUNCH_TAP, mItemInfo); + launcher.getStatsLogManager().logger().withItemInfo(mItemInfo) + .log(LAUNCHER_NOTIFICATION_LAUNCH_TAP); } catch (PendingIntent.CanceledException e) { e.printStackTrace(); } diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java index 8e60c27e66..61829c002b 100644 --- a/src/com/android/launcher3/popup/RemoteActionShortcut.java +++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java @@ -77,8 +77,8 @@ public class RemoteActionShortcut extends SystemShortcut { @Override public void onClick(View view) { AbstractFloatingView.closeAllOpenViews(mTarget); - mTarget.getStatsLogManager() - .log(LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP, mItemInfo); + mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo) + .log(LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP); final String actionIdentity = mAction.getTitle() + ", " + mItemInfo.getTargetComponent().getPackageName(); diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java index 59d24dee77..fd292a3714 100644 --- a/src/com/android/launcher3/popup/SystemShortcut.java +++ b/src/com/android/launcher3/popup/SystemShortcut.java @@ -119,7 +119,8 @@ public abstract class SystemShortcut extends Ite widgetsBottomSheet.populateAndShow(mItemInfo); mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP, ControlType.WIDGETS_BUTTON, view); - mTarget.getStatsLogManager().log(LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP, mItemInfo); + mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo) + .log(LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP); } } @@ -140,8 +141,8 @@ public abstract class SystemShortcut extends Ite mItemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle()); mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP, ControlType.APPINFO_TARGET, view); - mTarget.getStatsLogManager() - .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP, mItemInfo); + mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo) + .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP); } } diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java index de16941864..848666674d 100644 --- a/src/com/android/launcher3/touch/ItemClickHandler.java +++ b/src/com/android/launcher3/touch/ItemClickHandler.java @@ -113,7 +113,8 @@ public class ItemClickHandler { if (!folder.isOpen() && !folder.isDestroyed()) { // Open the requested folder folder.animateOpen(); - StatsLogManager.newInstance(v.getContext()).log(LAUNCHER_FOLDER_OPEN, folder.mInfo); + StatsLogManager.newInstance(v.getContext()).logger().withItemInfo(folder.mInfo) + .log(LAUNCHER_FOLDER_OPEN); } } diff --git a/src/com/android/launcher3/touch/WorkspaceTouchListener.java b/src/com/android/launcher3/touch/WorkspaceTouchListener.java index 7270ce28fb..4fa658e7d5 100644 --- a/src/com/android/launcher3/touch/WorkspaceTouchListener.java +++ b/src/com/android/launcher3/touch/WorkspaceTouchListener.java @@ -174,7 +174,7 @@ public class WorkspaceTouchListener extends GestureDetector.SimpleOnGestureListe mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); - mLauncher.getStatsLogManager().log(LAUNCHER_WORKSPACE_LONGPRESS); + mLauncher.getStatsLogManager().logger().log(LAUNCHER_WORKSPACE_LONGPRESS); OptionsPopupView.showDefaultOptions(mLauncher, mTouchDownPoint.x, mTouchDownPoint.y); } else { cancelLongPress(); diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java index 5431ba1894..d558781be8 100644 --- a/src/com/android/launcher3/views/OptionsPopupView.java +++ b/src/com/android/launcher3/views/OptionsPopupView.java @@ -86,7 +86,7 @@ public class OptionsPopupView extends ArrowPopup return false; } if (item.mEventId.getId() > 0) { - mLauncher.getStatsLogManager().log(item.mEventId); + mLauncher.getStatsLogManager().logger().log(item.mEventId); } if (item.mClickListener.onLongClick(view)) { close(true); From ff6bc2ab5fe5cba70f669cdf487c6c96330e7369 Mon Sep 17 00:00:00 2001 From: Becky Qiu Date: Mon, 15 Jun 2020 15:25:10 -0700 Subject: [PATCH 18/59] [Overview Actions] For in-place landscape, add select only when aiai works. When display orientation is not the same as device orientation, aiai won't work for select mode highlight. So we should only show the select button in task menu for in-place landscape when the display rotation is the same as the device rotation which is portrait. Screenshot would be in the task menu for in-place landscape all the time. Test: demo video: https://drive.google.com/file/d/1OQrjww2lFTTsthz4dB3BSa-jw943KLWp/view?usp=sharing Change-Id: I58b6f6da234ea36eef0af5bb966c33ebda3625b8 --- .../android/quickstep/TaskOverlayFactory.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java index 177f9a0b68..0101ac75d9 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java @@ -70,10 +70,19 @@ public class TaskOverlayFactory implements ResourceBasedOverride { // Add overview actions to the menu when in in-place rotate landscape mode. if (!canLauncherRotate && isInLandscape) { - for (TaskShortcutFactory actionMenuOption : ACTION_MENU_OPTIONS) { - SystemShortcut shortcut = actionMenuOption.getShortcut(activity, taskView); - if (shortcut != null) { - shortcuts.add(shortcut); + // Add screenshot action to task menu. + SystemShortcut screenshotShortcut = TaskShortcutFactory.SCREENSHOT + .getShortcut(activity, taskView); + if (screenshotShortcut != null) { + shortcuts.add(screenshotShortcut); + } + + // Add modal action only if display orientation is the same as the device orientation. + if (orientedState.getDisplayRotation() == ROTATION_0) { + SystemShortcut modalShortcut = TaskShortcutFactory.MODAL + .getShortcut(activity, taskView); + if (modalShortcut != null) { + shortcuts.add(modalShortcut); } } } @@ -104,11 +113,6 @@ public class TaskOverlayFactory implements ResourceBasedOverride { TaskShortcutFactory.WELLBEING }; - private static final TaskShortcutFactory[] ACTION_MENU_OPTIONS = new TaskShortcutFactory[]{ - TaskShortcutFactory.SCREENSHOT, - TaskShortcutFactory.MODAL - }; - /** * Overlay on each task handling Overview Action Buttons. */ From f91c1d0ef1b6df9d45c0a90c34fe8c13d0f61d83 Mon Sep 17 00:00:00 2001 From: Sreyas Date: Tue, 2 Jun 2020 16:15:49 -0700 Subject: [PATCH 19/59] Disabling OverviewActions when rotated. Bug: 157272300 Bug: 159135247 Change-Id: I9c9eeb49b7d18c1c81a830b7a35113070e7ac793 --- .../android/quickstep/TaskOverlayFactory.java | 7 +++- .../quickstep/views/OverviewActionsView.java | 32 +++++++++++++++++++ .../android/quickstep/views/RecentsView.java | 5 ++- .../quickstep/views/TaskThumbnailView.java | 7 ++-- .../android/quickstep/util/LayoutUtils.java | 15 ++++----- 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java index 0101ac75d9..ed07062235 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java @@ -19,6 +19,7 @@ package com.android.quickstep; import static android.view.Surface.ROTATION_0; import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; +import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED; import android.annotation.SuppressLint; import android.content.Context; @@ -143,8 +144,12 @@ public class TaskOverlayFactory implements ResourceBasedOverride { /** * Called when the current task is interactive for the user */ - public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix) { + public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix, + boolean rotated) { final boolean isAllowedByPolicy = thumbnail.isRealSnapshot; + + mActionsView.updateDisabledFlags(DISABLED_ROTATED, rotated); + getActionsView().setCallbacks(new OverlayUICallbacks() { @Override public void onShare() { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java index 0c21c5de42..a2da39855c 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java @@ -38,6 +38,7 @@ import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.quickstep.SysUINavigationMode; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.TaskOverlayFactory.OverlayUICallbacks; +import com.android.quickstep.util.LayoutUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -67,6 +68,15 @@ public class OverviewActionsView extends FrameLayo public static final int HIDDEN_GESTURE_RUNNING = 1 << 4; public static final int HIDDEN_NO_RECENTS = 1 << 5; + @IntDef(flag = true, value = { + DISABLED_SCROLLING, + DISABLED_ROTATED}) + @Retention(RetentionPolicy.SOURCE) + public @interface ActionsDisabledFlags { } + + public static final int DISABLED_SCROLLING = 1 << 0; + public static final int DISABLED_ROTATED = 1 << 1; + private static final int INDEX_CONTENT_ALPHA = 0; private static final int INDEX_VISIBILITY_ALPHA = 1; private static final int INDEX_FULLSCREEN_ALPHA = 2; @@ -77,6 +87,9 @@ public class OverviewActionsView extends FrameLayo @ActionsHiddenFlags private int mHiddenFlags; + @ActionsDisabledFlags + protected int mDisabledFlags; + protected T mCallbacks; public OverviewActionsView(Context context) { @@ -156,6 +169,25 @@ public class OverviewActionsView extends FrameLayo setVisibility(isHidden ? INVISIBLE : VISIBLE); } + /** + * Updates the proper disabled flag to indicate whether OverviewActionsView should be enabled. + * Ignores DISABLED_ROTATED flag for determining enabled. Flag is used to enable/disable + * buttons individually, currently done for select button in subclass. + * + * @param disabledFlags The flag to update. + * @param enable Whether to enable the disable flag: True will cause view to be disabled. + */ + public void updateDisabledFlags(@ActionsDisabledFlags int disabledFlags, boolean enable) { + if (enable) { + mDisabledFlags |= disabledFlags; + } else { + mDisabledFlags &= ~disabledFlags; + } + // + boolean isEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0; + LayoutUtils.setViewEnabled(this, isEnabled); + } + public AlphaProperty getContentAlpha() { return mMultiValueAlpha.getProperty(INDEX_CONTENT_ALPHA); } 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 43e9660ba6..1cc8e30176 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 @@ -622,14 +622,14 @@ public abstract class RecentsView extends PagedView impl @Override protected void onPageBeginTransition() { super.onPageBeginTransition(); - LayoutUtils.setViewEnabled(mActionsView, false); + mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, true); } @Override protected void onPageEndTransition() { super.onPageEndTransition(); if (isClearAllHidden()) { - LayoutUtils.setViewEnabled(mActionsView, true); + mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false); } if (getNextPage() > 0) { setSwipeDownShouldLaunchApp(true); @@ -2216,7 +2216,6 @@ public abstract class RecentsView extends PagedView impl boolean inPlaceLandscape = !mOrientationState.canLauncherRotate() && mOrientationState.getTouchRotation() != ROTATION_0; mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, modalness < 1 && inPlaceLandscape); - LayoutUtils.setViewEnabled(mActionsView, true); } @Nullable diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java index 26fb563b82..b2f937f8c2 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java @@ -357,10 +357,9 @@ public class TaskThumbnailView extends View implements PluginListener Date: Wed, 17 Jun 2020 17:53:59 -0700 Subject: [PATCH 20/59] Use screenSpaceBounds to position the target window for recents mw animation. Verified window is moving as expected using winscope. Note: Position is off when launching non-center task. Bug: 159171509 Change-Id: Ib11ed7df9a877348d76543279203f9bfc25f7829 --- .../src/com/android/quickstep/util/TaskViewSimulator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 196a7c487c..70fb78e30f 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 @@ -141,7 +141,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { */ public void setPreview(RemoteAnimationTargetCompat runningTarget) { setPreviewBounds(runningTarget.screenSpaceBounds, runningTarget.contentInsets); - mRunningTargetWindowPosition.set(runningTarget.position.x, runningTarget.position.y); + mRunningTargetWindowPosition.set(runningTarget.screenSpaceBounds.left, + runningTarget.screenSpaceBounds.top); } /** From 6fb99518efdde01724fa4107ca1273212170c960 Mon Sep 17 00:00:00 2001 From: Becky Qiu Date: Wed, 17 Jun 2020 17:07:05 -0700 Subject: [PATCH 21/59] [Overview Actions] Add overview actions events. Event IDs were generated by command line on my workstation by uieventscli. Manually added to StatsLogManager. Test: local Bug: 158477117 Change-Id: Ia237d1d9b1d5a52767cac44ab0b4a6d2500b9686 --- .../launcher3/logging/StatsLogManager.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index 8fd779d924..a0e6bfc513 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -149,7 +149,22 @@ public class StatsLogManager implements ResourceBasedOverride { LAUNCHER_ALL_APPS_RANKED(552), @UiEvent(doc = "App launch ranking logged for hotseat predictions)") - LAUNCHER_HOTSEAT_RANKED(553); + LAUNCHER_HOTSEAT_RANKED(553), + + @UiEvent(doc = "User tapped on the screenshot button on overview)") + LAUNCHER_OVERVIEW_ACTIONS_SCREENSHOT(580), + + @UiEvent(doc = "User tapped on the select button on overview)") + LAUNCHER_OVERVIEW_ACTIONS_SELECT(581), + + @UiEvent(doc = "User tapped on the share button on overview") + LAUNCHER_OVERVIEW_ACTIONS_SHARE(582), + + @UiEvent(doc = "User tapped on the close button in select mode") + LAUNCHER_SELECT_MODE_CLOSE(583), + + @UiEvent(doc = "User tapped on the highlight items in select mode") + LAUNCHER_SELECT_MODE_ITEM(584); // ADD MORE private final int mId; From 398c42fe6bf7d0f4ccbfe6d7d7fd6e82b030c8d7 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Wed, 17 Jun 2020 20:57:28 -0700 Subject: [PATCH 22/59] Snapshot logging only use cloned model thread folder contents Bug: 158826147 Change-Id: I9aea9fbc706b0dffa3f6abeaac663b072d62ad58 --- .../com/android/quickstep/logging/StatsLogCompatManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java index 0863aa2820..54894f07b3 100644 --- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java +++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java @@ -41,6 +41,7 @@ import com.android.launcher3.model.BgDataModel; 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.util.IntSparseArrayMap; import com.android.launcher3.util.LogConfig; import com.android.systemui.shared.system.SysUiStatsLog; @@ -192,7 +193,8 @@ public class StatsLogCompatManager extends StatsLogManager { writeSnapshot(atomInfo, mInstanceId); } for (FolderInfo fInfo : folders) { - for (ItemInfo info : fInfo.contents) { + ArrayList folderContents = (ArrayList) fInfo.contents.clone(); + for (ItemInfo info : folderContents) { LauncherAtom.ItemInfo atomInfo = info.buildProto(fInfo); writeSnapshot(atomInfo, mInstanceId); } From 714659f6d02382e3467e75b92bff7c173df0aa53 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Wed, 17 Jun 2020 13:54:03 -0700 Subject: [PATCH 23/59] Add LAUNCHER_WORKSPACE_SNAPSHOT event_id Bug: 159210161 Change-Id: Ie8e843ee10bf4ab0761232a3e61eb28e487666ab --- .../com/android/quickstep/logging/StatsLogCompatManager.java | 3 ++- src/com/android/launcher3/logging/StatsLogManager.java | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java index 54894f07b3..42ade78de9 100644 --- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java +++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java @@ -18,6 +18,7 @@ package com.android.quickstep.logging; import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.FOLDER; import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.PREDICTED_HOTSEAT_CONTAINER; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORKSPACE_SNAPSHOT; import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__ALLAPPS; import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__BACKGROUND; import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__HOME; @@ -214,7 +215,7 @@ public class StatsLogCompatManager extends StatsLogManager { return; } SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_SNAPSHOT, - 0 /* event_id */, + LAUNCHER_WORKSPACE_SNAPSHOT.getId() /* event_id */, info.getItemCase().getNumber() /* target_id */, instanceId.getId() /* instance_id */, 0 /* uid */, diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index a0e6bfc513..f72d76fdd2 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -151,6 +151,9 @@ public class StatsLogManager implements ResourceBasedOverride { @UiEvent(doc = "App launch ranking logged for hotseat predictions)") LAUNCHER_HOTSEAT_RANKED(553), + @UiEvent(doc = "User's workspace layout information is snapshot in the background.") + LAUNCHER_WORKSPACE_SNAPSHOT(579), + @UiEvent(doc = "User tapped on the screenshot button on overview)") LAUNCHER_OVERVIEW_ACTIONS_SCREENSHOT(580), @@ -165,6 +168,7 @@ public class StatsLogManager implements ResourceBasedOverride { @UiEvent(doc = "User tapped on the highlight items in select mode") LAUNCHER_SELECT_MODE_ITEM(584); + // ADD MORE private final int mId; From b64fc6c26f6a59d2bc7c19d08860097a60d0b845 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 4 Jun 2020 18:29:40 -0700 Subject: [PATCH 24/59] Fixing jump when swiping up in landscape and in waterfall cutout > Adding tests for TaskViewSimulator to ensure proper calculations > Disabling orientation listener while user is interacting with quickstep Bug: 158781568 Bug: 156891776 Change-Id: I299c3b1243ac0dbf28faee1b8566c77ea3954e33 --- .../android/quickstep/BaseSwipeUpHandler.java | 35 +-- .../quickstep/util/TaskViewSimulator.java | 2 +- .../android/quickstep/views/RecentsView.java | 4 + .../quickstep/util/TaskViewSimulatorTest.java | 203 ++++++++++++++++++ .../quickstep/util/RecentsOrientedState.java | 14 +- .../config/robolectric.properties | 1 + .../launcher3/shadows/LShadowDisplay.java | 54 +++++ 7 files changed, 297 insertions(+), 16 deletions(-) create mode 100644 quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java create mode 100644 robolectric_tests/src/com/android/launcher3/shadows/LShadowDisplay.java diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index f5c587405a..9db6576765 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -121,6 +121,10 @@ public abstract class BaseSwipeUpHandler, Q extend }); mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { + // Wait until the first scroll event before applying scroll to taskViewSimulator. + // Since, by default the current/running task already centered, this ensures that we + // do not move the running task, in case RecentsView has not yet laid out completely. + mRecentsViewScrollLinked = true; if (moveWindowWithRecentsScroll()) { updateFinalShift(); } @@ -128,7 +132,6 @@ public abstract class BaseSwipeUpHandler, Q extend runOnRecentsAnimationStart(() -> mRecentsView.setRecentsAnimationTargets(mRecentsAnimationController, mRecentsAnimationTargets)); - mRecentsViewScrollLinked = true; } protected void startNewTask(Consumer resultCallback) { @@ -205,26 +208,30 @@ public abstract class BaseSwipeUpHandler, Q extend mRecentsAnimationController = recentsAnimationController; mRecentsAnimationTargets = targets; mTransformParams.setTargetSet(mRecentsAnimationTargets); - DeviceProfile dp = mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile(); RemoteAnimationTargetCompat runningTaskTarget = targets.findTask( mGestureState.getRunningTaskId()); - if (targets.minimizedHomeBounds != null && runningTaskTarget != null) { - Rect overviewStackBounds = mActivityInterface - .getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget); - dp = dp.getMultiWindowProfile(mContext, - new WindowBounds(overviewStackBounds, targets.homeContentInsets)); - } else { - // If we are not in multi-window mode, home insets should be same as system insets. - dp = dp.copy(mContext); - } - dp.updateInsets(targets.homeContentInsets); - dp.updateIsSeascape(mContext); if (runningTaskTarget != null) { mTaskViewSimulator.setPreview(runningTaskTarget); } - initTransitionEndpoints(dp); + // Only initialize the device profile, if it has not been initialized before, as in some + // configurations targets.homeContentInsets may not be correct. + if (mActivity == null) { + DeviceProfile dp = mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile(); + if (targets.minimizedHomeBounds != null && runningTaskTarget != null) { + Rect overviewStackBounds = mActivityInterface + .getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget); + dp = dp.getMultiWindowProfile(mContext, + new WindowBounds(overviewStackBounds, targets.homeContentInsets)); + } else { + // If we are not in multi-window mode, home insets should be same as system insets. + dp = dp.copy(mContext); + } + dp.updateInsets(targets.homeContentInsets); + dp.updateIsSeascape(mContext); + initTransitionEndpoints(dp); + } // Notify when the animation starts if (!mRecentsAnimationStartCallbacks.isEmpty()) { 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 196a7c487c..f62218f773 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 @@ -255,8 +255,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { float taskHeight = mTaskRect.height(); mMatrix.set(mPositionHelper.getMatrix()); - mMatrix.postScale(scale, scale); mMatrix.postTranslate(insets.left, insets.top); + mMatrix.postScale(scale, scale); // Apply TaskView matrix: translate, scale, scroll mMatrix.postTranslate(mTaskRect.left, mTaskRect.top); 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 99afe39acd..39775987d1 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 @@ -998,6 +998,7 @@ public abstract class RecentsView extends PagedView impl mDwbToastShown = false; mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0); LayoutUtils.setViewEnabled(mActionsView, true); + mOrientationState.setGestureActive(false); } public @Nullable TaskView getRunningTaskView() { @@ -1035,6 +1036,7 @@ public abstract class RecentsView extends PagedView impl */ public void onGestureAnimationStart(int runningTaskId) { // This needs to be called before the other states are set since it can create the task view + mOrientationState.setGestureActive(true); showCurrentTask(runningTaskId); setEnableFreeScroll(false); setEnableDrawingLiveTile(false); @@ -1097,6 +1099,8 @@ public abstract class RecentsView extends PagedView impl * Called when a gesture from an app has finished. */ public void onGestureAnimationEnd() { + mOrientationState.setGestureActive(false); + setOnScrollChangeListener(null); setEnableFreeScroll(true); setEnableDrawingLiveTile(true); diff --git a/quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java new file mode 100644 index 0000000000..a31ba2177b --- /dev/null +++ b/quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java @@ -0,0 +1,203 @@ +/* + * 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 android.view.Display.DEFAULT_DISPLAY; + +import android.content.Context; +import android.graphics.Rect; +import android.graphics.RectF; +import android.hardware.display.DisplayManager; +import android.view.Surface; +import android.view.SurfaceControl; + +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.shadows.LShadowDisplay; +import com.android.launcher3.util.DefaultDisplay; +import com.android.quickstep.LauncherActivityInterface; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; + +import org.hamcrest.Description; +import org.hamcrest.TypeSafeMatcher; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.LooperMode; +import org.robolectric.annotation.LooperMode.Mode; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.shadows.ShadowDisplayManager; + +@RunWith(RobolectricTestRunner.class) +@LooperMode(Mode.PAUSED) +public class TaskViewSimulatorTest { + + @Test + public void taskProperlyScaled_portrait_noRotation_sameInsets1() { + new TaskMatrixVerifier() + .withLauncherSize(1200, 2450) + .withInsets(new Rect(0, 80, 0, 120)) + .verifyNoTransforms(); + } + + @Test + public void taskProperlyScaled_portrait_noRotation_sameInsets2() { + new TaskMatrixVerifier() + .withLauncherSize(1200, 2450) + .withInsets(new Rect(55, 80, 55, 120)) + .verifyNoTransforms(); + } + + @Test + public void taskProperlyScaled_landscape_noRotation_sameInsets1() { + new TaskMatrixVerifier() + .withLauncherSize(2450, 1250) + .withInsets(new Rect(0, 80, 0, 40)) + .verifyNoTransforms(); + } + + @Test + public void taskProperlyScaled_landscape_noRotation_sameInsets2() { + new TaskMatrixVerifier() + .withLauncherSize(2450, 1250) + .withInsets(new Rect(0, 80, 120, 0)) + .verifyNoTransforms(); + } + + @Test + public void taskProperlyScaled_landscape_noRotation_sameInsets3() { + new TaskMatrixVerifier() + .withLauncherSize(2450, 1250) + .withInsets(new Rect(55, 80, 55, 120)) + .verifyNoTransforms(); + } + + @Test + public void taskProperlyScaled_landscape_rotated() { + new TaskMatrixVerifier() + .withLauncherSize(1200, 2450) + .withInsets(new Rect(0, 80, 0, 120)) + .withAppBounds( + new Rect(0, 0, 2450, 1200), + new Rect(0, 80, 0, 120), + Surface.ROTATION_90) + .verifyNoTransforms(); + } + + private static class TaskMatrixVerifier extends TransformParams { + + private final Context mContext = RuntimeEnvironment.application; + + private Rect mAppBounds = new Rect(); + private Rect mLauncherInsets = new Rect(); + + private Rect mAppInsets; + + private int mAppRotation = -1; + private DeviceProfile mDeviceProfile; + + TaskMatrixVerifier withLauncherSize(int width, int height) { + ShadowDisplayManager.changeDisplay(DEFAULT_DISPLAY, + String.format("w%sdp-h%sdp-mdpi", width, height)); + if (mAppBounds.isEmpty()) { + mAppBounds.set(0, 0, width, height); + } + return this; + } + + TaskMatrixVerifier withInsets(Rect insets) { + LShadowDisplay shadowDisplay = Shadow.extract( + mContext.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY)); + shadowDisplay.setInsets(insets); + mLauncherInsets.set(insets); + return this; + } + + TaskMatrixVerifier withAppBounds(Rect bounds, Rect insets, int appRotation) { + mAppBounds.set(bounds); + mAppInsets = insets; + mAppRotation = appRotation; + return this; + } + + void verifyNoTransforms() { + mDeviceProfile = InvariantDeviceProfile.INSTANCE.get(mContext) + .getDeviceProfile(mContext); + mDeviceProfile.updateInsets(mLauncherInsets); + + TaskViewSimulator tvs = new TaskViewSimulator(mContext, + LauncherActivityInterface.INSTANCE); + tvs.setDp(mDeviceProfile); + + int launcherRotation = DefaultDisplay.INSTANCE.get(mContext).getInfo().rotation; + if (mAppRotation < 0) { + mAppRotation = launcherRotation; + } + tvs.setLayoutRotation(launcherRotation, mAppRotation); + if (mAppInsets == null) { + mAppInsets = new Rect(mLauncherInsets); + } + tvs.setPreviewBounds(mAppBounds, mAppInsets); + + tvs.fullScreenProgress.value = 1; + tvs.recentsViewScale.value = tvs.getFullScreenScale(); + tvs.apply(this); + } + + @Override + public SurfaceParams[] createSurfaceParams(BuilderProxy proxy) { + SurfaceParams.Builder builder = new SurfaceParams.Builder((SurfaceControl) null); + proxy.onBuildTargetParams(builder, null, this); + return new SurfaceParams[] {builder.build()}; + } + + @Override + public void applySurfaceParams(SurfaceParams[] params) { + // Verify that the task position remains the same + RectF newAppBounds = new RectF(mAppBounds); + params[0].matrix.mapRect(newAppBounds); + Assert.assertThat(newAppBounds, new AlmostSame(mAppBounds)); + + System.err.println("Bounds mapped: " + mAppBounds + " => " + newAppBounds); + } + } + + private static class AlmostSame extends TypeSafeMatcher { + + // Allow 1px error margin to account for float to int conversions + private final float mError = 1f; + private final Rect mExpected; + + AlmostSame(Rect expected) { + mExpected = expected; + } + + @Override + protected boolean matchesSafely(RectF item) { + return Math.abs(item.left - mExpected.left) < mError + && Math.abs(item.top - mExpected.top) < mError + && Math.abs(item.right - mExpected.right) < mError + && Math.abs(item.bottom - mExpected.bottom) < mError; + } + + @Override + public void describeTo(Description description) { + description.appendValue(mExpected); + } + } +} diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java index 68636cb1ab..90ee18f19e 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java +++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java @@ -105,6 +105,9 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre private static final int FLAG_ROTATION_WATCHER_ENABLED = 1 << 6; // Enable home rotation for UI tests, ignoring home rotation value from prefs private static final int FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING = 1 << 7; + // Whether the swipe gesture is running, so the recents would stay locked in the + // current orientation + private static final int FLAG_SWIPE_UP_NOT_RUNNING = 1 << 8; private static final int MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE = FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY @@ -114,7 +117,8 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre // multi-window is enabled as in that case, activity itself rotates. private static final int VALUE_ROTATION_WATCHER_ENABLED = MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE | FLAG_SYSTEM_ROTATION_ALLOWED - | FLAG_ROTATION_WATCHER_SUPPORTED | FLAG_ROTATION_WATCHER_ENABLED; + | FLAG_ROTATION_WATCHER_SUPPORTED | FLAG_ROTATION_WATCHER_ENABLED + | FLAG_SWIPE_UP_NOT_RUNNING; private final Context mContext; private final ContentResolver mContentResolver; @@ -156,6 +160,7 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre if (originalSmallestWidth < 600) { mFlags |= FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY; } + mFlags |= FLAG_SWIPE_UP_NOT_RUNNING; initFlags(); } @@ -166,6 +171,13 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre setFlag(FLAG_MULTIWINDOW_ROTATION_ALLOWED, isMultiWindow); } + /** + * Sets if the swipe up gesture is currently running or not + */ + public void setGestureActive(boolean isGestureActive) { + setFlag(FLAG_SWIPE_UP_NOT_RUNNING, !isGestureActive); + } + /** * Sets the appropriate {@link PagedOrientationHandler} for {@link #mOrientationHandler} * @param touchRotation The rotation the nav bar region that is touched is in diff --git a/robolectric_tests/config/robolectric.properties b/robolectric_tests/config/robolectric.properties index b1717120af..a8e0cb3acd 100644 --- a/robolectric_tests/config/robolectric.properties +++ b/robolectric_tests/config/robolectric.properties @@ -5,6 +5,7 @@ shadows= \ com.android.launcher3.shadows.LShadowAppWidgetManager \ com.android.launcher3.shadows.LShadowBackupManager \ com.android.launcher3.shadows.LShadowBitmap \ + com.android.launcher3.shadows.LShadowDisplay \ com.android.launcher3.shadows.LShadowLauncherApps \ com.android.launcher3.shadows.LShadowTypeface \ com.android.launcher3.shadows.LShadowUserManager \ diff --git a/robolectric_tests/src/com/android/launcher3/shadows/LShadowDisplay.java b/robolectric_tests/src/com/android/launcher3/shadows/LShadowDisplay.java new file mode 100644 index 0000000000..3813fa182f --- /dev/null +++ b/robolectric_tests/src/com/android/launcher3/shadows/LShadowDisplay.java @@ -0,0 +1,54 @@ +/* + * 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.shadows; + +import static org.robolectric.shadow.api.Shadow.directlyOn; + +import android.graphics.Point; +import android.graphics.Rect; +import android.view.Display; + +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.RealObject; +import org.robolectric.shadows.ShadowDisplay; + +/** + * Extension of {@link ShadowDisplay} with missing shadow methods + */ +@Implements(value = Display.class) +public class LShadowDisplay extends ShadowDisplay { + + private final Rect mInsets = new Rect(); + + @RealObject Display realObject; + + /** + * Sets the insets for the display + */ + public void setInsets(Rect insets) { + mInsets.set(insets); + } + + @Override + protected void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) { + directlyOn(realObject, Display.class).getCurrentSizeRange(outSmallestSize, outLargestSize); + outSmallestSize.x -= mInsets.left + mInsets.right; + outLargestSize.x -= mInsets.left + mInsets.right; + + outSmallestSize.y -= mInsets.top + mInsets.bottom; + outLargestSize.y -= mInsets.top + mInsets.bottom; + } +} From 44c1b5e03d55c346b939d62f7f73ceb71de25543 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Thu, 18 Jun 2020 10:19:19 -0700 Subject: [PATCH 25/59] Show a snackbar on predicted icon longpress The first time a user long presses a predicted icon, suppress drag/drop and show a snackbar about app predictions. Bug: 159170242 Test: Manual Change-Id: I5f853a9774b38ad9fad22ff55feff417a801f52c --- .../hybridhotseat/HotseatPredictionController.java | 13 +++++++++++++ src/com/android/launcher3/util/OnboardingPrefs.java | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java index 30a34e46eb..80d7cbd850 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java @@ -32,6 +32,7 @@ import android.content.ComponentName; import android.content.Intent; import android.os.Process; import android.util.Log; +import android.view.HapticFeedbackConstants; import android.view.View; import android.view.ViewGroup; @@ -69,6 +70,7 @@ import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IntArray; +import com.android.launcher3.util.OnboardingPrefs; import com.android.launcher3.views.ArrowTipView; import com.android.launcher3.views.Snackbar; @@ -120,6 +122,17 @@ public class HotseatPredictionController implements DragController.DragListener, private final View.OnLongClickListener mPredictionLongClickListener = v -> { if (!ItemLongClickListener.canStartDrag(mLauncher)) return false; if (mLauncher.getWorkspace().isSwitchingState()) return false; + if (!mLauncher.getOnboardingPrefs().getBoolean( + OnboardingPrefs.HOTSEAT_LONGPRESS_TIP_SEEN)) { + Intent intent = new Intent(SETTINGS_ACTION); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + Snackbar.show(mLauncher, R.string.hotseat_tip_gaps_filled, + R.string.hotseat_prediction_settings, null, + () -> mLauncher.startActivity(intent)); + mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.HOTSEAT_LONGPRESS_TIP_SEEN); + mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + return true; + } // Start the drag mLauncher.getWorkspace().beginDragShared(v, this, new DragOptions()); return false; diff --git a/src/com/android/launcher3/util/OnboardingPrefs.java b/src/com/android/launcher3/util/OnboardingPrefs.java index 90a1c82661..e3bd1b91a5 100644 --- a/src/com/android/launcher3/util/OnboardingPrefs.java +++ b/src/com/android/launcher3/util/OnboardingPrefs.java @@ -38,6 +38,7 @@ public class OnboardingPrefs { public static final String SHELF_BOUNCE_COUNT = "launcher.shelf_bounce_count"; public static final String ALL_APPS_COUNT = "launcher.all_apps_count"; public static final String HOTSEAT_DISCOVERY_TIP_COUNT = "launcher.hotseat_discovery_tip_count"; + public static final String HOTSEAT_LONGPRESS_TIP_SEEN = "launcher.hotseat_longpress_tip_seen"; /** * Events that either have happened or have not (booleans). @@ -111,4 +112,11 @@ public class OnboardingPrefs { mSharedPrefs.edit().putInt(eventKey, count).apply(); return hasReachedMaxCount(count, eventKey); } + + /** + * Marks on-boarding preference boolean at true + */ + public void markChecked(String flag) { + mSharedPrefs.edit().putBoolean(flag, true).apply(); + } } From c376a1de2c942703ef8fe4095fe9f4bf6d2c39a7 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Thu, 18 Jun 2020 13:10:37 -0700 Subject: [PATCH 26/59] Add flag Intent.FLAG_ACTIVITY_NEW_TASK when launching suggestion settings Bug: 158604370 Test: Manual Change-Id: I01e313d29cbc9b7ea2413547d9a7b4940d126ce8 --- .../launcher3/hybridhotseat/HotseatEduController.java | 8 ++++++-- .../hybridhotseat/HotseatPredictionController.java | 8 +++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java index 522a2dc969..c1bf2fd960 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java @@ -84,7 +84,7 @@ public class HotseatEduController { } Snackbar.show(mLauncher, R.string.hotsaet_tip_prediction_enabled, R.string.hotseat_prediction_settings, null, - () -> mLauncher.startActivity(new Intent(SETTINGS_ACTION))); + () -> mLauncher.startActivity(getSettingsIntent())); } /** @@ -237,7 +237,7 @@ public class HotseatEduController { < mLauncher.getDeviceProfile().inv.numHotseatIcons) { Snackbar.show(mLauncher, R.string.hotseat_tip_gaps_filled, R.string.hotseat_prediction_settings, null, - () -> mLauncher.startActivity(new Intent(SETTINGS_ACTION))); + () -> mLauncher.startActivity(getSettingsIntent())); } else { new ArrowTipView(mLauncher).show( mLauncher.getString(R.string.hotseat_tip_no_empty_slots), mHotseat.getTop()); @@ -281,5 +281,9 @@ public class HotseatEduController { mActiveDialog.setHotseatEduController(this); mActiveDialog.show(mPredictedApps); } + + static Intent getSettingsIntent() { + return new Intent(SETTINGS_ACTION).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java index 30a34e46eb..296f1dc745 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java @@ -17,7 +17,7 @@ package com.android.launcher3.hybridhotseat; import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; -import static com.android.launcher3.hybridhotseat.HotseatEduController.SETTINGS_ACTION; +import static com.android.launcher3.hybridhotseat.HotseatEduController.getSettingsIntent; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_RANKED; import android.animation.Animator; @@ -29,7 +29,6 @@ import android.app.prediction.AppPredictor; import android.app.prediction.AppTarget; import android.app.prediction.AppTargetEvent; import android.content.ComponentName; -import android.content.Intent; import android.os.Process; import android.util.Log; import android.view.View; @@ -158,8 +157,7 @@ public class HotseatPredictionController implements DragController.DragListener, // launcher has empty predictions set Snackbar.show(mLauncher, R.string.hotsaet_tip_prediction_disabled, R.string.hotseat_prediction_settings, null, - () -> mLauncher.startActivity( - new Intent(SETTINGS_ACTION))); + () -> mLauncher.startActivity(getSettingsIntent())); } else if (isEduSeen()) { // user has already went through education new ArrowTipView(mLauncher).show( @@ -183,7 +181,7 @@ public class HotseatPredictionController implements DragController.DragListener, } else { Snackbar.show(mLauncher, R.string.hotseat_tip_gaps_filled, R.string.hotseat_prediction_settings, null, - () -> mLauncher.startActivity(new Intent(SETTINGS_ACTION))); + () -> mLauncher.startActivity(HotseatEduController.getSettingsIntent())); } } From 9058e305e5bffee44cc3b92ec86120c715900a39 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Wed, 17 Jun 2020 00:12:35 -0700 Subject: [PATCH 27/59] Avoid hotseat edu button overlapping Screenshot: https://screenshot.googleplex.com/cCNn6hdrqu1 Bug: 158194467 Change-Id: I465ab73be2079f20994b3f2bbe57f64e46d05777 --- .../res/layout/predicted_hotseat_edu.xml | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml b/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml index b9621e489f..36c9b00e07 100644 --- a/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml +++ b/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml @@ -72,33 +72,42 @@ android:layout_height="0dp" launcher:containerType="hotseat" /> - -