From 9d2ece156de5300bc11f1a3c36de9ca893f9ab82 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 22 Mar 2024 13:52:19 -0700 Subject: [PATCH] Removing ext_test directory Except for a few methods, most of the testing code was already in the main codebase. Maintaining the additional source directory adds unnecessary overhead Bug: 330920490 Test: Presubmit Flag: None Change-Id: I56c43ab7a4869b26858d622d0b8b14f286d50e90 --- Android.bp | 27 +- ext_tests/res/values/overrides.xml | 5 - .../testing/DebugTestInformationHandler.java | 258 ------------------ lint-baseline.xml | 144 +--------- lint-baseline2.xml | 37 --- .../DebugQuickstepTestInformationHandler.java | 51 ---- .../testing/TestInformationHandler.java | 189 +++++++++++++ 7 files changed, 199 insertions(+), 512 deletions(-) delete mode 100644 ext_tests/res/values/overrides.xml delete mode 100644 ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java delete mode 100644 lint-baseline2.xml delete mode 100644 quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java diff --git a/Android.bp b/Android.bp index cdada0a87f..f45394a998 100644 --- a/Android.bp +++ b/Android.bp @@ -17,7 +17,7 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } -min_launcher3_sdk_version = "26" +min_launcher3_sdk_version = "30" // Common source files used to build launcher (java and kotlin) // All sources are split so they can be reused in many other libraries/apps in other folders @@ -69,22 +69,6 @@ filegroup { ], } -filegroup { - name: "launcher-ext_tests", - srcs: [ - "ext_tests/**/*.java", - "ext_tests/**/*.kt", - ], -} - -filegroup { - name: "launcher-quickstep-ext_tests", - srcs: [ - "quickstep/ext_tests/**/*.java", - "quickstep/ext_tests/**/*.kt", - ], -} - // Proguard files for Launcher3 filegroup { name: "launcher-proguard-rules", @@ -186,7 +170,7 @@ android_library { sdk_version: "current", min_sdk_version: min_launcher3_sdk_version, lint: { - baseline_filename: "lint-baseline2.xml", + baseline_filename: "lint-baseline.xml", }, } @@ -212,7 +196,7 @@ android_library { min_sdk_version: min_launcher3_sdk_version, manifest: "AndroidManifest-common.xml", lint: { - baseline_filename: "lint-baseline2.xml", + baseline_filename: "lint-baseline.xml", }, } @@ -229,11 +213,8 @@ android_app { ":launcher-src", ":launcher-src_shortcuts_overrides", ":launcher-src_ui_overrides", - ":launcher-ext_tests", - ], - resource_dirs: [ - "ext_tests/res", ], + optimize: { proguard_flags_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 deleted file mode 100644 index 3f071d4219..0000000000 --- a/ext_tests/res/values/overrides.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 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 deleted file mode 100644 index 6e7a82ae5c..0000000000 --- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.launcher3.testing; - -import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; -import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; - -import android.app.Activity; -import android.app.Application; -import android.content.Context; -import android.os.Binder; -import android.os.Bundle; -import android.system.Os; - -import androidx.annotation.Keep; -import androidx.annotation.Nullable; - -import com.android.launcher3.BubbleTextView; -import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherModel; -import com.android.launcher3.ShortcutAndWidgetContainer; -import com.android.launcher3.icons.ClockDrawableWrapper; -import com.android.launcher3.testing.shared.TestProtocol; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.WeakHashMap; -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 Collection sEvents; - private static Application.ActivityLifecycleCallbacks sActivityLifecycleCallbacks; - private static final Map sActivities = - Collections.synchronizedMap(new WeakHashMap<>()); - private static int sActivitiesCreatedCount = 0; - - public DebugTestInformationHandler(Context context) { - init(context); - if (sActivityLifecycleCallbacks == null) { - sActivityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() { - @Override - public void onActivityCreated(Activity activity, Bundle bundle) { - sActivities.put(activity, true); - ++sActivitiesCreatedCount; - } - - @Override - public void onActivityStarted(Activity activity) { - } - - @Override - public void onActivityResumed(Activity activity) { - } - - @Override - public void onActivityPaused(Activity activity) { - } - - @Override - public void onActivityStopped(Activity activity) { - } - - @Override - public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { - } - - @Override - public void onActivityDestroyed(Activity activity) { - } - }; - ((Application) context.getApplicationContext()) - .registerActivityLifecycleCallbacks(sActivityLifecycleCallbacks); - } - } - - 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, String arg, @Nullable Bundle extras) { - 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; - ClockDrawableWrapper.sRunningInTest = true; - return response; - - case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING: - TestProtocol.sDebugTracing = false; - ClockDrawableWrapper.sRunningInTest = false; - return response; - - case TestProtocol.REQUEST_PID: { - response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, Os.getpid()); - return response; - } - - case TestProtocol.REQUEST_FORCE_GC: { - runGcAndFinalizersSync(); - return response; - } - - case TestProtocol.REQUEST_START_EVENT_LOGGING: { - sEvents = new ArrayList<>(); - TestLogging.setEventConsumer( - (sequence, event) -> { - final Collection events = sEvents; - if (events != null) { - synchronized (events) { - events.add(sequence + '/' + event); - } - } - }); - return response; - } - - case TestProtocol.REQUEST_STOP_EVENT_LOGGING: { - TestLogging.setEventConsumer(null); - sEvents = null; - return response; - } - - case TestProtocol.REQUEST_GET_TEST_EVENTS: { - if (sEvents == null) { - // sEvents can be null if Launcher died and restarted after - // REQUEST_START_EVENT_LOGGING. - return response; - } - - synchronized (sEvents) { - response.putStringArrayList( - TestProtocol.TEST_INFO_RESPONSE_FIELD, new ArrayList<>(sEvents)); - } - return response; - } - - case TestProtocol.REQUEST_REINITIALIZE_DATA: { - final long identity = Binder.clearCallingIdentity(); - try { - MODEL_EXECUTOR.execute(() -> { - LauncherModel model = LauncherAppState.getInstance(mContext).getModel(); - model.getModelDbController().createEmptyDB(); - MAIN_EXECUTOR.execute(model::forceReload); - }); - return response; - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - case TestProtocol.REQUEST_CLEAR_DATA: { - final long identity = Binder.clearCallingIdentity(); - try { - MODEL_EXECUTOR.execute(() -> { - LauncherModel model = LauncherAppState.getInstance(mContext).getModel(); - model.getModelDbController().createEmptyDB(); - model.getModelDbController().clearEmptyDbFlag(); - MAIN_EXECUTOR.execute(model::forceReload); - }); - return response; - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - case TestProtocol.REQUEST_HOTSEAT_ICON_NAMES: { - return getLauncherUIProperty(Bundle::putStringArrayList, l -> { - ShortcutAndWidgetContainer hotseatIconsContainer = - l.getHotseat().getShortcutsAndWidgets(); - ArrayList hotseatIconNames = new ArrayList<>(); - - for (int i = 0; i < hotseatIconsContainer.getChildCount(); i++) { - // Use unchecked cast to catch changes in hotseat layout - BubbleTextView icon = (BubbleTextView) hotseatIconsContainer.getChildAt(i); - hotseatIconNames.add((String) icon.getText()); - } - - return hotseatIconNames; - }); - } - - case TestProtocol.REQUEST_GET_ACTIVITIES_CREATED_COUNT: { - response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, sActivitiesCreatedCount); - return response; - } - - case TestProtocol.REQUEST_GET_ACTIVITIES: { - response.putStringArray(TestProtocol.TEST_INFO_RESPONSE_FIELD, - sActivities.keySet().stream().map( - a -> a.getClass().getSimpleName() + " (" - + (a.isDestroyed() ? "destroyed" : "current") + ")") - .toArray(String[]::new)); - return response; - } - - case TestProtocol.REQUEST_MODEL_QUEUE_CLEARED: - return getFromExecutorSync(MODEL_EXECUTOR, Bundle::new); - - default: - return super.call(method, arg, extras); - } - } -} diff --git a/lint-baseline.xml b/lint-baseline.xml index fe005cadf0..2ee9531298 100644 --- a/lint-baseline.xml +++ b/lint-baseline.xml @@ -3,13 +3,13 @@ + message="`@android:dimen/system_app_widget_background_radius` requires API level 31 (current min is 26)" + errorLine1=' <corners android:radius="@android:dimen/system_app_widget_background_radius" />' + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="packages/apps/Launcher3/res/drawable/widget_resize_frame.xml" + line="20" + column="14"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lint-baseline2.xml b/lint-baseline2.xml deleted file mode 100644 index 84f1b15d54..0000000000 --- a/lint-baseline2.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java b/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java deleted file mode 100644 index 0b17a7b7d7..0000000000 --- a/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.quickstep; - -import android.content.Context; -import android.os.Bundle; - -import androidx.annotation.Nullable; - -import com.android.launcher3.testing.DebugTestInformationHandler; -import com.android.launcher3.testing.shared.TestProtocol; - -/** - * Class to handle requests from tests, including debug ones, to Quickstep Launcher builds. - */ -public abstract class DebugQuickstepTestInformationHandler extends QuickstepTestInformationHandler { - - private final DebugTestInformationHandler mDebugTestInformationHandler; - - public DebugQuickstepTestInformationHandler(Context context) { - super(context); - mDebugTestInformationHandler = new DebugTestInformationHandler(context); - } - - @Override - public Bundle call(String method, String arg, @Nullable Bundle extras) { - Bundle response = new Bundle(); - if (TestProtocol.REQUEST_RECREATE_TASKBAR.equals(method)) { - // Allow null-pointer to catch illegal states. - runOnTISBinder(tisBinder -> tisBinder.getTaskbarManager().recreateTaskbar()); - return response; - } - response = super.call(method, arg, extras); - if (response != null) return response; - return mDebugTestInformationHandler.call(method, arg, extras); - } -} - diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java index 12cdd67515..d5c9b9fa89 100644 --- a/src/com/android/launcher3/testing/TestInformationHandler.java +++ b/src/com/android/launcher3/testing/TestInformationHandler.java @@ -23,39 +23,56 @@ import static com.android.launcher3.config.FeatureFlags.enableAppPairs; import static com.android.launcher3.config.FeatureFlags.enableSplitContextually; import static com.android.launcher3.testing.shared.TestProtocol.TEST_INFO_RESPONSE_FIELD; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; +import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.app.Activity; +import android.app.Application; import android.content.Context; import android.content.res.Resources; import android.graphics.Insets; import android.graphics.Point; import android.graphics.Rect; +import android.os.Binder; import android.os.Bundle; +import android.system.Os; import android.view.WindowInsets; +import androidx.annotation.Keep; import androidx.annotation.Nullable; import androidx.core.view.WindowInsetsCompat; +import com.android.launcher3.BubbleTextView; import com.android.launcher3.CellLayout; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Hotseat; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherState; import com.android.launcher3.R; +import com.android.launcher3.ShortcutAndWidgetContainer; import com.android.launcher3.Workspace; import com.android.launcher3.dragndrop.DragLayer; +import com.android.launcher3.icons.ClockDrawableWrapper; import com.android.launcher3.testing.shared.HotseatCellCenterRequest; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.testing.shared.WorkspaceCellCenterRequest; +import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.ResourceBasedOverride; import com.android.launcher3.widget.picker.WidgetsFullSheet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import java.util.WeakHashMap; import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Supplier; @@ -69,6 +86,12 @@ public class TestInformationHandler implements ResourceBasedOverride { context, R.string.test_information_handler_class); } + private static Collection sEvents; + private static Application.ActivityLifecycleCallbacks sActivityLifecycleCallbacks; + private static final Set sActivities = + Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<>())); + private static int sActivitiesCreatedCount = 0; + protected Context mContext; protected DeviceProfile mDeviceProfile; protected LauncherAppState mLauncherAppState; @@ -78,6 +101,17 @@ public class TestInformationHandler implements ResourceBasedOverride { mDeviceProfile = InvariantDeviceProfile.INSTANCE. get(context).getDeviceProfile(context); mLauncherAppState = LauncherAppState.getInstanceNoCreate(); + if (sActivityLifecycleCallbacks == null) { + sActivityLifecycleCallbacks = new ActivityLifecycleCallbacksAdapter() { + @Override + public void onActivityCreated(Activity activity, Bundle bundle) { + sActivities.add(activity); + ++sActivitiesCreatedCount; + } + }; + ((Application) context.getApplicationContext()) + .registerActivityLifecycleCallbacks(sActivityLifecycleCallbacks); + } } /** @@ -309,6 +343,127 @@ public class TestInformationHandler implements ResourceBasedOverride { return response; } + 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; + ClockDrawableWrapper.sRunningInTest = true; + return response; + + case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING: + TestProtocol.sDebugTracing = false; + ClockDrawableWrapper.sRunningInTest = false; + return response; + + case TestProtocol.REQUEST_PID: { + response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, Os.getpid()); + return response; + } + + case TestProtocol.REQUEST_FORCE_GC: { + runGcAndFinalizersSync(); + return response; + } + + case TestProtocol.REQUEST_START_EVENT_LOGGING: { + sEvents = new ArrayList<>(); + TestLogging.setEventConsumer( + (sequence, event) -> { + final Collection events = sEvents; + if (events != null) { + synchronized (events) { + events.add(sequence + '/' + event); + } + } + }); + return response; + } + + case TestProtocol.REQUEST_STOP_EVENT_LOGGING: { + TestLogging.setEventConsumer(null); + sEvents = null; + return response; + } + + case TestProtocol.REQUEST_GET_TEST_EVENTS: { + if (sEvents == null) { + // sEvents can be null if Launcher died and restarted after + // REQUEST_START_EVENT_LOGGING. + return response; + } + + synchronized (sEvents) { + response.putStringArrayList( + TestProtocol.TEST_INFO_RESPONSE_FIELD, new ArrayList<>(sEvents)); + } + return response; + } + + case TestProtocol.REQUEST_REINITIALIZE_DATA: { + final long identity = Binder.clearCallingIdentity(); + try { + MODEL_EXECUTOR.execute(() -> { + LauncherModel model = LauncherAppState.getInstance(mContext).getModel(); + model.getModelDbController().createEmptyDB(); + MAIN_EXECUTOR.execute(model::forceReload); + }); + return response; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + case TestProtocol.REQUEST_CLEAR_DATA: { + final long identity = Binder.clearCallingIdentity(); + try { + MODEL_EXECUTOR.execute(() -> { + LauncherModel model = LauncherAppState.getInstance(mContext).getModel(); + model.getModelDbController().createEmptyDB(); + model.getModelDbController().clearEmptyDbFlag(); + MAIN_EXECUTOR.execute(model::forceReload); + }); + return response; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + case TestProtocol.REQUEST_HOTSEAT_ICON_NAMES: { + return getLauncherUIProperty(Bundle::putStringArrayList, l -> { + ShortcutAndWidgetContainer hotseatIconsContainer = + l.getHotseat().getShortcutsAndWidgets(); + ArrayList hotseatIconNames = new ArrayList<>(); + + for (int i = 0; i < hotseatIconsContainer.getChildCount(); i++) { + // Use unchecked cast to catch changes in hotseat layout + BubbleTextView icon = (BubbleTextView) hotseatIconsContainer.getChildAt(i); + hotseatIconNames.add((String) icon.getText()); + } + + return hotseatIconNames; + }); + } + + case TestProtocol.REQUEST_GET_ACTIVITIES_CREATED_COUNT: { + response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, sActivitiesCreatedCount); + return response; + } + + case TestProtocol.REQUEST_GET_ACTIVITIES: { + response.putStringArray(TestProtocol.TEST_INFO_RESPONSE_FIELD, + sActivities.stream().map( + a -> a.getClass().getSimpleName() + " (" + + (a.isDestroyed() ? "destroyed" : "current") + ")") + .toArray(String[]::new)); + return response; + } + + case TestProtocol.REQUEST_MODEL_QUEUE_CLEARED: + return getFromExecutorSync(MODEL_EXECUTOR, Bundle::new); + default: return null; } @@ -387,4 +542,38 @@ public class TestInformationHandler implements ResourceBasedOverride { */ void set(Bundle b, String key, T value); } + + + 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(); + } + } + }; + } }