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 ebc83c6bad..6f4d34c8c7 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(