Merge "More diags for b/129434166" into ub-launcher3-master
diff --git a/go/quickstep/src/com/android/quickstep/TaskActionController.java b/go/quickstep/src/com/android/quickstep/TaskActionController.java
index 77b287b..71bee91 100644
--- a/go/quickstep/src/com/android/quickstep/TaskActionController.java
+++ b/go/quickstep/src/com/android/quickstep/TaskActionController.java
@@ -42,6 +42,9 @@
* @param viewHolder the task view holder to launch
*/
public void launchTask(TaskHolder viewHolder) {
+ if (viewHolder.getTask() == null) {
+ return;
+ }
TaskItemView itemView = (TaskItemView) (viewHolder.itemView);
View v = itemView.getThumbnailView();
int left = 0;
@@ -60,6 +63,9 @@
* @param viewHolder the task view holder to remove
*/
public void removeTask(TaskHolder viewHolder) {
+ if (viewHolder.getTask() == null) {
+ return;
+ }
int position = viewHolder.getAdapterPosition();
Task task = viewHolder.getTask();
ActivityManagerWrapper.getInstance().removeTask(task.key.id);
diff --git a/go/quickstep/src/com/android/quickstep/TaskAdapter.java b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
index c98eca6..674fcae 100644
--- a/go/quickstep/src/com/android/quickstep/TaskAdapter.java
+++ b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
@@ -28,6 +28,7 @@
import com.android.systemui.shared.recents.model.Task;
import java.util.List;
+import java.util.Objects;
/**
* Recycler view adapter that dynamically inflates and binds {@link TaskHolder} instances with the
@@ -40,6 +41,7 @@
private final TaskListLoader mLoader;
private final ArrayMap<Integer, TaskItemView> mTaskIdToViewMap = new ArrayMap<>();
private TaskActionController mTaskActionController;
+ private boolean mIsShowingLoadingUi;
public TaskAdapter(@NonNull TaskListLoader loader) {
mLoader = loader;
@@ -50,6 +52,18 @@
}
/**
+ * Sets all positions in the task adapter to loading views, binding new views if necessary.
+ * This changes the task adapter's view of the data, so the appropriate notify events should be
+ * called in addition to this method to reflect the changes.
+ *
+ * @param isShowingLoadingUi true to bind loading task views to all positions, false to return
+ * to the real data
+ */
+ public void setIsShowingLoadingUi(boolean isShowingLoadingUi) {
+ mIsShowingLoadingUi = isShowingLoadingUi;
+ }
+
+ /**
* Get task item view for a given task id if it's attached to the view.
*
* @param taskId task id to search for
@@ -70,6 +84,10 @@
@Override
public void onBindViewHolder(TaskHolder holder, int position) {
+ if (mIsShowingLoadingUi) {
+ holder.bindEmptyUi();
+ return;
+ }
List<Task> tasks = mLoader.getCurrentTaskList();
if (position >= tasks.size()) {
// Task list has updated.
@@ -79,13 +97,13 @@
holder.bindTask(task);
mLoader.loadTaskIconAndLabel(task, () -> {
// Ensure holder still has the same task.
- if (task.equals(holder.getTask())) {
+ if (Objects.equals(task, holder.getTask())) {
holder.getTaskItemView().setIcon(task.icon);
holder.getTaskItemView().setLabel(task.titleDescription);
}
});
mLoader.loadTaskThumbnail(task, () -> {
- if (task.equals(holder.getTask())) {
+ if (Objects.equals(task, holder.getTask())) {
holder.getTaskItemView().setThumbnail(task.thumbnail.thumbnail);
}
});
@@ -93,16 +111,27 @@
@Override
public void onViewAttachedToWindow(@NonNull TaskHolder holder) {
+ if (holder.getTask() == null) {
+ return;
+ }
mTaskIdToViewMap.put(holder.getTask().key.id, (TaskItemView) holder.itemView);
}
@Override
public void onViewDetachedFromWindow(@NonNull TaskHolder holder) {
+ if (holder.getTask() == null) {
+ return;
+ }
mTaskIdToViewMap.remove(holder.getTask().key.id);
}
@Override
public int getItemCount() {
- return Math.min(mLoader.getCurrentTaskList().size(), MAX_TASKS_TO_DISPLAY);
+ if (mIsShowingLoadingUi) {
+ // Show loading version of all items.
+ return MAX_TASKS_TO_DISPLAY;
+ } else {
+ return Math.min(mLoader.getCurrentTaskList().size(), MAX_TASKS_TO_DISPLAY);
+ }
}
}
diff --git a/go/quickstep/src/com/android/quickstep/TaskHolder.java b/go/quickstep/src/com/android/quickstep/TaskHolder.java
index 744afd7..98dc989 100644
--- a/go/quickstep/src/com/android/quickstep/TaskHolder.java
+++ b/go/quickstep/src/com/android/quickstep/TaskHolder.java
@@ -15,7 +15,7 @@
*/
package com.android.quickstep;
-import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import com.android.quickstep.views.TaskItemView;
@@ -50,11 +50,23 @@
}
/**
- * Gets the task currently bound to this view
+ * Bind a generic empty UI to the holder to make it clear that the item is loading/unbound and
+ * should not be expected to react to user input.
+ */
+ public void bindEmptyUi() {
+ mTask = null;
+ // TODO: Set the task view to a loading, empty UI.
+ // Temporarily using the one below for visual confirmation but should be swapped out to new
+ // UI later.
+ mTaskItemView.resetTaskItemView();
+ }
+
+ /**
+ * Gets the task currently bound to this view. May be null if task holder is in a loading state.
*
* @return the current task
*/
- public @NonNull Task getTask() {
+ public @Nullable Task getTask() {
return mTask;
}
}
diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
index 5bb4c5a..c742be3 100644
--- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
@@ -28,6 +28,10 @@
import android.util.FloatProperty;
import android.view.View;
import android.view.ViewDebug;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.LayoutAnimationController;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
@@ -69,6 +73,8 @@
}
};
private static final long CROSSFADE_DURATION = 300;
+ private static final long LAYOUT_ITEM_ANIMATE_IN_DURATION = 150;
+ private static final long LAYOUT_ITEM_ANIMATE_IN_DELAY_BETWEEN = 40;
private static final long ITEM_ANIMATE_OUT_DURATION = 150;
private static final long ITEM_ANIMATE_OUT_DELAY_BETWEEN = 40;
private static final float ITEM_ANIMATE_OUT_TRANSLATION_X_RATIO = .25f;
@@ -84,6 +90,7 @@
private final TaskListLoader mTaskLoader;
private final TaskAdapter mTaskAdapter;
private final TaskActionController mTaskActionController;
+ private final LayoutAnimationController mLayoutAnimation;
private RecentsToActivityHelper mActivityHelper;
private RecyclerView mTaskRecyclerView;
@@ -99,6 +106,7 @@
mTaskAdapter = new TaskAdapter(mTaskLoader);
mTaskActionController = new TaskActionController(mTaskLoader, mTaskAdapter);
mTaskAdapter.setActionController(mTaskActionController);
+ mLayoutAnimation = createLayoutAnimation();
}
@Override
@@ -112,6 +120,7 @@
ItemTouchHelper helper = new ItemTouchHelper(
new TaskSwipeCallback(mTaskActionController));
helper.attachToRecyclerView(mTaskRecyclerView);
+ mTaskRecyclerView.setLayoutAnimation(mLayoutAnimation);
mEmptyView = findViewById(R.id.recent_task_empty_view);
mContentView = findViewById(R.id.recent_task_content_view);
@@ -131,7 +140,6 @@
}
}
-
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
@@ -157,10 +165,13 @@
* becomes visible.
*/
public void onBeginTransitionToOverview() {
+ mTaskRecyclerView.scheduleLayoutAnimation();
+ mTaskAdapter.setIsShowingLoadingUi(true);
+ mTaskAdapter.notifyDataSetChanged();
// Load any task changes
mTaskLoader.loadTaskList(tasks -> {
- // TODO: Put up some loading UI while task content is loading. May have to do something
- // smarter when animating from app to overview.
+ mTaskAdapter.setIsShowingLoadingUi(false);
+ // TODO: Animate the loading UI out and the loaded data in.
mTaskAdapter.notifyDataSetChanged();
});
}
@@ -322,4 +333,18 @@
}
});
}
+
+ private static LayoutAnimationController createLayoutAnimation() {
+ AnimationSet anim = new AnimationSet(false /* shareInterpolator */);
+
+ Animation alphaAnim = new AlphaAnimation(0, 1);
+ alphaAnim.setDuration(LAYOUT_ITEM_ANIMATE_IN_DURATION);
+ anim.addAnimation(alphaAnim);
+
+ LayoutAnimationController layoutAnim = new LayoutAnimationController(anim);
+ layoutAnim.setDelay(
+ (float) LAYOUT_ITEM_ANIMATE_IN_DELAY_BETWEEN / LAYOUT_ITEM_ANIMATE_IN_DURATION);
+
+ return layoutAnim;
+ }
}
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index 895485d..6034791 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -32,7 +32,6 @@
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.TestHelpers;
-import com.android.systemui.shared.system.QuickStepContract;
import org.junit.Assert;
import org.junit.rules.TestRule;
@@ -78,9 +77,9 @@
@Override
public void evaluate() throws Throwable {
final Context context = getInstrumentation().getContext();
- final String prevOverlayPkg = QuickStepContract.isGesturalMode(context)
+ final String prevOverlayPkg = LauncherInstrumentation.isGesturalMode(context)
? NAV_BAR_MODE_GESTURAL_OVERLAY
- : QuickStepContract.isSwipeUpMode(context)
+ : LauncherInstrumentation.isSwipeUpMode(context)
? NAV_BAR_MODE_2BUTTON_OVERLAY
: NAV_BAR_MODE_3BUTTON_OVERLAY;
final LauncherInstrumentation.NavigationModel originalMode =
@@ -150,4 +149,4 @@
return base;
}
}
-}
\ No newline at end of file
+}
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 252cae1..ec63e35 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -44,7 +44,7 @@
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
<item name="folderDotColor">?android:attr/colorPrimary</item>
<item name="folderIconBorderColor">?android:attr/colorPrimary</item>
- <item name="loadingIconColor">#FFF</item>
+ <item name="loadingIconColor">#CCFFFFFF</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
@@ -82,7 +82,7 @@
<item name="folderDotColor">#FF464646</item>
<item name="folderIconBorderColor">#FF80868B</item>
<item name="isMainColorDark">true</item>
- <item name="loadingIconColor">#000</item>
+ <item name="loadingIconColor">#99FFFFFF</item>
</style>
<style name="LauncherTheme.Dark.DarkText" parent="@style/LauncherTheme.Dark">
diff --git a/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java b/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
index 5f2fb59..23745cb 100644
--- a/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.graphics;
+import static androidx.core.graphics.ColorUtils.compositeColors;
+
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -47,7 +49,8 @@
super(b, iconColor);
mProgressPath = progressPath;
- mPaint.setColor(Themes.getAttrColor(context, R.attr.loadingIconColor));
+ mPaint.setColor(compositeColors(
+ Themes.getAttrColor(context, R.attr.loadingIconColor), iconColor));
}
@Override
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 46b463b..089d672 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -97,5 +97,13 @@
<category android:name="android.intent.category.LAUNCHER_APP" />
</intent-filter>
</activity>
+ <activity
+ android:name="com.android.launcher3.testcomponent.BaseTestingActivity"
+ android:label="LauncherTestApp">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
index 904590c..9c6d102 100644
--- a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
+++ b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.graphics.Color;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
@@ -63,6 +64,7 @@
mView = new LinearLayout(this);
mView.setPadding(mMargin, mMargin, mMargin, mMargin);
mView.setOrientation(LinearLayout.VERTICAL);
+ mView.setBackgroundColor(Color.BLUE);
setContentView(mView);
registerReceiver(mCommandReceiver, new IntentFilter(mAction + SUFFIX_COMMAND));
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index c2e6749..e11e62e 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -330,9 +330,7 @@
public void testDragAppIcon() throws Throwable {
try {
TestProtocol.sDebugTracing = true;
- LauncherActivityInfo settingsApp = getSettingsApp();
-
- final String appName = settingsApp.getLabel().toString();
+ final String appName = "LauncherTestApp";
// 1. Open all apps and wait for load complete.
// 2. Drag icon to homescreen.
// 3. Verify that the icon works on homescreen.
@@ -341,7 +339,7 @@
getAppIcon(appName).
dragToWorkspace().
getWorkspaceAppIcon(appName).
- launch(settingsApp.getComponentName().getPackageName());
+ launch(getInstrumentation().getContext().getPackageName());
} finally {
TestProtocol.sDebugTracing = false;
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index c72f7d0..3a45e93 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -16,12 +16,16 @@
package com.android.launcher3.tapl;
+import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
+import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
+
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
@@ -172,11 +176,11 @@
// Workaround, use constructed context because both the instrumentation context and the
// app context are not constructed with resources that take overlays into account
final Context ctx = baseContext.createPackageContext("android", 0);
- if (QuickStepContract.isGesturalMode(ctx)) {
+ if (isGesturalMode(ctx)) {
return NavigationModel.ZERO_BUTTON;
- } else if (QuickStepContract.isSwipeUpMode(ctx)) {
+ } else if (isSwipeUpMode(ctx)) {
return NavigationModel.TWO_BUTTON;
- } else if (QuickStepContract.isLegacyMode(ctx)) {
+ } else if (isLegacyMode(ctx)) {
return NavigationModel.THREE_BUTTON;
} else {
fail("Can't detect navigation mode");
@@ -343,18 +347,33 @@
log(action = "0-button: already in workspace");
} else if (hasLauncherObject(OVERVIEW_RES_ID)) {
log(action = "0-button: from overview");
- mDevice.pressHome();
+ final UiObject2 navBar = waitForSystemUiObject("navigation_bar_frame");
+
+ swipe(
+ navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
+ navBar.getVisibleBounds().centerX(), 0,
+ NORMAL_STATE_ORDINAL, ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME);
} else if (hasLauncherObject(WIDGETS_RES_ID)) {
log(action = "0-button: from widgets");
mDevice.pressHome();
} else if (hasLauncherObject(APPS_RES_ID)) {
log(action = "0-button: from all apps");
- mDevice.pressHome();
+ final UiObject2 navBar = waitForSystemUiObject("navigation_bar_frame");
+
+ swipe(
+ navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
+ navBar.getVisibleBounds().centerX(), 0,
+ NORMAL_STATE_ORDINAL, ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME);
} else {
log(action = "0-button: from another app");
assertTrue("Launcher is visible, don't know how to go home",
!mDevice.hasObject(By.pkg(getLauncherPackageName())));
- mDevice.pressHome();
+ final UiObject2 navBar = waitForSystemUiObject("navigation_bar_frame");
+
+ swipe(
+ navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
+ navBar.getVisibleBounds().centerX(), 0,
+ BACKGROUND_APP_STATE_ORDINAL, ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME);
}
} else {
log(action = "clicking home button");
@@ -607,6 +626,46 @@
}
}
+ public static boolean isGesturalMode(Context context) {
+ return QuickStepContract.isGesturalMode(getCurrentInteractionMode(context));
+ }
+
+ public static boolean isSwipeUpMode(Context context) {
+ return QuickStepContract.isSwipeUpMode(getCurrentInteractionMode(context));
+ }
+
+ public static boolean isLegacyMode(Context context) {
+ return QuickStepContract.isLegacyMode(getCurrentInteractionMode(context));
+ }
+
+ private static int getCurrentInteractionMode(Context context) {
+ return getSystemIntegerRes(context, "config_navBarInteractionMode");
+ }
+
+ private static int getSystemIntegerRes(Context context, String resName) {
+ Resources res = context.getResources();
+ int resId = res.getIdentifier(resName, "integer", "android");
+
+ if (resId != 0) {
+ return res.getInteger(resId);
+ } else {
+ Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
+ return -1;
+ }
+ }
+
+ private static int getSystemDimensionResId(Context context, String resName) {
+ Resources res = context.getResources();
+ int resId = res.getIdentifier(resName, "dimen", "android");
+
+ if (resId != 0) {
+ return resId;
+ } else {
+ Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
+ return -1;
+ }
+ }
+
static void sleep(int duration) {
try {
Thread.sleep(duration);
@@ -616,8 +675,10 @@
int getEdgeSensitivityWidth() {
try {
- return QuickStepContract.getEdgeSensitivityWidth(
- mInstrumentation.getTargetContext().createPackageContext("android", 0)) + 1;
+ final Context context = mInstrumentation.getTargetContext().createPackageContext(
+ "android", 0);
+ return context.getResources().getDimensionPixelSize(
+ getSystemDimensionResId(context, "config_backGestureInset")) + 1;
} catch (PackageManager.NameNotFoundException e) {
fail("Can't get edge sensitivity: " + e);
return 0;