Merging ub-launcher3-master, build 5945220
Test: Manual
Bug:123904290 P2 Remove magic constants from TAPL
Bug:130294785 P3 Can no longer long press to open settings in hotseat area
Bug:131115553 P2 Enable CacheDataUpdatedTaskTest tests
Bug:134712476 P4 Add Duo contact to home screen, icon froze and vanished while over home screen
Bug:136278866 P2 Temporary workarounds to make tests pass on Cuttlefish
Bug:136829198 P2 Scrolling Overview During Quickswitch causes switch with weird animation
Bug:137568159 P4 Refactor LauncherCallback to support multiple clients
Bug:137777105 P1 Make clearcut launcher logging feature parity with westworld logging
Bug:137851409 P4 Jank during swipe up due to inflation
Bug:138620399 P1 Quick switch flicker / artifacts
Bug:139016518 P2 [PinnedStackController] Move shelf offset into sysui
Bug:139137636 P2 Create memory tests for Launcher
Bug:139258979 P2 Switch to the screenshot mode when then system passes ThumbnailData back upon RecentsAnimation cancelation
Bug:139259253 P2 Transform multiple app surfaces during app open animation from overview
Bug:139439373 P2 Live tile should switch to screenshot before finishing recents animation
Bug:139828243 P2 Create a prototype for Overview screenshot actions with a SystemUI plugin
Bug:139888225 P2 Convert custom widget into plugins
Bug:139913027 P2 [a11y] App title in Widget list shouldn't be actionable by a11y methods. (It would cause Pixel launcher crash.)
Bug:139917483 P1 [B1C1][Dec19_QPR][CTS_Verifier_10_r1]Pixel launcher crash observed in Device owner test-> Lock Task UI
Bug:139941530 P2 Lab-only Flake: Launcher switches to All Apps after pressing Recents button
Bug:140212732 P2 [PO Cable] Strange launcher behavior after restore
Bug:140242324 P2 Cache shortcutInfo icons in Launcher
Bug:140246642 P4 Add binder tests for launcher interactions
Bug:140311911 P2 Flake in Launcher tests: java.lang.AssertionError: Stable state != state: OverviewState, LauncherState
Bug:140406263 P2 [a11y] Unable to scroll to the left of the main Home screen to Display google app by Voice access or Switch access.
Bug:140539007 P3 After apply the wallpaper on wallpaper picker, the screen will stay on wallpaper picker about 2 second
Bug:140626334 P4 Pass wallpaper SC to launcher for animation during launch and swipe up
Bug:140635319 P1 [Flaky test] testPromiseIcon_addedFromEligibleSession failing due to NPE on Launcher#getStateManager
Bug:140786694 P2 [A11y]No talkback feedback when long pressing on an app at home screen
Bug:140935140 P1 Launcher force close observed while accessing app info shortcuts.
Bug:141260670 P3 Drag and drop preview doesn't match the destination grid size
Bug:141262820 P3 [Grid] icon badge size should scale as the grid size changes
Bug:141265063 P2 Long press on homescreen in between icons doesn't bring up home settings
Bug:141275518 P2 Test WellbeingTests.testPauseAppFromOverview flakes on Cuttlefish
Bug:141315387 P1 [Failing test] 3P launchers + 2 button mode: failed goToOverviewFromHome and goToOverviewFromApp
Bug:141376165 P2 Remove static initializations in Launcher
Bug:141390432 P1 [Failing test] TaplTestsLauncher3 in 2-button mode
Bug:141517004 P1 FallbackRecentsTest.goToOverviewFromHome Failure
Bug:141522764 P1 DefaultLayoutProviderTest failures
Bug:141523101 P1 TaplTestsQuickstep#testAllAppsFromHome,testAllAppsFromOverview failures
Bug:141524555 P1 FallbackRecentsTest.testOverview flake
Bug:141576561 P2 Fix FlagOverrideSampleTest inside robolectric test
Bug:141576665 P2 AddWorkspaceItemsTaskTest broken
Bug:141577881 P2 FileLogTest broken
Bug:141579810 P1 ViewInflationDuringSwipeUp test failures
Bug:141580748 P2 FallbackRecentsTest#testOverview failure
Bug:141697444 P1 TaplTestsLauncher3#testWidgets test failure
Bug:141770616 P2 Flake: Can't find a launcher object; selector: BySelector [RES='\Qcom.google.android.apps.nexuslauncher:id/deep_shortcuts_container\E'] (visible state: AllApps),
Bug:141772190 P2 Flake: Context menu is still visible afterswiping up to home
Bug:141864547 P2 calendar-stable sometimes fails dialog dismissal on cuttlefish
Bug:141886704 P2 Use app targets to determine input consumer instead of launcher state
Bug:141934188 P2 Automation Test for adding widget automatically
Bug:141939911 P3 Clean up SwipeDetector
Bug:141986013 P2 Update all apps fade interpolators
Bug:142068081 P1 Quick Switch touch swipe dropped, flicker ensues
Bug:142120338 P2 Gmail app (work profile) icon not drawing
Bug:142148773 P2 grid size should not affect widget padding in WidgetsRecyclerView
Bug:142351228 P1 public void testSwipeUp_with_list_widgets() is failing for merge CL
Bug:79868152 P3 Fade out caret with workspace and back in when in Overview
Bug:136282913 P1 Swipe up from Assistant Fulfillment Card Jank
Bug:138473688 P4 Home settings can't be dismissed by swipe up
Bug:140252765 P2 Audit Gesture Nav tests (including Back and Quick Switch)
Bug:141568904 P1 NPE: Pixel launcher crash is observed when adding Directions widget
Bug:142514365 P1 Failing test AddWidgetTest.testDragIcon
Bug:142803200 P1 Broken binder tests
Change-Id: I811537cc8d406f0acd9fa45daddae4da79ffff12
diff --git a/tests/Android.mk b/tests/Android.mk
index b5c1dae..31a9960 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -30,7 +30,6 @@
LOCAL_STATIC_JAVA_LIBRARIES += SystemUISharedLib
LOCAL_SRC_FILES := $(call all-java-files-under, tapl) \
- ../quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java \
../src/com/android/launcher3/ResourceUtils.java \
../src/com/android/launcher3/util/SecureSettingsObserver.java \
../src/com/android/launcher3/testing/TestProtocol.java
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index c6f55a7..56eca6d 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -62,6 +62,12 @@
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
+ <activity android:name="com.android.launcher3.testcomponent.CustomShortcutConfigActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.CREATE_SHORTCUT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
<activity
android:name="com.android.launcher3.testcomponent.RequestPinItemActivity"
android:icon="@drawable/test_drawable_pin_item"
@@ -73,8 +79,12 @@
</intent-filter>
</activity>
+ <service
+ android:name="com.android.launcher3.testcomponent.ListViewService"
+ android:permission="android.permission.BIND_REMOTEVIEWS" />
+
<provider
- android:name="com.android.launcher3.testcomponent.TestCommandReceiver"
+ android:name="com.android.launcher3.testcomponent.TestCommandProvider"
android:authorities="${packageName}.commands"
android:exported="true"/>
diff --git a/tests/res/layout/test_layout_widget_list.xml b/tests/res/layout/test_layout_widget_list.xml
new file mode 100644
index 0000000..0152040
--- /dev/null
+++ b/tests/res/layout/test_layout_widget_list.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#FFFFFF">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#FF0000FF"
+ android:id="@android:id/text1"
+ android:padding="10dp" />
+
+ <ListView
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:id="@android:id/list" />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java b/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
index 7ef946d..efbd9c9 100644
--- a/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
+++ b/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
@@ -48,6 +48,7 @@
public void setUp() throws Exception {
super.setUp();
mDevice.pressHome();
+ waitForLauncherCondition("Launcher didn't start", launcher -> launcher != null);
waitForState("Launcher internal state didn't switch to Home", LauncherState.NORMAL);
mSessionId = -1;
}
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 64df8e0..7029ad5 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -1,29 +1,5 @@
package com.android.launcher3.model;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.database.MatrixCursor;
-import android.graphics.Bitmap;
-import android.os.Process;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.launcher3.WorkspaceItemInfo;
-import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.ItemInfo;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.compat.LauncherAppsCompat;
-import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.util.PackageManagerHelper;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static com.android.launcher3.LauncherSettings.Favorites.INTENT;
import static com.android.launcher3.LauncherSettings.Favorites.CELLX;
import static com.android.launcher3.LauncherSettings.Favorites.CELLY;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER;
@@ -32,6 +8,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.ICON;
import static com.android.launcher3.LauncherSettings.Favorites.ICON_PACKAGE;
import static com.android.launcher3.LauncherSettings.Favorites.ICON_RESOURCE;
+import static com.android.launcher3.LauncherSettings.Favorites.INTENT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
@@ -40,15 +17,41 @@
import static com.android.launcher3.LauncherSettings.Favorites.SCREEN;
import static com.android.launcher3.LauncherSettings.Favorites.TITLE;
import static com.android.launcher3.LauncherSettings.Favorites._ID;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
+
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.database.MatrixCursor;
+import android.graphics.Bitmap;
+import android.os.Process;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.WorkspaceItemInfo;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.util.PackageManagerHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
* Tests for {@link LoaderCursor}
*/
@@ -62,7 +65,7 @@
private MatrixCursor mCursor;
private InvariantDeviceProfile mIDP;
private Context mContext;
- private LauncherAppsCompat mLauncherApps;
+ private LauncherApps mLauncherApps;
private LoaderCursor mLoaderCursor;
@@ -81,7 +84,7 @@
when(mMockApp.getIconCache()).thenReturn(mMockIconCache);
when(mMockApp.getInvariantDeviceProfile()).thenReturn(mIDP);
when(mMockApp.getContext()).thenReturn(mContext);
- mLauncherApps = LauncherAppsCompat.getInstance(mContext);
+ mLauncherApps = mContext.getSystemService(LauncherApps.class);
mLoaderCursor = new LoaderCursor(mCursor, mMockApp);
mLoaderCursor.allUsers.put(0, Process.myUserHandle());
diff --git a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
index 6fa8d62..27990f4 100644
--- a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
+++ b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
@@ -1,8 +1,11 @@
package com.android.launcher3.provider;
+import static org.junit.Assert.assertEquals;
+
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
+
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
@@ -13,8 +16,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.assertEquals;
-
/**
* Tests for {@link RestoreDbTask}
*/
@@ -82,7 +83,7 @@
private final long mProfileId;
MyDatabaseHelper(long profileId) {
- super(InstrumentationRegistry.getContext(), null, null);
+ super(InstrumentationRegistry.getContext(), null);
mProfileId = profileId;
}
diff --git a/tests/src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java b/tests/src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java
new file mode 100644
index 0000000..b673faa
--- /dev/null
+++ b/tests/src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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.testcomponent;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+
+import com.android.launcher3.R;
+
+import java.util.UUID;
+
+/**
+ * A custom shortcut is a 1x1 widget that launches a specific intent when user tap on it.
+ * Custom shortcuts are replaced by deep shortcuts after api 25.
+ */
+public class CustomShortcutConfigActivity extends BaseTestingActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent launchIntent = new Intent(this, BaseTestingActivity.class)
+ .setAction("com.android.launcher3.intent.action.test_shortcut");
+ Intent shortcutIntent = createShortcutResultIntent(
+ this, UUID.randomUUID().toString(), "Shortcut",
+ R.drawable.ic_widget, launchIntent);
+ setResult(RESULT_OK, shortcutIntent);
+ finish();
+ }
+
+ private static Intent createShortcutResultIntent(
+ Context context, String uniqueId, String name, int iconId, Intent launchIntent) {
+ ShortcutInfo shortcutInfo =
+ createShortcutInfo(context, uniqueId, name, iconId, launchIntent);
+ ShortcutManager sm = context.getSystemService(ShortcutManager.class);
+ return sm.createShortcutResultIntent(shortcutInfo);
+ }
+
+ private static ShortcutInfo createShortcutInfo(
+ Context context, String uniqueId, String name, int iconId, Intent launchIntent) {
+ return new ShortcutInfo.Builder(context, uniqueId)
+ .setShortLabel(name)
+ .setLongLabel(name)
+ .setIcon(Icon.createWithResource(context, iconId))
+ .setIntent(launchIntent)
+ .build();
+ }
+}
diff --git a/tests/src/com/android/launcher3/testcomponent/ListViewService.java b/tests/src/com/android/launcher3/testcomponent/ListViewService.java
new file mode 100644
index 0000000..3da20e0
--- /dev/null
+++ b/tests/src/com/android/launcher3/testcomponent/ListViewService.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 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.testcomponent;
+
+import android.content.Intent;
+import android.os.IBinder;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
+
+public class ListViewService extends RemoteViewsService {
+
+ public static IBinder sBinderForTest;
+
+ @Override
+ public RemoteViewsFactory onGetViewFactory(Intent intent) {
+ return new SimpleViewsFactory();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return sBinderForTest != null ? sBinderForTest : super.onBind(intent);
+ }
+
+ public static class SimpleViewsFactory implements RemoteViewsFactory {
+
+ public int viewCount = 0;
+
+ @Override
+ public void onCreate() { }
+
+ @Override
+ public void onDataSetChanged() { }
+
+ @Override
+ public void onDestroy() { }
+
+ @Override
+ public int getCount() {
+ return viewCount;
+ }
+
+ @Override
+ public RemoteViews getViewAt(int i) {
+ RemoteViews views = new RemoteViews("android", android.R.layout.simple_list_item_1);
+ views.setTextViewText(android.R.id.text1, getLabel(i));
+ return views;
+ }
+
+ public String getLabel(int i) {
+ return "Item " + i;
+ }
+
+ @Override
+ public RemoteViews getLoadingView() {
+ return null;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return false;
+ }
+
+ public IBinder toBinder() {
+ return new RemoteViewsService() {
+ @Override
+ public RemoteViewsFactory onGetViewFactory(Intent intent) {
+ return SimpleViewsFactory.this;
+ }
+ }.onBind(new Intent("dummy_intent"));
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/testcomponent/TestCommandProvider.java b/tests/src/com/android/launcher3/testcomponent/TestCommandProvider.java
new file mode 100644
index 0000000..f9981a9
--- /dev/null
+++ b/tests/src/com/android/launcher3/testcomponent/TestCommandProvider.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 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.testcomponent;
+
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.DONT_KILL_APP;
+import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
+
+import static com.android.launcher3.testcomponent.TestCommandReceiver.DISABLE_TEST_LAUNCHER;
+import static com.android.launcher3.testcomponent.TestCommandReceiver.ENABLE_TEST_LAUNCHER;
+import static com.android.launcher3.testcomponent.TestCommandReceiver.EXTRA_VALUE;
+import static com.android.launcher3.testcomponent.TestCommandReceiver.GET_SYSTEM_HEALTH_MESSAGE;
+import static com.android.launcher3.testcomponent.TestCommandReceiver.KILL_PROCESS;
+import static com.android.launcher3.testcomponent.TestCommandReceiver.SET_LIST_VIEW_SERVICE_BINDER;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.util.Base64;
+
+import com.android.launcher3.tapl.TestHelpers;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+public class TestCommandProvider extends ContentProvider {
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException("unimplemented mock method");
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ throw new UnsupportedOperationException("unimplemented mock method");
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ throw new UnsupportedOperationException("unimplemented mock method");
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ throw new UnsupportedOperationException("unimplemented mock method");
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException("unimplemented mock method");
+ }
+
+ @Override
+ public Bundle call(String method, String arg, Bundle extras) {
+ switch (method) {
+ case ENABLE_TEST_LAUNCHER: {
+ getContext().getPackageManager().setComponentEnabledSetting(
+ new ComponentName(getContext(), TestLauncherActivity.class),
+ COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
+ return null;
+ }
+ case DISABLE_TEST_LAUNCHER: {
+ getContext().getPackageManager().setComponentEnabledSetting(
+ new ComponentName(getContext(), TestLauncherActivity.class),
+ COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP);
+ return null;
+ }
+ case KILL_PROCESS: {
+ ((ActivityManager) getContext().getSystemService(Activity.ACTIVITY_SERVICE))
+ .killBackgroundProcesses(arg);
+ return null;
+ }
+
+ case GET_SYSTEM_HEALTH_MESSAGE: {
+ final Bundle response = new Bundle();
+ response.putString("result",
+ TestHelpers.getSystemHealthMessage(getContext(), Long.parseLong(arg)));
+ return response;
+ }
+
+ case SET_LIST_VIEW_SERVICE_BINDER: {
+ ListViewService.sBinderForTest = extras.getBinder(EXTRA_VALUE);
+ return null;
+ }
+ }
+ return super.call(method, arg, extras);
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ String path = Base64.encodeToString(uri.getPath().getBytes(),
+ Base64.NO_CLOSE | Base64.NO_PADDING | Base64.NO_WRAP);
+ File file = new File(getContext().getCacheDir(), path);
+ if (!file.exists()) {
+ // Create an empty file so that we can pass its descriptor
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ }
+ }
+
+ return ParcelFileDescriptor.open(file, MODE_READ_WRITE);
+ }
+}
diff --git a/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java b/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java
index 6a6916e..eb6c3ed 100644
--- a/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java
+++ b/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java
@@ -15,125 +15,36 @@
*/
package com.android.launcher3.testcomponent;
-import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
-import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
-import static android.content.pm.PackageManager.DONT_KILL_APP;
-import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
-
-import android.app.Activity;
-import android.app.ActivityManager;
import android.app.Instrumentation;
-import android.content.ComponentName;
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
-import android.util.Base64;
import androidx.test.InstrumentationRegistry;
-import com.android.launcher3.tapl.TestHelpers;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
/**
* Content provider to receive commands from tests
*/
-public class TestCommandReceiver extends ContentProvider {
+public class TestCommandReceiver {
public static final String ENABLE_TEST_LAUNCHER = "enable-test-launcher";
public static final String DISABLE_TEST_LAUNCHER = "disable-test-launcher";
public static final String KILL_PROCESS = "kill-process";
public static final String GET_SYSTEM_HEALTH_MESSAGE = "get-system-health-message";
+ public static final String SET_LIST_VIEW_SERVICE_BINDER = "set-list-view-service-binder";
- @Override
- public boolean onCreate() {
- return true;
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException("unimplemented mock method");
- }
-
- @Override
- public String getType(Uri uri) {
- throw new UnsupportedOperationException("unimplemented mock method");
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- throw new UnsupportedOperationException("unimplemented mock method");
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- throw new UnsupportedOperationException("unimplemented mock method");
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException("unimplemented mock method");
- }
-
- @Override
- public Bundle call(String method, String arg, Bundle extras) {
- switch (method) {
- case ENABLE_TEST_LAUNCHER: {
- getContext().getPackageManager().setComponentEnabledSetting(
- new ComponentName(getContext(), TestLauncherActivity.class),
- COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
- return null;
- }
- case DISABLE_TEST_LAUNCHER: {
- getContext().getPackageManager().setComponentEnabledSetting(
- new ComponentName(getContext(), TestLauncherActivity.class),
- COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP);
- return null;
- }
- case KILL_PROCESS: {
- ((ActivityManager) getContext().getSystemService(Activity.ACTIVITY_SERVICE)).
- killBackgroundProcesses(arg);
- return null;
- }
-
- case GET_SYSTEM_HEALTH_MESSAGE: {
- final Bundle response = new Bundle();
- response.putString("result", TestHelpers.getSystemHealthMessage(getContext()));
- return response;
- }
- }
- return super.call(method, arg, extras);
- }
+ public static final String EXTRA_VALUE = "value";
public static Bundle callCommand(String command) {
return callCommand(command, null);
}
public static Bundle callCommand(String command, String arg) {
- Instrumentation inst = InstrumentationRegistry.getInstrumentation();
- Uri uri = Uri.parse("content://" + inst.getContext().getPackageName() + ".commands");
- return inst.getTargetContext().getContentResolver().call(uri, command, arg, null);
+ return callCommand(command, arg, null);
}
- @Override
- public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
- String path = Base64.encodeToString(uri.getPath().getBytes(),
- Base64.NO_CLOSE | Base64.NO_PADDING | Base64.NO_WRAP);
- File file = new File(getContext().getCacheDir(), path);
- if (!file.exists()) {
- // Create an empty file so that we can pass its descriptor
- try {
- file.createNewFile();
- } catch (IOException e) {
- }
- }
-
- return ParcelFileDescriptor.open(file, MODE_READ_WRITE);
+ public static Bundle callCommand(String command, String arg, Bundle extras) {
+ Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ Uri uri = Uri.parse("content://" + inst.getContext().getPackageName() + ".commands");
+ return inst.getTargetContext().getContentResolver().call(uri, command, arg, extras);
}
}
diff --git a/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java b/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java
index e042357..f209fae 100644
--- a/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java
+++ b/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java
@@ -25,6 +25,10 @@
import android.util.Log;
import android.view.ViewConfiguration;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import com.android.launcher3.testcomponent.TouchEventGenerator;
import org.junit.Before;
@@ -33,10 +37,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class SwipeDetectorTest {
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 1fac708..62989a3 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -17,6 +17,7 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
import static com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -27,11 +28,13 @@
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.os.Process;
import android.os.RemoteException;
@@ -43,19 +46,19 @@
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
+import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.Utilities;
-import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Wait;
@@ -94,8 +97,7 @@
protected LooperExecutor mMainThreadExecutor = MAIN_EXECUTOR;
protected final UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
- protected final LauncherInstrumentation mLauncher =
- new LauncherInstrumentation(getInstrumentation());
+ protected final LauncherInstrumentation mLauncher = new LauncherInstrumentation();
protected Context mTargetContext;
protected String mTargetPackage;
@@ -107,8 +109,9 @@
}
if (TestHelpers.isInLauncherProcess()) {
Utilities.enableRunningInTestHarnessForTests();
- mLauncher.setSystemHealthSupplier(() -> TestCommandReceiver.callCommand(
- TestCommandReceiver.GET_SYSTEM_HEALTH_MESSAGE).getString("result"));
+ mLauncher.setSystemHealthSupplier(startTime -> TestCommandReceiver.callCommand(
+ TestCommandReceiver.GET_SYSTEM_HEALTH_MESSAGE, startTime.toString()).
+ getString("result"));
mLauncher.setOnSettledStateAction(
containerType -> executeOnLauncher(
launcher ->
@@ -173,15 +176,13 @@
mTargetContext = InstrumentationRegistry.getTargetContext();
mTargetPackage = mTargetContext.getPackageName();
- // Unlock the phone
- mDevice.executeShellCommand("input keyevent 82");
}
@After
public void verifyLauncherState() {
try {
// Limits UI tests affecting tests running after them.
- waitForModelLoaded();
+ mLauncher.waitForLauncherInitialized();
} catch (Throwable t) {
Log.e(TAG,
"Couldn't deinit after a test, exiting tests, see logs for failures that "
@@ -220,14 +221,36 @@
} catch (Throwable t) {
throw new IllegalArgumentException(t);
}
- waitForModelLoaded();
+ mLauncher.waitForLauncherInitialized();
}
- protected void waitForModelLoaded() {
- waitForLauncherCondition("Launcher model didn't load", launcher -> {
- final LauncherModel model = LauncherAppState.getInstance(mTargetContext).getModel();
- return model.getCallback() == null || model.isModelLoaded();
- });
+ /**
+ * Adds {@param item} on the homescreen on the 0th screen
+ */
+ protected void addItemToScreen(ItemInfo item) {
+ ContentResolver resolver = mTargetContext.getContentResolver();
+ int screenId = FIRST_SCREEN_ID;
+ // Update the screen id counter for the provider.
+ LauncherSettings.Settings.call(resolver, LauncherSettings.Settings.METHOD_NEW_SCREEN_ID);
+
+ if (screenId > FIRST_SCREEN_ID) {
+ screenId = FIRST_SCREEN_ID;
+ }
+
+ // Insert the item
+ ContentWriter writer = new ContentWriter(mTargetContext);
+ item.id = LauncherSettings.Settings.call(
+ resolver, LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
+ .getInt(LauncherSettings.Settings.EXTRA_VALUE);
+ item.screenId = screenId;
+ item.onAddToDatabase(writer);
+ writer.put(LauncherSettings.Favorites._ID, item.id);
+ resolver.insert(LauncherSettings.Favorites.CONTENT_URI, writer.getValues(mTargetContext));
+ resetLoaderState();
+
+ // Launch the home activity
+ mDevice.pressHome();
+ mLauncher.waitForLauncherInitialized();
}
/**
@@ -312,9 +335,8 @@
}
protected LauncherActivityInfo getSettingsApp() {
- return LauncherAppsCompat.getInstance(mTargetContext)
- .getActivityList("com.android.settings",
- Process.myUserHandle()).get(0);
+ return mTargetContext.getSystemService(LauncherApps.class)
+ .getActivityList("com.android.settings", Process.myUserHandle()).get(0);
}
/**
diff --git a/tests/src/com/android/launcher3/ui/DefaultLayoutProviderTest.java b/tests/src/com/android/launcher3/ui/DefaultLayoutProviderTest.java
index a76b4a4..1d89d6e 100644
--- a/tests/src/com/android/launcher3/ui/DefaultLayoutProviderTest.java
+++ b/tests/src/com/android/launcher3/ui/DefaultLayoutProviderTest.java
@@ -30,7 +30,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
-import com.android.launcher3.testcomponent.TestCommandReceiver;
+import com.android.launcher3.testcomponent.TestCommandProvider;
import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.rule.ShellCommandRule;
@@ -63,7 +63,7 @@
PackageManager pm = mTargetContext.getPackageManager();
ProviderInfo pi = pm.getProviderInfo(new ComponentName(mContext,
- TestCommandReceiver.class), 0);
+ TestCommandProvider.class), 0);
mAuthority = pi.authority;
}
@@ -73,7 +73,6 @@
// Launch the home activity
mDevice.pressHome();
- waitForModelLoaded();
mLauncher.getWorkspace().getHotseatAppIcon(getSettingsApp().getLabel().toString());
}
@@ -89,7 +88,6 @@
// Launch the home activity
mDevice.pressHome();
- waitForModelLoaded();
// Verify widget present
assertTrue("Widget is not present",
@@ -106,7 +104,6 @@
// Launch the home activity
mDevice.pressHome();
- waitForModelLoaded();
mLauncher.getWorkspace().getHotseatFolder("Folder: Copy");
}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 2cf6c2b..5e87612 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -24,8 +24,6 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import android.util.Log;
-
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -38,7 +36,6 @@
import com.android.launcher3.tapl.AppIconMenuItem;
import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.tapl.Workspace;
-import com.android.launcher3.util.rule.TestStabilityRule.Stability;
import com.android.launcher3.views.OptionsPopupView;
import com.android.launcher3.widget.WidgetsFullSheet;
import com.android.launcher3.widget.WidgetsRecyclerView;
@@ -342,13 +339,24 @@
}
}
- public static String getAppPackageName() {
- return getInstrumentation().getContext().getPackageName();
+ /**
+ * Test dragging a custom shortcut to the workspace and launch it.
+ *
+ * A custom shortcut is a 1x1 widget that launches a specific intent when user tap on it.
+ * Custom shortcuts are replaced by deep shortcuts after api 25.
+ */
+ @Test
+ @Ignore("Temporarily disabled to unblock merging to master")
+ @PortraitLandscape
+ public void testDragCustomShortcut() {
+ mLauncher.getWorkspace().openAllWidgets()
+ .getWidget("com.android.launcher3.testcomponent.CustomShortcutConfigActivity")
+ .dragToWorkspace();
+ mLauncher.getWorkspace().getWorkspaceAppIcon("Shortcut")
+ .launch(getAppPackageName());
}
- @Test
- @Stability
- public void testTestStabilityAttribute() {
- Log.d("TestStabilityRule", "Hello world!");
+ public static String getAppPackageName() {
+ return getInstrumentation().getContext().getPackageName();
}
}
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index 3f35a3a..e1b3ede 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -41,7 +41,6 @@
import com.android.launcher3.util.rule.ShellCommandRule;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -53,7 +52,8 @@
@RunWith(AndroidJUnit4.class)
public class AddConfigWidgetTest extends AbstractLauncherUiTest {
- @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
+ @Rule
+ public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
private LauncherAppWidgetProviderInfo mWidgetInfo;
private AppWidgetManager mAppWidgetManager;
@@ -70,14 +70,12 @@
@Test
@PortraitLandscape
- @org.junit.Ignore
public void testWidgetConfig() throws Throwable {
runTest(true);
}
@Test
@PortraitLandscape
- @org.junit.Ignore
public void testConfigCancelled() throws Throwable {
runTest(false);
}
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index 1edce22..b8ca5de 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -30,7 +30,6 @@
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.rule.ShellCommandRule;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -42,11 +41,11 @@
@RunWith(AndroidJUnit4.class)
public class AddWidgetTest extends AbstractLauncherUiTest {
- @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
+ @Rule
+ public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
@Test
@PortraitLandscape
- @org.junit.Ignore
public void testDragIcon() throws Throwable {
clearHomescreen();
mDevice.pressHome();
diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
index e6348d9..3d691da 100644
--- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
@@ -15,7 +15,9 @@
*/
package com.android.launcher3.ui.widget;
-import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
+import static androidx.test.InstrumentationRegistry.getTargetContext;
+
+import static com.android.launcher3.widget.WidgetHostViewLoader.getDefaultOptionsForWidget;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -25,6 +27,7 @@
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.ContentResolver;
+import android.content.Context;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
@@ -39,15 +42,12 @@
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.compat.AppWidgetManagerCompat;
-import com.android.launcher3.compat.PackageInstallerCompat;
+import com.android.launcher3.pm.PackageInstallerCompat;
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
-import com.android.launcher3.util.ContentWriter;
-import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.widget.PendingAddWidgetInfo;
-import com.android.launcher3.widget.WidgetHostViewLoader;
import org.junit.After;
import org.junit.Before;
@@ -57,7 +57,6 @@
import java.util.HashSet;
import java.util.Set;
-import java.util.function.Consumer;
/**
* Tests for bind widget flow.
@@ -72,7 +71,6 @@
public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
private ContentResolver mResolver;
- private AppWidgetManagerCompat mWidgetManager;
// Objects created during test, which should be cleaned up in the end.
private Cursor mCursor;
@@ -85,7 +83,6 @@
super.setUp();
mResolver = mTargetContext.getContentResolver();
- mWidgetManager = AppWidgetManagerCompat.getInstance(mTargetContext);
// Clear all existing data
LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
@@ -108,7 +105,7 @@
LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, true);
LauncherAppWidgetInfo item = createWidgetInfo(info, true);
- setupContents(item);
+ addItemToScreen(item);
verifyWidgetPresent(info);
}
@@ -117,7 +114,7 @@
LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false);
LauncherAppWidgetInfo item = createWidgetInfo(info, true);
- setupContents(item);
+ addItemToScreen(item);
verifyWidgetPresent(info);
}
@@ -127,7 +124,7 @@
LauncherAppWidgetInfo item = createWidgetInfo(info, false);
item.appWidgetId = -33;
- setupContents(item);
+ addItemToScreen(item);
final Workspace workspace = mLauncher.getWorkspace();
// Item deleted from db
@@ -148,7 +145,7 @@
LauncherAppWidgetInfo item = createWidgetInfo(info, false);
item.restoreStatus = LauncherAppWidgetInfo.FLAG_ID_NOT_VALID;
- setupContents(item);
+ addItemToScreen(item);
verifyWidgetPresent(info);
}
@@ -161,7 +158,7 @@
LauncherAppWidgetInfo item = createWidgetInfo(info, false);
item.restoreStatus = LauncherAppWidgetInfo.FLAG_ID_NOT_VALID;
- setupContents(item);
+ addItemToScreen(item);
verifyPendingWidgetPresent();
// Item deleted from db
@@ -183,7 +180,7 @@
item.restoreStatus = LauncherAppWidgetInfo.FLAG_ID_NOT_VALID
| LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
- setupContents(item);
+ addItemToScreen(item);
assertTrue("Pending widget exists",
mLauncher.getWorkspace().tryGetPendingWidget(0) == null);
@@ -202,7 +199,7 @@
| LauncherAppWidgetInfo.FLAG_RESTORE_STARTED
| LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
- setupContents(item);
+ addItemToScreen(item);
verifyPendingWidgetPresent();
// Verify item still exists in db
@@ -230,7 +227,7 @@
PackageInstaller installer = mTargetContext.getPackageManager().getPackageInstaller();
mSessionId = installer.createSession(params);
- setupContents(item);
+ addItemToScreen(item);
verifyPendingWidgetPresent();
// Verify item still exists in db
@@ -245,35 +242,6 @@
& LauncherAppWidgetInfo.FLAG_ID_NOT_VALID);
}
- /**
- * Adds {@param item} on the homescreen on the 0th screen at 0,0, and verifies that the
- * widget class is displayed on the homescreen.
- */
- private void setupContents(LauncherAppWidgetInfo item) {
- int screenId = FIRST_SCREEN_ID;
- // Update the screen id counter for the provider.
- LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_NEW_SCREEN_ID);
-
- if (screenId > FIRST_SCREEN_ID) {
- screenId = FIRST_SCREEN_ID;
- }
-
- // Insert the item
- ContentWriter writer = new ContentWriter(mTargetContext);
- item.id = LauncherSettings.Settings.call(
- mResolver, LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
- .getInt(LauncherSettings.Settings.EXTRA_VALUE);
- item.screenId = screenId;
- item.onAddToDatabase(writer);
- writer.put(LauncherSettings.Favorites._ID, item.id);
- mResolver.insert(LauncherSettings.Favorites.CONTENT_URI, writer.getValues(mTargetContext));
- resetLoaderState();
-
- // Launch the home activity
- mDevice.pressHome();
- waitForModelLoaded();
- }
-
private void verifyWidgetPresent(LauncherAppWidgetProviderInfo info) {
assertTrue("Widget is not present",
mLauncher.getWorkspace().tryGetWidget(info.label, DEFAULT_UI_TIMEOUT) != null);
@@ -289,8 +257,10 @@
* @param bindWidget if true the info is bound and a valid widgetId is assigned to
* the LauncherAppWidgetInfo
*/
- private LauncherAppWidgetInfo createWidgetInfo(
+ public static LauncherAppWidgetInfo createWidgetInfo(
LauncherAppWidgetProviderInfo info, boolean bindWidget) {
+ Context targetContext = getTargetContext();
+
LauncherAppWidgetInfo item = new LauncherAppWidgetInfo(
LauncherAppWidgetInfo.NO_ID, info.provider);
item.spanX = info.minSpanX;
@@ -308,11 +278,12 @@
pendingInfo.spanY = item.spanY;
pendingInfo.minSpanX = item.minSpanX;
pendingInfo.minSpanY = item.minSpanY;
- Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(mTargetContext, pendingInfo);
+ Bundle options = getDefaultOptionsForWidget(targetContext, pendingInfo);
- AppWidgetHost host = new LauncherAppWidgetHost(mTargetContext);
+ AppWidgetHost host = new LauncherAppWidgetHost(targetContext);
int widgetId = host.allocateAppWidgetId();
- if (!mWidgetManager.bindAppWidgetIdIfAllowed(widgetId, info, options)) {
+ if (!AppWidgetManagerCompat.getInstance(targetContext)
+ .bindAppWidgetIdIfAllowed(widgetId, info, options)) {
host.deleteAppWidgetId(widgetId);
throw new IllegalArgumentException("Unable to bind widget id");
}
@@ -331,7 +302,7 @@
Set<String> activePackage = getOnUiThread(() -> {
Set<String> packages = new HashSet<>();
- PackageInstallerCompat.getInstance(mTargetContext).updateAndGetActiveSessionCache()
+ PackageInstallerCompat.getInstance(mTargetContext).getActiveSessions()
.keySet().forEach(packageUserKey -> packages.add(packageUserKey.mPackageName));
return packages;
});
diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java b/tests/src/com/android/launcher3/util/RaceConditionReproducer.java
index 8f89173..ed2ec7b 100644
--- a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java
+++ b/tests/src/com/android/launcher3/util/RaceConditionReproducer.java
@@ -17,8 +17,6 @@
package com.android.launcher3.util;
import static com.android.launcher3.util.Executors.createAndStartNewLooper;
-import static com.android.launcher3.util.RaceConditionTracker.ENTER_POSTFIX;
-import static com.android.launcher3.util.RaceConditionTracker.EXIT_POSTFIX;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -64,15 +62,30 @@
*
* When we register event XXX:enter, we hold all other events until we register XXX:exit.
*/
-public class RaceConditionReproducer implements RaceConditionTracker.EventProcessor {
+public class RaceConditionReproducer {
private static final String TAG = "RaceConditionReproducer";
+
+ private static final boolean ENTER = true;
+ private static final boolean EXIT = false;
+ private static final String ENTER_POSTFIX = "enter";
+ private static final String EXIT_POSTFIX = "exit";
+
private static final long SHORT_TIMEOUT_MS = 2000;
private static final long LONG_TIMEOUT_MS = 60000;
// Handler used to resume postponed events.
- private static final Handler POSTPONED_EVENT_RESUME_HANDLER = createEventResumeHandler();
+ private static final Handler POSTPONED_EVENT_RESUME_HANDLER =
+ new Handler(createAndStartNewLooper("RaceConditionEventResumer"));
- private static Handler createEventResumeHandler() {
- return new Handler(createAndStartNewLooper("RaceConditionEventResumer"));
+ public static String enterExitEvt(String eventName, boolean isEnter) {
+ return eventName + ":" + (isEnter ? ENTER_POSTFIX : EXIT_POSTFIX);
+ }
+
+ public static String enterEvt(String eventName) {
+ return enterExitEvt(eventName, ENTER);
+ }
+
+ public static String exitEvt(String eventName) {
+ return enterExitEvt(eventName, EXIT);
}
/**
@@ -209,7 +222,8 @@
parseReproString(mReproString) : generateSequenceToFollowLocked();
Log.e(TAG, "---- Start of iteration; state:\n" + dumpStateLocked());
checkIfCompletedSequenceToFollowLocked();
- RaceConditionTracker.setEventProcessor(this);
+
+ TraceHelperForTest.setRaceConditionReproducer(this);
}
/**
@@ -218,7 +232,8 @@
* Returns whether we need more iterations.
*/
public synchronized boolean finishIteration() {
- RaceConditionTracker.setEventProcessor(null);
+ TraceHelperForTest.setRaceConditionReproducer(null);
+
runResumeAllEventsCallbackLocked();
assertTrue("Non-empty postponed events", mPostponedEvents.isEmpty());
assertTrue("Last registered event is :enter", lastEventAsEnter() == null);
@@ -243,7 +258,6 @@
/**
* Called when the app issues an event.
*/
- @Override
public void onEvent(String event) {
final Semaphore waitObject = tryRegisterEvent(event);
if (waitObject != null) {
diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java b/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java
index 3fc268e..59f2173 100644
--- a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java
+++ b/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java
@@ -22,6 +22,8 @@
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,17 +39,29 @@
return res;
}
- private static void run3_3_TestAction() throws InterruptedException {
+ RaceConditionReproducer eventProcessor;
+
+ @Before
+ public void setup() {
+ eventProcessor = new RaceConditionReproducer();
+ }
+
+ @After
+ public void tearDown() {
+ TraceHelperForTest.cleanup();
+ }
+
+ private void run3_3_TestAction() throws InterruptedException {
Thread tb = new Thread(() -> {
- RaceConditionTracker.onEvent("B1");
- RaceConditionTracker.onEvent("B2");
- RaceConditionTracker.onEvent("B3");
+ eventProcessor.onEvent("B1");
+ eventProcessor.onEvent("B2");
+ eventProcessor.onEvent("B3");
});
tb.start();
- RaceConditionTracker.onEvent("A1");
- RaceConditionTracker.onEvent("A2");
- RaceConditionTracker.onEvent("A3");
+ eventProcessor.onEvent("A1");
+ eventProcessor.onEvent("A2");
+ eventProcessor.onEvent("A3");
tb.join();
}
@@ -56,7 +70,6 @@
@Ignore // The test is too long for continuous testing.
// 2 threads, 3 events each.
public void test3_3() throws Exception {
- final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
boolean sawTheValidSequence = false;
for (; ; ) {
@@ -80,25 +93,24 @@
@Ignore // The test is too long for continuous testing.
// 2 threads, 3 events, including enter-exit pairs each.
public void test3_3_enter_exit() throws Exception {
- final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
boolean sawTheValidSequence = false;
for (; ; ) {
eventProcessor.startIteration();
Thread tb = new Thread(() -> {
- RaceConditionTracker.onEvent("B1:enter");
- RaceConditionTracker.onEvent("B1:exit");
- RaceConditionTracker.onEvent("B2");
- RaceConditionTracker.onEvent("B3:enter");
- RaceConditionTracker.onEvent("B3:exit");
+ eventProcessor.onEvent("B1:enter");
+ eventProcessor.onEvent("B1:exit");
+ eventProcessor.onEvent("B2");
+ eventProcessor.onEvent("B3:enter");
+ eventProcessor.onEvent("B3:exit");
});
tb.start();
- RaceConditionTracker.onEvent("A1");
- RaceConditionTracker.onEvent("A2:enter");
- RaceConditionTracker.onEvent("A2:exit");
- RaceConditionTracker.onEvent("A3:enter");
- RaceConditionTracker.onEvent("A3:exit");
+ eventProcessor.onEvent("A1");
+ eventProcessor.onEvent("A2:enter");
+ eventProcessor.onEvent("A2:exit");
+ eventProcessor.onEvent("A3:enter");
+ eventProcessor.onEvent("A3:exit");
tb.join();
final boolean needMoreIterations = eventProcessor.finishIteration();
@@ -119,9 +131,7 @@
@Test
// 2 threads, 3 events each; reproducing a particular event sequence.
public void test3_3_ReproMode() throws Exception {
- final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(
- SOME_VALID_SEQUENCE_3_3);
-
+ eventProcessor = new RaceConditionReproducer(SOME_VALID_SEQUENCE_3_3);
eventProcessor.startIteration();
run3_3_TestAction();
assertTrue(!eventProcessor.finishIteration());
@@ -134,23 +144,21 @@
@Ignore // The test is too long for continuous testing.
// 2 threads with 2 events; 1 thread with 1 event.
public void test2_1_2() throws Exception {
- final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
-
for (; ; ) {
eventProcessor.startIteration();
Thread tb = new Thread(() -> {
- RaceConditionTracker.onEvent("B1");
- RaceConditionTracker.onEvent("B2");
+ eventProcessor.onEvent("B1");
+ eventProcessor.onEvent("B2");
});
tb.start();
Thread tc = new Thread(() -> {
- RaceConditionTracker.onEvent("C1");
+ eventProcessor.onEvent("C1");
});
tc.start();
- RaceConditionTracker.onEvent("A1");
- RaceConditionTracker.onEvent("A2");
+ eventProcessor.onEvent("A1");
+ eventProcessor.onEvent("A2");
tb.join();
tc.join();
@@ -167,28 +175,26 @@
@Ignore // The test is too long for continuous testing.
// 2 threads with 2 events; 1 thread with 1 event. Includes enter-exit pairs.
public void test2_1_2_enter_exit() throws Exception {
- final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
-
for (; ; ) {
eventProcessor.startIteration();
Thread tb = new Thread(() -> {
- RaceConditionTracker.onEvent("B1:enter");
- RaceConditionTracker.onEvent("B1:exit");
- RaceConditionTracker.onEvent("B2:enter");
- RaceConditionTracker.onEvent("B2:exit");
+ eventProcessor.onEvent("B1:enter");
+ eventProcessor.onEvent("B1:exit");
+ eventProcessor.onEvent("B2:enter");
+ eventProcessor.onEvent("B2:exit");
});
tb.start();
Thread tc = new Thread(() -> {
- RaceConditionTracker.onEvent("C1:enter");
- RaceConditionTracker.onEvent("C1:exit");
+ eventProcessor.onEvent("C1:enter");
+ eventProcessor.onEvent("C1:exit");
});
tc.start();
- RaceConditionTracker.onEvent("A1:enter");
- RaceConditionTracker.onEvent("A1:exit");
- RaceConditionTracker.onEvent("A2:enter");
- RaceConditionTracker.onEvent("A2:exit");
+ eventProcessor.onEvent("A1:enter");
+ eventProcessor.onEvent("A1:exit");
+ eventProcessor.onEvent("A2:enter");
+ eventProcessor.onEvent("A2:exit");
tb.join();
tc.join();
diff --git a/tests/src/com/android/launcher3/util/TraceHelperForTest.java b/tests/src/com/android/launcher3/util/TraceHelperForTest.java
new file mode 100644
index 0000000..f1c8a67
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/TraceHelperForTest.java
@@ -0,0 +1,116 @@
+/**
+ * Copyright (C) 2019 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.util;
+
+import java.util.LinkedList;
+import java.util.function.IntConsumer;
+
+public class TraceHelperForTest extends TraceHelper {
+
+ private static final TraceHelperForTest INSTANCE_FOR_TEST = new TraceHelperForTest();
+
+ private final ThreadLocal<LinkedList<TraceInfo>> mStack =
+ ThreadLocal.withInitial(LinkedList::new);
+
+ private RaceConditionReproducer mRaceConditionReproducer;
+ private IntConsumer mFlagsChangeListener;
+
+ public static void setRaceConditionReproducer(RaceConditionReproducer reproducer) {
+ TraceHelper.INSTANCE = INSTANCE_FOR_TEST;
+ INSTANCE_FOR_TEST.mRaceConditionReproducer = reproducer;
+ }
+
+ public static void cleanup() {
+ INSTANCE_FOR_TEST.mRaceConditionReproducer = null;
+ INSTANCE_FOR_TEST.mFlagsChangeListener = null;
+ }
+
+ public static void setFlagsChangeListener(IntConsumer listener) {
+ TraceHelper.INSTANCE = INSTANCE_FOR_TEST;
+ INSTANCE_FOR_TEST.mFlagsChangeListener = listener;
+ }
+
+ private TraceHelperForTest() { }
+
+ @Override
+ public Object beginSection(String sectionName, int flags) {
+ LinkedList<TraceInfo> stack = mStack.get();
+ TraceInfo info = new TraceInfo(sectionName, flags);
+ stack.add(info);
+
+ if ((flags & TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS) != 0
+ && mRaceConditionReproducer != null) {
+ mRaceConditionReproducer.onEvent(RaceConditionReproducer.enterEvt(sectionName));
+ }
+ updateBinderTracking(stack);
+
+ super.beginSection(sectionName, flags);
+ return info;
+ }
+
+ @Override
+ public void endSection(Object token) {
+ LinkedList<TraceInfo> stack = mStack.get();
+ if (stack.size() == 0) {
+ new Throwable().printStackTrace();
+ }
+ TraceInfo info = (TraceInfo) token;
+ stack.remove(info);
+ if ((info.flags & TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS) != 0
+ && mRaceConditionReproducer != null) {
+ mRaceConditionReproducer.onEvent(RaceConditionReproducer.exitEvt(info.sectionName));
+ }
+ updateBinderTracking(stack);
+
+ super.endSection(token);
+ }
+
+ @Override
+ public Object beginFlagsOverride(int flags) {
+ LinkedList<TraceInfo> stack = mStack.get();
+ TraceInfo info = new TraceInfo(null, flags);
+ stack.add(info);
+ updateBinderTracking(stack);
+ super.beginFlagsOverride(flags);
+ return info;
+ }
+
+ @Override
+ public void endFlagsOverride(Object token) {
+ super.endFlagsOverride(token);
+ LinkedList<TraceInfo> stack = mStack.get();
+ TraceInfo info = (TraceInfo) token;
+ stack.remove(info);
+ updateBinderTracking(stack);
+ }
+
+ private void updateBinderTracking(LinkedList<TraceInfo> stack) {
+ if (mFlagsChangeListener != null) {
+ mFlagsChangeListener.accept(stack.stream()
+ .mapToInt(info -> info.flags).reduce(0, (a, b) -> a | b));
+ }
+ }
+
+ private static class TraceInfo {
+ public final String sectionName;
+ public final int flags;
+
+ TraceInfo(String sectionName, int flags) {
+ this.sectionName = sectionName;
+ this.flags = flags;
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
index 8391ae7..69bf01d 100644
--- a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
+++ b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
@@ -17,6 +17,7 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
@@ -37,11 +38,11 @@
private static final String TAG = "TestStabilityRule";
private static final Pattern LAUNCHER_BUILD =
Pattern.compile("^("
- + "(?<androidStudio>BuildFromAndroidStudio)|"
- + "(?<commandLine>[0-9]+-eng\\.[a-z]+\\.[0-9]+\\.[0-9]+)|"
- + "(?<presubmit>[0-9]+-P[0-9]+)|"
- + "(?<postsubmit>[0-9]+-[0-9]+|"
- + "(?<platform>[0-9]+))"
+ + "(?<local>(BuildFromAndroidStudio|"
+ + "([0-9]+|[A-Z])-eng\\.[a-z]+\\.[0-9]+\\.[0-9]+))|"
+ + "(?<presubmit>([0-9]+|[A-Z])-P[0-9]+)|"
+ + "(?<postsubmit>([0-9]+|[A-Z])-[0-9]+)|"
+ + "(?<platform>[0-9]+|[A-Z])"
+ ")$");
private static final Pattern PLATFORM_BUILD =
Pattern.compile("^("
@@ -50,88 +51,97 @@
+ "(?<postsubmit>[0-9]+)"
+ ")$");
+ public static final int LOCAL = 0x1;
+ public static final int UNBUNDLED_PRESUBMIT = 0x2;
+ public static final int UNBUNDLED_POSTSUBMIT = 0x4;
+ public static final int PLATFORM_PRESUBMIT = 0x8;
+ public static final int PLATFORM_POSTSUBMIT = 0x10;
+
+ private static final int RUN_FLAFOR = getRunFlavor();
+
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Stability {
+ int flavors();
}
@Override
public Statement apply(Statement base, Description description) {
- if (description.getAnnotation(Stability.class) != null) {
+ final Stability stability = description.getAnnotation(Stability.class);
+ if (stability != null) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
- final String launcherVersion =
- getInstrumentation().
- getContext().
- getPackageManager().
- getPackageInfo(
- UiDevice.getInstance(getInstrumentation()).
- getLauncherPackageName(),
- 0).
- versionName;
-
- final Matcher launcherBuildMatcher = LAUNCHER_BUILD.matcher(launcherVersion);
-
- boolean launcherLocalBuild = false;
- boolean launcherUnbundledPresubmit = false;
- boolean launcherUnbundledPostsubmit = false;
- boolean launcherPlatform = false;
-
- if (!launcherBuildMatcher.find()) {
- Log.e(TAG, "Match not found");
- } else if (launcherBuildMatcher.group("androidStudio") != null
- || launcherBuildMatcher.group("commandLine") != null) {
- launcherLocalBuild = true;
- } else if (launcherBuildMatcher.group("presubmit") != null) {
- launcherUnbundledPresubmit = true;
- } else if (launcherBuildMatcher.group("postsubmit") != null) {
- launcherUnbundledPostsubmit = true;
- } else if (launcherBuildMatcher.group("platform") != null) {
- launcherPlatform = true;
+ if ((stability.flavors() & RUN_FLAFOR) != 0) {
+ Log.d(TAG, "Running " + description.getDisplayName());
+ base.evaluate();
} else {
- Log.e(TAG, "ERROR1");
+ Log.d(TAG, "Skipping " + description.getDisplayName());
}
-
- boolean platformLocalBuild = false;
- boolean platformPresubmit = false;
- boolean platformPostsubmit = false;
-
- final String platformVersion = Build.VERSION.INCREMENTAL;
- final Matcher platformBuildMatcher = PLATFORM_BUILD.matcher(platformVersion);
- if (!platformBuildMatcher.find()) {
- Log.e(TAG, "Match not found");
- } else if (platformBuildMatcher.group("commandLine") != null) {
- platformLocalBuild = true;
- } else if (platformBuildMatcher.group("presubmit") != null) {
- platformPresubmit = true;
- } else if (platformBuildMatcher.group("postsubmit") != null) {
- platformPostsubmit = true;
- } else {
- Log.e(TAG, "ERROR2");
- }
-
- Log.d(TAG, "Launcher: " + launcherVersion + ", platform: " + platformVersion);
-
- if (launcherLocalBuild && (platformLocalBuild || platformPostsubmit)) {
- Log.d(TAG, "LOCAL RUN");
- } else if (launcherUnbundledPresubmit && platformPostsubmit) {
- Log.d(TAG, "UNBUNDLED PRESUBMIT");
- } else if (launcherUnbundledPostsubmit && platformPostsubmit) {
- Log.d(TAG, "UNBUNDLED POSTSUBMIT");
- } else if (launcherPlatform && platformPresubmit) {
- Log.d(TAG, "PLATFORM PRESUBMIT");
- } else if (launcherPlatform && platformPostsubmit) {
- Log.d(TAG, "PLATFORM POSTSUBMIT");
- } else {
- Log.e(TAG, "ERROR3");
- }
-
- base.evaluate();
}
};
} else {
return base;
}
}
+
+ private static int getRunFlavor() {
+ final String launcherVersion;
+ try {
+ launcherVersion = getInstrumentation().
+ getContext().
+ getPackageManager().
+ getPackageInfo(
+ UiDevice.getInstance(getInstrumentation()).
+ getLauncherPackageName(),
+ 0).
+ versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ final Matcher launcherBuildMatcher = LAUNCHER_BUILD.matcher(launcherVersion);
+
+ if (!launcherBuildMatcher.find()) {
+ throw new AssertionError("Launcher build match not found");
+ }
+
+ final String platformVersion = Build.VERSION.INCREMENTAL;
+ final Matcher platformBuildMatcher = PLATFORM_BUILD.matcher(platformVersion);
+
+ if (!platformBuildMatcher.find()) {
+ throw new AssertionError("Platform build match not found");
+ }
+
+ Log.d(TAG, "Launcher: " + launcherVersion + ", platform: " + platformVersion);
+
+ final int runFlavor;
+
+ if (launcherBuildMatcher.group("local") != null && (
+ platformBuildMatcher.group("commandLine") != null ||
+ platformBuildMatcher.group("postsubmit") != null)) {
+ Log.d(TAG, "LOCAL RUN");
+ runFlavor = LOCAL;
+ } else if (launcherBuildMatcher.group("presubmit") != null
+ && platformBuildMatcher.group("postsubmit") != null) {
+ Log.d(TAG, "UNBUNDLED PRESUBMIT");
+ runFlavor = UNBUNDLED_PRESUBMIT;
+ } else if (launcherBuildMatcher.group("postsubmit") != null
+ && platformBuildMatcher.group("postsubmit") != null) {
+ Log.d(TAG, "UNBUNDLED POSTSUBMIT");
+ runFlavor = UNBUNDLED_POSTSUBMIT;
+ } else if (launcherBuildMatcher.group("platform") != null
+ && platformBuildMatcher.group("presubmit") != null) {
+ Log.d(TAG, "PLATFORM PRESUBMIT");
+ runFlavor = PLATFORM_PRESUBMIT;
+ } else if (launcherBuildMatcher.group("platform") != null
+ && platformBuildMatcher.group("postsubmit") != null) {
+ Log.d(TAG, "PLATFORM POSTSUBMIT");
+ runFlavor = PLATFORM_POSTSUBMIT;
+ } else {
+ throw new AssertionError("Unrecognized run flavor");
+ }
+
+ return runFlavor;
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index f070280..e1e9b8d 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -53,8 +53,8 @@
return LauncherInstrumentation.ContainerType.ALL_APPS;
}
- private boolean hasClickableIcon(
- UiObject2 allAppsContainer, UiObject2 appListRecycler, BySelector appIconSelector) {
+ private boolean hasClickableIcon(UiObject2 allAppsContainer, UiObject2 appListRecycler,
+ BySelector appIconSelector, int displayBottom) {
final UiObject2 icon = appListRecycler.findObject(appIconSelector);
if (icon == null) {
LauncherInstrumentation.log("hasClickableIcon: icon not visible");
@@ -66,6 +66,10 @@
LauncherInstrumentation.log("hasClickableIcon: icon center is under search box");
return false;
}
+ if (iconBounds.bottom > displayBottom) {
+ LauncherInstrumentation.log("hasClickableIcon: icon center bellow bottom offset");
+ return false;
+ }
LauncherInstrumentation.log("hasClickableIcon: icon is clickable");
return true;
}
@@ -90,21 +94,32 @@
final UiObject2 allAppsContainer = verifyActiveContainer();
final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer,
"apps_list_view");
+ final UiObject2 searchBox = getSearchBox(allAppsContainer);
+
+ int bottomGestureMargin = ResourceUtils.getNavbarSize(
+ ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mLauncher.getResources()) + 1;
+ int deviceHeight = mLauncher.getDevice().getDisplayHeight();
+ int displayBottom = deviceHeight - bottomGestureMargin;
allAppsContainer.setGestureMargins(
0,
getSearchBox(allAppsContainer).getVisibleBounds().bottom + 1,
0,
- ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
- mLauncher.getResources()) + 1);
+ bottomGestureMargin);
final BySelector appIconSelector = AppIcon.getAppIconSelector(appName, mLauncher);
- if (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector)) {
+ if (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector,
+ displayBottom)) {
scrollBackToBeginning();
int attempts = 0;
- int scroll = getScroll(allAppsContainer);
+ int scroll = getAllAppsScroll();
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled")) {
- while (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector)) {
- mLauncher.scroll(allAppsContainer, Direction.DOWN, 0.8f, null, 50);
- final int newScroll = getScroll(allAppsContainer);
+ while (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector,
+ displayBottom)) {
+ mLauncher.scrollToLastVisibleRow(
+ allAppsContainer,
+ mLauncher.getObjectsInContainer(allAppsContainer, "icon"),
+ searchBox.getVisibleBounds().bottom
+ - allAppsContainer.getVisibleBounds().top);
+ final int newScroll = getAllAppsScroll();
if (newScroll == scroll) break;
mLauncher.assertTrue(
@@ -117,8 +132,11 @@
verifyActiveContainer();
}
+ // Ignore bottom offset selection here as there might not be any scroll more scroll
+ // region available.
mLauncher.assertTrue("Unable to scroll to a clickable icon: " + appName,
- hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector));
+ hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector,
+ deviceHeight));
final UiObject2 appIcon = mLauncher.waitForObjectInContainer(appListRecycler,
appIconSelector);
@@ -136,16 +154,16 @@
int attempts = 0;
final Rect margins = new Rect(0, searchBox.getVisibleBounds().bottom + 1, 0, 5);
- for (int scroll = getScroll(allAppsContainer);
+ for (int scroll = getAllAppsScroll();
scroll != 0;
- scroll = getScroll(allAppsContainer)) {
+ scroll = getAllAppsScroll()) {
mLauncher.assertTrue("Negative scroll position", scroll > 0);
mLauncher.assertTrue(
"Exceeded max scroll attempts: " + MAX_SCROLL_ATTEMPTS,
++attempts <= MAX_SCROLL_ATTEMPTS);
- mLauncher.scroll(allAppsContainer, Direction.UP, 1, margins, 50);
+ mLauncher.scroll(allAppsContainer, Direction.UP, margins, 50);
}
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled up")) {
@@ -154,9 +172,10 @@
}
}
- private int getScroll(UiObject2 allAppsContainer) {
- return mLauncher.getAnswerFromLauncher(allAppsContainer, TestProtocol.GET_SCROLL_MESSAGE).
- getInt(TestProtocol.SCROLL_Y_FIELD, -1);
+ private int getAllAppsScroll() {
+ return mLauncher.getTestInfo(
+ TestProtocol.REQUEST_APPS_LIST_SCROLL_Y)
+ .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
private UiObject2 getSearchBox(UiObject2 allAppsContainer) {
@@ -172,7 +191,7 @@
final UiObject2 allAppsContainer = verifyActiveContainer();
// Start the gesture in the center to avoid starting at elements near the top.
mLauncher.scroll(
- allAppsContainer, Direction.DOWN, 1, new Rect(0, 0, 0, mHeight / 2), 10);
+ allAppsContainer, Direction.DOWN, new Rect(0, 0, 0, mHeight / 2), 10);
verifyActiveContainer();
}
}
@@ -186,7 +205,7 @@
final UiObject2 allAppsContainer = verifyActiveContainer();
// Start the gesture in the center, for symmetry with forward.
mLauncher.scroll(
- allAppsContainer, Direction.UP, 1, new Rect(0, mHeight / 2, 0, 0), 10);
+ allAppsContainer, Direction.UP, new Rect(0, mHeight / 2, 0, 0), 10);
verifyActiveContainer();
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index bcce8ef..0d9038f 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -23,6 +23,7 @@
import android.view.MotionEvent;
import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
import com.android.launcher3.testing.TestProtocol;
@@ -104,7 +105,12 @@
startY = endY = mLauncher.getDevice().getDisplayHeight() / 2;
}
- mLauncher.swipeToState(startX, startY, endX, endY, 10, expectedState);
+ if (mLauncher.isFallbackOverview()) {
+ mLauncher.linearGesture(startX, startY, endX, endY, 10);
+ new BaseOverview(mLauncher);
+ } else {
+ mLauncher.swipeToState(startX, startY, endX, endY, 10, expectedState);
+ }
break;
}
@@ -114,6 +120,60 @@
}
}
+ /**
+ * Swipes right or double presses the square button to switch to the previous app.
+ */
+ public Background quickSwitchToPreviousApp() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to quick switch to the previous app")) {
+ verifyActiveContainer();
+ quickSwitchToPreviousApp(getExpectedStateForQuickSwitch());
+ return new Background(mLauncher);
+ }
+ }
+
+ protected int getExpectedStateForQuickSwitch() {
+ return BACKGROUND_APP_STATE_ORDINAL;
+ }
+
+ protected void quickSwitchToPreviousApp(int expectedState) {
+ boolean transposeInLandscape = false;
+ switch (mLauncher.getNavigationModel()) {
+ case TWO_BUTTON:
+ transposeInLandscape = true;
+ // Fall through, zero button and two button modes behave the same.
+ case ZERO_BUTTON: {
+ final int startX;
+ final int startY;
+ final int endX;
+ final int endY;
+ if (mLauncher.getDevice().isNaturalOrientation() || !transposeInLandscape) {
+ // Swipe from the bottom left to the bottom right of the screen.
+ startX = 0;
+ startY = getSwipeStartY();
+ endX = mLauncher.getDevice().getDisplayWidth();
+ endY = startY;
+ } else {
+ // Swipe from the bottom right to the top right of the screen.
+ startX = getSwipeStartX();
+ startY = mLauncher.getRealDisplaySize().y - 1;
+ endX = startX;
+ endY = 0;
+ }
+ mLauncher.swipeToState(startX, startY, endX, endY, 20, expectedState);
+ break;
+ }
+
+ case THREE_BUTTON:
+ // Double press the recents button.
+ UiObject2 recentsButton = mLauncher.waitForSystemUiObject("recent_apps");
+ recentsButton.click();
+ mLauncher.getOverview();
+ recentsButton.click();
+ break;
+ }
+ }
+
protected String getSwipeHeightRequestName() {
return TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT;
}
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index eaa21ae..8ccfc05 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -55,7 +55,7 @@
final int leftMargin = mLauncher.getTestInfo(
TestProtocol.REQUEST_OVERVIEW_LEFT_GESTURE_MARGIN).
getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
- mLauncher.scroll(overview, Direction.LEFT, 1, new Rect(leftMargin, 0, 0, 0), 20);
+ mLauncher.scroll(overview, Direction.LEFT, new Rect(leftMargin + 1, 0, 0, 0), 20);
verifyActiveContainer();
}
}
@@ -89,7 +89,7 @@
final int rightMargin = mLauncher.getTestInfo(
TestProtocol.REQUEST_OVERVIEW_RIGHT_GESTURE_MARGIN).
getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
- mLauncher.scroll(overview, Direction.RIGHT, 1, new Rect(0, 0, rightMargin, 0), 20);
+ mLauncher.scroll(overview, Direction.RIGHT, new Rect(0, 0, rightMargin + 1, 0), 20);
verifyActiveContainer();
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Home.java b/tests/tapl/com/android/launcher3/tapl/Home.java
index cfc4374..e0fe933 100644
--- a/tests/tapl/com/android/launcher3/tapl/Home.java
+++ b/tests/tapl/com/android/launcher3/tapl/Home.java
@@ -17,6 +17,7 @@
package com.android.launcher3.tapl;
import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
+import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
import androidx.annotation.NonNull;
@@ -58,4 +59,9 @@
}
}
}
+
+ @Override
+ protected int getExpectedStateForQuickSwitch() {
+ return QUICK_SWITCH_STATE_ORDINAL;
+ }
}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 383c3ce..0879404 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -37,7 +37,6 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -52,6 +51,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.Configurator;
@@ -60,20 +60,24 @@
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
+import com.android.launcher3.ResourceUtils;
import com.android.launcher3.testing.TestProtocol;
import com.android.systemui.shared.system.QuickStepContract;
-import org.junit.Assert;
-
+import java.util.ArrayList;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
-import java.util.function.Supplier;
+import java.util.function.Function;
+
+import org.junit.Assert;
/**
* The main tapl object. The only object that can be explicitly constructed by the using code. It
@@ -84,6 +88,7 @@
private static final String TAG = "Tapl";
private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 20;
private static final int GESTURE_STEP_MS = 16;
+ private static long START_TIME = System.currentTimeMillis();
// Types for launcher containers that the user is interacting with. "Background" is a
// pseudo-container corresponding to inactive launcher covered by another app.
@@ -134,13 +139,22 @@
private int mExpectedRotation = Surface.ROTATION_0;
private final Uri mTestProviderUri;
private final Deque<String> mDiagnosticContext = new LinkedList<>();
- private Supplier<String> mSystemHealthSupplier;
+ private Function<Long, String> mSystemHealthSupplier;
private Consumer<ContainerType> mOnSettledStateAction;
/**
* Constructs the root of TAPL hierarchy. You get all other objects from it.
*/
+ public LauncherInstrumentation() {
+ this(InstrumentationRegistry.getInstrumentation());
+ }
+
+ /**
+ * Constructs the root of TAPL hierarchy. You get all other objects from it.
+ * Deprecated: use the constructor without parameters instead.
+ */
+ @Deprecated
public LauncherInstrumentation(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
mDevice = UiDevice.getInstance(instrumentation);
@@ -238,10 +252,6 @@
return null;
}
- public static boolean isAvd() {
- return Build.MODEL.contains("Cuttlefish");
- }
-
static void log(String message) {
Log.d(TAG, message);
}
@@ -296,7 +306,7 @@
return "Background";
}
- public void setSystemHealthSupplier(Supplier<String> supplier) {
+ public void setSystemHealthSupplier(Function<Long, String> supplier) {
this.mSystemHealthSupplier = supplier;
}
@@ -316,8 +326,8 @@
}
return mSystemHealthSupplier != null
- ? mSystemHealthSupplier.get()
- : TestHelpers.getSystemHealthMessage(getContext());
+ ? mSystemHealthSupplier.apply(START_TIME)
+ : TestHelpers.getSystemHealthMessage(getContext(), START_TIME);
}
private void fail(String message) {
@@ -486,8 +496,8 @@
}
}
- private void waitForLauncherInitialized() {
- for (int i = 0; i < 100; ++i) {
+ public void waitForLauncherInitialized() {
+ for (int i = 0; i < 600; ++i) {
if (getTestInfo(
TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED).
getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD)) {
@@ -512,15 +522,6 @@
}
}
- Bundle getAnswerFromLauncher(UiObject2 view, String requestTag) {
- // Send a fake set-text request to Launcher to initiate a response with requested data.
- final String responseTag = requestTag + TestProtocol.RESPONSE_MESSAGE_POSTFIX;
- return (Bundle) executeAndWaitForEvent(
- () -> view.setText(requestTag),
- event -> responseTag.equals(event.getClassName()),
- "Launcher didn't respond to request: " + requestTag);
- }
-
/**
* Presses nav bar home button.
*
@@ -534,6 +535,9 @@
// accessibility events prior to pressing Home.
final String action;
if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
+ final String anomaly = getAnomalyMessage();
+ if (anomaly != null) fail("Can't swipe up to Home: " + anomaly);
+
final Point displaySize = getRealDisplaySize();
if (hasLauncherObject("deep_shortcuts_container")) {
@@ -541,13 +545,17 @@
displaySize.x / 2, displaySize.y - 1,
displaySize.x / 2, 0,
ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME);
- assertTrue("Context menu is still visible afterswiping up to home",
- !hasLauncherObject("deep_shortcuts_container"));
+ try (LauncherInstrumentation.Closable c = addContextLayer(
+ "Swiped up from context menu to home")) {
+ waitUntilGone("deep_shortcuts_container");
+ }
}
if (hasLauncherObject(WORKSPACE_RES_ID)) {
log(action = "already at home");
} else {
- log(action = "swiping up to home");
+ log("Hierarchy before swiping up to home");
+ dumpViewHierarchy();
+ log(action = "swiping up to home from " + getVisibleStateMessage());
final int finalState = mDevice.hasObject(By.pkg(getLauncherPackageName()))
? NORMAL_STATE_ORDINAL : BACKGROUND_APP_STATE_ORDINAL;
@@ -769,7 +777,36 @@
TestProtocol.stateOrdinalToString(parcel.getInt(TestProtocol.STATE_FIELD)));
}
- void scroll(UiObject2 container, Direction direction, float percent, Rect margins, int steps) {
+ int getBottomGestureSize() {
+ return ResourceUtils.getNavbarSize(
+ ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, getResources()) + 1;
+ }
+
+ int getBottomGestureMargin(UiObject2 container) {
+ return container.getVisibleBounds().bottom - getRealDisplaySize().y
+ + getBottomGestureSize();
+ }
+
+ void scrollToLastVisibleRow(UiObject2 container, Collection<UiObject2> items, int topPadding) {
+ final UiObject2 lowestItem = Collections.max(items, (i1, i2) ->
+ Integer.compare(i1.getVisibleBounds().top, i2.getVisibleBounds().top));
+
+ final int gestureStart = lowestItem.getVisibleBounds().top + getTouchSlop();
+ final int distance = gestureStart - container.getVisibleBounds().top - topPadding;
+ final int bottomMargin = container.getVisibleBounds().height() - distance;
+
+ scroll(
+ container,
+ Direction.DOWN,
+ new Rect(
+ 0,
+ 0,
+ 0,
+ Math.max(bottomMargin, getBottomGestureMargin(container))),
+ 150);
+ }
+
+ void scroll(UiObject2 container, Direction direction, Rect margins, int steps) {
final Rect rect = container.getVisibleBounds();
if (margins != null) {
rect.left += margins.left;
@@ -786,34 +823,26 @@
switch (direction) {
case UP: {
startX = endX = rect.centerX();
- final int vertCenter = rect.centerY();
- final float halfGestureHeight = rect.height() * percent / 2.0f;
- startY = (int) (vertCenter - halfGestureHeight) + 1;
- endY = (int) (vertCenter + halfGestureHeight);
+ startY = rect.top;
+ endY = rect.bottom - 1;
}
break;
case DOWN: {
startX = endX = rect.centerX();
- final int vertCenter = rect.centerY();
- final float halfGestureHeight = rect.height() * percent / 2.0f;
- startY = (int) (vertCenter + halfGestureHeight) - 1;
- endY = (int) (vertCenter - halfGestureHeight);
+ startY = rect.bottom - 1;
+ endY = rect.top;
}
break;
case LEFT: {
startY = endY = rect.centerY();
- final int horizCenter = rect.centerX();
- final float halfGestureWidth = rect.width() * percent / 2.0f;
- startX = (int) (horizCenter - halfGestureWidth) + 1;
- endX = (int) (horizCenter + halfGestureWidth);
+ startX = rect.left;
+ endX = rect.right - 1;
}
break;
case RIGHT: {
startY = endY = rect.centerY();
- final int horizCenter = rect.centerX();
- final float halfGestureWidth = rect.width() * percent / 2.0f;
- startX = (int) (horizCenter + halfGestureWidth) - 1;
- endX = (int) (horizCenter - halfGestureWidth);
+ startX = rect.right - 1;
+ endX = rect.left;
}
break;
default:
@@ -844,10 +873,6 @@
mDevice.waitForIdle();
}
- float getDisplayDensity() {
- return mInstrumentation.getTargetContext().getResources().getDisplayMetrics().density;
- }
-
int getTouchSlop() {
return ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
@@ -969,4 +994,18 @@
public void produceNativeLeak() {
getTestInfo(TestProtocol.REQUEST_NATIVE_LEAK);
}
-}
\ No newline at end of file
+
+ public void produceViewLeak() {
+ getTestInfo(TestProtocol.REQUEST_VIEW_LEAK);
+ }
+
+ public ArrayList<ComponentName> getRecentTasks() {
+ ArrayList<ComponentName> tasks = new ArrayList<>();
+ ArrayList<String> components = getTestInfo(TestProtocol.REQUEST_RECENT_TASKS_LIST)
+ .getStringArrayList(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ for (String s : components) {
+ tasks.add(ComponentName.unflattenFromString(s));
+ }
+ return tasks;
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/TestHelpers.java b/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
index a089a52..e882171 100644
--- a/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
+++ b/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
@@ -77,13 +77,18 @@
return launchers.get(0).activityInfo;
}
- public static String getOverviewPackageName() {
+ public static ComponentName getOverviewComponentName() {
Resources res = Resources.getSystem();
int id = res.getIdentifier("config_recentsComponentName", "string", "android");
if (id != 0) {
- return ComponentName.unflattenFromString(res.getString(id)).getPackageName();
+ return ComponentName.unflattenFromString(res.getString(id));
}
- return "com.android.systemui";
+ return new ComponentName("com.android.systemui",
+ "com.android.systemui.recents.RecentsActivity");
+ }
+
+ public static String getOverviewPackageName() {
+ return getOverviewComponentName().getPackageName();
}
private static String truncateCrash(String text, int maxLines) {
@@ -101,11 +106,11 @@
return ret.toString();
}
- private static String checkCrash(Context context, String label) {
+ private static String checkCrash(Context context, String label, long startTime) {
DropBoxManager dropbox = (DropBoxManager) context.getSystemService(Context.DROPBOX_SERVICE);
Assert.assertNotNull("Unable access the DropBoxManager service", dropbox);
- long timestamp = System.currentTimeMillis() - 5 * 60000;
+ long timestamp = startTime;
DropBoxManager.Entry entry;
StringBuilder errorDetails = new StringBuilder();
while (null != (entry = dropbox.getNextEntry(label, timestamp))) {
@@ -123,7 +128,7 @@
return errorDetails.length() != 0 ? errorDetails.toString() : null;
}
- public static String getSystemHealthMessage(Context context) {
+ public static String getSystemHealthMessage(Context context, long startTime) {
try {
StringBuilder errors = new StringBuilder();
@@ -131,7 +136,6 @@
"system_app_anr",
"system_app_crash",
"system_app_native_crash",
- "system_app_wtf",
"system_server_anr",
"system_server_crash",
"system_server_native_crash",
@@ -139,7 +143,7 @@
};
for (String label : labels) {
- final String crash = checkCrash(context, label);
+ final String crash = checkCrash(context, label, startTime);
if (crash != null) errors.append(crash);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java
index 7d308af..5fcaa55 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widgets.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java
@@ -16,8 +16,6 @@
package com.android.launcher3.tapl;
-import static org.junit.Assert.fail;
-
import android.graphics.Point;
import android.graphics.Rect;
@@ -26,13 +24,12 @@
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiObject2;
-import com.android.launcher3.ResourceUtils;
+import java.util.Collection;
/**
* All widgets container.
*/
public final class Widgets extends LauncherInstrumentation.VisibleContainer {
- private static final Rect MARGINS = new Rect(100, 100, 100, 100);
private static final int FLING_STEPS = 10;
Widgets(LauncherInstrumentation launcher) {
@@ -48,7 +45,11 @@
"want to fling forward in widgets")) {
LauncherInstrumentation.log("Widgets.flingForward enter");
final UiObject2 widgetsContainer = verifyActiveContainer();
- mLauncher.scroll(widgetsContainer, Direction.DOWN, 1f, MARGINS, FLING_STEPS);
+ mLauncher.scroll(
+ widgetsContainer,
+ Direction.DOWN,
+ new Rect(0, 0, 0, mLauncher.getBottomGestureMargin(widgetsContainer) + 1),
+ FLING_STEPS);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("flung forward")) {
verifyActiveContainer();
}
@@ -64,7 +65,11 @@
"want to fling backwards in widgets")) {
LauncherInstrumentation.log("Widgets.flingBackward enter");
final UiObject2 widgetsContainer = verifyActiveContainer();
- mLauncher.scroll(widgetsContainer, Direction.UP, 1f, MARGINS, FLING_STEPS);
+ mLauncher.scroll(
+ widgetsContainer,
+ Direction.UP,
+ new Rect(0, 0, widgetsContainer.getVisibleBounds().width(), 0),
+ FLING_STEPS);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("flung back")) {
verifyActiveContainer();
}
@@ -78,32 +83,33 @@
}
public Widget getWidget(String labelText) {
- final int margin = ResourceUtils.getNavbarSize(
- ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mLauncher.getResources()) + 1;
final UiObject2 widgetsContainer = verifyActiveContainer();
- widgetsContainer.setGestureMargins(0, 0, 0, margin);
-
final Point displaySize = mLauncher.getRealDisplaySize();
+ final BySelector labelSelector = By.clazz("android.widget.TextView").text(labelText);
int i = 0;
- final BySelector selector = By.clazz("android.widget.TextView").text(labelText);
-
for (; ; ) {
- final UiObject2 label = mLauncher.tryWaitForLauncherObject(selector, 300);
- if (label != null) {
+ final Collection<UiObject2> cells = mLauncher.getObjectsInContainer(
+ widgetsContainer, "widgets_cell_list_container");
+ mLauncher.assertTrue("Widgets doesn't have 2 rows", cells.size() >= 2);
+ for (UiObject2 cell : cells) {
+ final UiObject2 label = cell.findObject(labelSelector);
+ if (label == null) continue;
+
final UiObject2 widget = label.getParent().getParent();
mLauncher.assertEquals(
"View is not WidgetCell",
"com.android.launcher3.widget.WidgetCell",
widget.getClassName());
- if (widget.getVisibleBounds().bottom <= displaySize.y - margin) {
+ if (widget.getVisibleBounds().bottom
+ <= displaySize.y - mLauncher.getBottomGestureSize()) {
return new Widget(mLauncher, widget);
}
}
- if (++i > 40) fail("Too many attempts");
- mLauncher.scroll(widgetsContainer, Direction.DOWN, 0.7f, MARGINS, 50);
+ mLauncher.assertTrue("Too many attempts", ++i <= 40);
+ mLauncher.scrollToLastVisibleRow(widgetsContainer, cells, 0);
}
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 510ea14..d1261e0 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -38,8 +38,6 @@
* Operations on the workspace screen.
*/
public final class Workspace extends Home {
- private static final float FLING_SPEED =
- LauncherInstrumentation.isAvd() ? 1500.0F : 3500.0F;
private static final int DRAG_DURACTION = 2000;
private static final int FLING_STEPS = 10;
private final UiObject2 mHotseat;
@@ -142,7 +140,7 @@
}
private boolean isWorkspaceScrollable(UiObject2 workspace) {
- return workspace.isScrollable();
+ return workspace.getChildCount() > 1;
}
@NonNull
@@ -182,8 +180,8 @@
*/
public void flingForward() {
final UiObject2 workspace = verifyActiveContainer();
- mLauncher.scroll(workspace, Direction.RIGHT, 1f,
- new Rect(0, 0, mLauncher.getEdgeSensitivityWidth(), 0),
+ mLauncher.scroll(workspace, Direction.RIGHT,
+ new Rect(0, 0, mLauncher.getEdgeSensitivityWidth() + 1, 0),
FLING_STEPS);
verifyActiveContainer();
}
@@ -194,8 +192,8 @@
*/
public void flingBackward() {
final UiObject2 workspace = verifyActiveContainer();
- mLauncher.scroll(workspace, Direction.LEFT, 1f,
- new Rect(mLauncher.getEdgeSensitivityWidth(), 0, 0, 0),
+ mLauncher.scroll(workspace, Direction.LEFT,
+ new Rect(mLauncher.getEdgeSensitivityWidth() + 1, 0, 0, 0),
FLING_STEPS);
verifyActiveContainer();
}