Merge "Allow visual stashing when going to overview in tests" into sc-v2-dev
diff --git a/build.gradle b/build.gradle
index a7eef13..617738a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,7 +2,6 @@
repositories {
mavenCentral()
google()
- jcenter()
}
dependencies {
classpath GRADLE_CLASS_PATH
diff --git a/go/quickstep/res/layout/overview_actions_container.xml b/go/quickstep/res/layout/overview_actions_container.xml
index cc65cbf..710e2e0 100644
--- a/go/quickstep/res/layout/overview_actions_container.xml
+++ b/go/quickstep/res/layout/overview_actions_container.xml
@@ -105,6 +105,23 @@
<!-- Unused. Included only for compatibility with parent class. -->
<Button
+ android:id="@+id/action_split"
+ style="@style/GoOverviewActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawableStart="@drawable/ic_split_screen"
+ android:text="@string/action_split"
+ android:theme="@style/ThemeControlHighlightWorkspaceColor"
+ android:visibility="gone" />
+
+ <Space
+ android:id="@+id/action_split_space"
+ android:layout_width="0dp"
+ android:layout_height="1dp"
+ android:layout_weight="1"
+ android:visibility="gone" />
+
+ <Button
android:id="@+id/action_share"
style="@style/GoOverviewActionButton"
android:layout_width="wrap_content"
diff --git a/gradle.properties b/gradle.properties
index 7f4c609..d5c1d77 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,6 +1,7 @@
# Until all the dependencies move to android X
android.useAndroidX = true
android.enableJetifier = true
+org.gradle.parallel=true
ANDROID_X_VERSION=1+
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index fcbea77..c80818a 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -24,6 +24,7 @@
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
@@ -35,6 +36,7 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.ServiceConnection;
+import android.graphics.Insets;
import android.hardware.SensorManager;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Bundle;
@@ -43,6 +45,7 @@
import android.os.IBinder;
import android.util.Log;
import android.view.View;
+import android.view.WindowInsets;
import android.window.SplashScreen;
import androidx.annotation.Nullable;
@@ -639,4 +642,17 @@
mDepthController.dump(prefix, writer);
}
}
+
+ @Override
+ public void updateWindowInsets(WindowInsets.Builder updatedInsetsBuilder,
+ WindowInsets oldInsets) {
+ // Override the tappable insets to be 0 on the bottom for gesture nav (otherwise taskbar
+ // would count towards it). This is used for the bottom protection in All Apps for example.
+ if (SysUINavigationMode.getMode(this) == NO_BUTTON) {
+ Insets oldTappableInsets = oldInsets.getInsets(WindowInsets.Type.tappableElement());
+ Insets newTappableInsets = Insets.of(oldTappableInsets.left, oldTappableInsets.top,
+ oldTappableInsets.right, 0);
+ updatedInsetsBuilder.setInsets(WindowInsets.Type.tappableElement(), newTappableInsets);
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 89cc1f6..b8d00bd 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -28,17 +28,24 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.Utilities.mapBoundToRange;
import static com.android.launcher3.Utilities.postAsyncCallback;
+import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
+import static com.android.launcher3.anim.Interpolators.EXAGGERATED_EASE;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_BACK_SWIPE_HOME_ANIMATION;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SCRIM_FOR_APP_LAUNCH;
import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS;
+import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
+import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
+import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
@@ -50,20 +57,24 @@
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Point;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.CancellationSignal;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.util.Pair;
import android.util.Size;
import android.view.SurfaceControl;
@@ -86,8 +97,11 @@
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.taskbar.LauncherTaskbarUIController;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.ActivityOptionsWrapper;
+import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
+import com.android.launcher3.util.ObjectWrapper;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.FloatingIconView;
@@ -96,8 +110,11 @@
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskViewUtils;
+import com.android.quickstep.util.AppCloseConfig;
import com.android.quickstep.util.MultiValueUpdateListener;
+import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.RemoteAnimationProvider;
+import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.WorkspaceRevealAnim;
import com.android.quickstep.views.FloatingWidgetView;
@@ -1179,10 +1196,183 @@
}
/**
- * Animator that controls the transformations of the windows the targets that are closing.
+ * Returns view on the workspace that corresponds to the closing app in the list of app targets
*/
- private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] appTargets,
- RemoteAnimationTargetCompat[] wallpaperTargets) {
+ private @Nullable View findWorkspaceView(RemoteAnimationTargetCompat[] appTargets) {
+ for (RemoteAnimationTargetCompat appTarget : appTargets) {
+ if (appTarget.mode == MODE_CLOSING) {
+ View workspaceView = findWorkspaceView(appTarget);
+ if (workspaceView != null) {
+ return workspaceView;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns view on the workspace that corresponds to the {@param runningTaskTarget}.
+ */
+ private @Nullable View findWorkspaceView(RemoteAnimationTargetCompat runningTaskTarget) {
+ if (runningTaskTarget == null || runningTaskTarget.taskInfo == null) {
+ return null;
+ }
+
+ final ComponentName[] taskInfoActivities = new ComponentName[] {
+ runningTaskTarget.taskInfo.baseActivity,
+ runningTaskTarget.taskInfo.origActivity,
+ runningTaskTarget.taskInfo.realActivity,
+ runningTaskTarget.taskInfo.topActivity};
+
+ String packageName = null;
+ for (ComponentName component : taskInfoActivities) {
+ if (component != null && component.getPackageName() != null) {
+ packageName = component.getPackageName();
+ break;
+ }
+ }
+
+ if (packageName == null) {
+ return null;
+ }
+
+ // Find the associated item info for the launch cookie (if available), note that predicted
+ // apps actually have an id of -1, so use another default id here
+ final ArrayList<IBinder> launchCookies = runningTaskTarget.taskInfo.launchCookies == null
+ ? new ArrayList<>()
+ : runningTaskTarget.taskInfo.launchCookies;
+
+ int launchCookieItemId = NO_MATCHING_ID;
+ for (IBinder cookie : launchCookies) {
+ Integer itemId = ObjectWrapper.unwrap(cookie);
+ if (itemId != null) {
+ launchCookieItemId = itemId;
+ break;
+ }
+ }
+
+ return mLauncher.getWorkspace().getFirstMatchForAppClose(launchCookieItemId,
+ packageName, UserHandle.of(runningTaskTarget.taskInfo.userId));
+ }
+
+ private @NonNull RectF getDefaultWindowTargetRect() {
+ RecentsView recentsView = mLauncher.getOverviewPanel();
+ PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
+ DeviceProfile dp = mLauncher.getDeviceProfile();
+ final int halfIconSize = dp.iconSizePx / 2;
+ float primaryDimension = orientationHandler
+ .getPrimaryValue(dp.availableWidthPx, dp.availableHeightPx);
+ float secondaryDimension = orientationHandler
+ .getSecondaryValue(dp.availableWidthPx, dp.availableHeightPx);
+ final float targetX = primaryDimension / 2f;
+ final float targetY = secondaryDimension - dp.hotseatBarSizePx;
+ return new RectF(targetX - halfIconSize, targetY - halfIconSize,
+ targetX + halfIconSize, targetY + halfIconSize);
+ }
+
+ /**
+ * Closing animator that animates the window into its final location on the workspace.
+ */
+ private void getClosingWindowAnimators(AnimatorSet animation,
+ RemoteAnimationTargetCompat[] targets, View workspaceView) {
+ FloatingIconView floatingIconView = null;
+ FloatingWidgetView floatingWidget = null;
+ RectF targetRect = new RectF();
+
+ RemoteAnimationTargetCompat runningTaskTarget = null;
+ boolean isTransluscent = false;
+ for (RemoteAnimationTargetCompat target : targets) {
+ if (target.mode == MODE_CLOSING) {
+ runningTaskTarget = target;
+ isTransluscent = runningTaskTarget.isTranslucent;
+ break;
+ }
+ }
+
+ // Get floating view and target rect.
+ if (workspaceView instanceof LauncherAppWidgetHostView) {
+ Size windowSize = new Size(mDeviceProfile.availableWidthPx,
+ mDeviceProfile.availableHeightPx);
+ int fallbackBackgroundColor =
+ FloatingWidgetView.getDefaultBackgroundColor(mLauncher, runningTaskTarget);
+ floatingWidget = FloatingWidgetView.getFloatingWidgetView(mLauncher,
+ (LauncherAppWidgetHostView) workspaceView, targetRect, windowSize,
+ mDeviceProfile.isMultiWindowMode ? 0 : getWindowCornerRadius(mLauncher),
+ isTransluscent, fallbackBackgroundColor);
+ } else if (workspaceView != null) {
+ floatingIconView = getFloatingIconView(mLauncher, workspaceView,
+ true /* hideOriginal */, targetRect, false /* isOpening */);
+ } else {
+ targetRect.set(getDefaultWindowTargetRect());
+ }
+
+ final RectF startRect = new RectF(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx);
+ RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mLauncher);
+
+ // Hook up floating views to the closing window animators.
+ if (floatingIconView != null) {
+ anim.addAnimatorListener(floatingIconView);
+ floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged);
+ floatingIconView.setFastFinishRunnable(anim::end);
+ FloatingIconView finalFloatingIconView = floatingIconView;
+
+ // We want the window alpha to be 0 once this threshold is met, so that the
+ // FolderIconView can be seen morphing into the icon shape.
+ final float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION;
+
+ RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect) {
+ @Override
+ public void onUpdate(@Nullable AppCloseConfig values, RectF currentRectF,
+ float progress) {
+ finalFloatingIconView.update(1f, 255 /* fgAlpha */, currentRectF, progress,
+ windowAlphaThreshold, getCornerRadius(progress), false);
+
+ super.onUpdate(values, currentRectF, progress);
+ }
+ };
+ anim.addOnUpdateListener(runner);
+ } else if (floatingWidget != null) {
+ anim.addAnimatorListener(floatingWidget);
+ floatingWidget.setOnTargetChangeListener(anim::onTargetPositionChanged);
+ floatingWidget.setFastFinishRunnable(anim::end);
+
+ final float floatingWidgetAlpha = isTransluscent ? 0 : 1;
+ FloatingWidgetView finalFloatingWidget = floatingWidget;
+ RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect) {
+ @Override
+ public void onUpdate(@Nullable AppCloseConfig values, RectF currentRectF,
+ float progress) {
+ final float fallbackBackgroundAlpha =
+ 1 - mapBoundToRange(progress, 0.8f, 1, 0, 1, EXAGGERATED_EASE);
+ final float foregroundAlpha =
+ mapBoundToRange(progress, 0.5f, 1, 0, 1, EXAGGERATED_EASE);
+ finalFloatingWidget.update(currentRectF, floatingWidgetAlpha, foregroundAlpha,
+ fallbackBackgroundAlpha, 1 - progress);
+
+ super.onUpdate(values, currentRectF, progress);
+ }
+ };
+ anim.addOnUpdateListener(runner);
+ }
+
+ // Use a fixed velocity to start the animation.
+ float velocityPxPerS = DynamicResource.provider(mLauncher)
+ .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
+ PointF velocity = new PointF(0, -velocityPxPerS);
+ animation.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
+ true /* animateOverviewScrim */, workspaceView).getAnimators());
+ animation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ anim.start(mLauncher, velocity);
+ }
+ });
+ }
+
+ /**
+ * Closing window animator that moves the window down and offscreen.
+ */
+ private Animator getFallbackClosingWindowAnimators(RemoteAnimationTargetCompat[] appTargets) {
final int rotationChange = getRotationChange(appTargets);
SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(mDragLayer);
Matrix matrix = new Matrix();
@@ -1321,7 +1511,7 @@
LauncherAnimationRunner.AnimationResult result) {
if (mLauncher.isDestroyed()) {
AnimatorSet anim = new AnimatorSet();
- anim.play(getClosingWindowAnimators(appTargets, wallpaperTargets));
+ anim.play(getFallbackClosingWindowAnimators(appTargets));
result.setAnimation(anim, mLauncher.getApplicationContext());
return;
}
@@ -1348,9 +1538,23 @@
if (anim == null) {
anim = new AnimatorSet();
- anim.play(mFromUnlock
- ? getUnlockWindowAnimator(appTargets, wallpaperTargets)
- : getClosingWindowAnimators(appTargets, wallpaperTargets));
+
+ boolean playFallBackAnimation = mLauncher.isInState(LauncherState.ALL_APPS)
+ && (launcherIsATargetWithMode(appTargets, MODE_OPENING)
+ || mLauncher.isForceInvisible());
+
+ View workspaceView = findWorkspaceView(appTargets);
+ boolean playWorkspaceReveal = true;
+ if (mFromUnlock) {
+ anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
+ } else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
+ && !playFallBackAnimation) {
+ getClosingWindowAnimators(anim, appTargets, workspaceView);
+ // We play StaggeredWorkspaceAnim as a part of the closing window animation.
+ playWorkspaceReveal = false;
+ } else {
+ anim.play(getFallbackClosingWindowAnimators(appTargets));
+ }
// Normally, we run the launcher content animation when we are transitioning
// home, but if home is already visible, then we don't want to animate the
@@ -1378,7 +1582,9 @@
}
});
} else {
- anim.play(new WorkspaceRevealAnim(mLauncher, false).getAnimators());
+ if (playWorkspaceReveal) {
+ anim.play(new WorkspaceRevealAnim(mLauncher, false).getAnimators());
+ }
}
}
}
@@ -1527,4 +1733,73 @@
mTransitionManager.mTaskStartParams.put(taskId, Pair.create(supportedType, color));
}
}
+
+ /**
+ * RectFSpringAnim update listener to be used for app to home animation.
+ */
+ private class SpringAnimRunner implements RectFSpringAnim.OnUpdateListener {
+ private final RemoteAnimationTargetCompat[] mAppTargets;
+ private final Matrix mMatrix = new Matrix();
+ private final Point mTmpPos = new Point();
+ private final Rect mCurrentRect = new Rect();
+ private final float mStartRadius;
+ private final float mEndRadius;
+ private final SurfaceTransactionApplier mSurfaceApplier;
+
+ SpringAnimRunner(RemoteAnimationTargetCompat[] appTargets, RectF targetRect) {
+ mAppTargets = appTargets;
+ mStartRadius = QuickStepContract.getWindowCornerRadius(mLauncher);
+ mEndRadius = Math.max(1, targetRect.width()) / 2f;
+ mSurfaceApplier = new SurfaceTransactionApplier(mDragLayer);
+ }
+
+ public float getCornerRadius(float progress) {
+ return Utilities.mapRange(progress, mStartRadius, mEndRadius);
+ }
+
+ @Override
+ public void onUpdate(@Nullable AppCloseConfig values, RectF currentRectF, float progress) {
+ SurfaceParams[] params = new SurfaceParams[mAppTargets.length];
+ for (int i = mAppTargets.length - 1; i >= 0; i--) {
+ RemoteAnimationTargetCompat target = mAppTargets[i];
+ SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
+
+ if (target.localBounds != null) {
+ mTmpPos.set(target.localBounds.left, target.localBounds.top);
+ } else {
+ mTmpPos.set(target.position.x, target.position.y);
+ }
+
+ if (target.mode == MODE_CLOSING) {
+ float alpha = getWindowAlpha(progress);
+ currentRectF.round(mCurrentRect);
+
+ builder.withMatrix(mMatrix)
+ .withWindowCrop(mCurrentRect)
+ .withAlpha(alpha)
+ .withCornerRadius(getCornerRadius(progress));
+ } else if (target.mode == MODE_OPENING) {
+ mMatrix.setTranslate(mTmpPos.x, mTmpPos.y);
+ builder.withMatrix(mMatrix)
+ .withAlpha(1f);
+ }
+ params[i] = builder.build();
+ }
+ mSurfaceApplier.scheduleApply(params);
+ }
+
+ protected float getWindowAlpha(float progress) {
+ // Alpha interpolates between [1, 0] between progress values [start, end]
+ final float start = 0f;
+ final float end = 0.85f;
+
+ if (progress <= start) {
+ return 1f;
+ }
+ if (progress >= end) {
+ return 0f;
+ }
+ return Utilities.mapToRange(progress, start, end, 1, 0, ACCEL_1_5);
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 978fb57..e3e7b33 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -51,6 +51,7 @@
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -63,11 +64,16 @@
public class TaskOverlayFactory implements ResourceBasedOverride {
public static List<SystemShortcut> getEnabledShortcuts(TaskView taskView,
- DeviceProfile deviceProfile) {
+ DeviceProfile deviceProfile, TaskIdAttributeContainer taskContainer) {
final ArrayList<SystemShortcut> shortcuts = new ArrayList<>();
final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext());
+ boolean hasMultipleTasks = taskView.getTaskIds()[1] != -1;
for (TaskShortcutFactory menuOption : MENU_OPTIONS) {
- SystemShortcut shortcut = menuOption.getShortcut(activity, taskView);
+ if (hasMultipleTasks && !menuOption.showForSplitscreen()) {
+ continue;
+ }
+
+ SystemShortcut shortcut = menuOption.getShortcut(activity, taskContainer);
if (shortcut == null) {
continue;
}
@@ -87,7 +93,7 @@
if (!canLauncherRotate && isInLandscape) {
// Add screenshot action to task menu.
SystemShortcut screenshotShortcut = TaskShortcutFactory.SCREENSHOT
- .getShortcut(activity, taskView);
+ .getShortcut(activity, taskContainer);
if (screenshotShortcut != null) {
shortcuts.add(screenshotShortcut);
}
@@ -95,7 +101,7 @@
// Add modal action only if display orientation is the same as the device orientation.
if (orientedState.getDisplayRotation() == ROTATION_0) {
SystemShortcut modalShortcut = TaskShortcutFactory.MODAL
- .getShortcut(activity, taskView);
+ .getShortcut(activity, taskContainer);
if (modalShortcut != null) {
shortcuts.add(modalShortcut);
}
@@ -105,7 +111,7 @@
}
- public static void addSplitOptions(List<SystemShortcut> outShortcuts,
+ private static void addSplitOptions(List<SystemShortcut> outShortcuts,
BaseDraggingActivity activity, TaskView taskView, DeviceProfile deviceProfile) {
int[] taskViewTaskIds = taskView.getTaskIds();
boolean alreadyHasMultipleTasks = taskViewTaskIds[0] != -1 &&
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index 559125e..dbb5f10 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -45,6 +45,7 @@
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
@@ -61,9 +62,25 @@
* Represents a system shortcut that can be shown for a recent task.
*/
public interface TaskShortcutFactory {
- SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView view);
+ SystemShortcut getShortcut(BaseDraggingActivity activity,
+ TaskIdAttributeContainer taskContainer);
- TaskShortcutFactory APP_INFO = (activity, view) -> new AppInfo(activity, view.getItemInfo());
+ default boolean showForSplitscreen() {
+ return false;
+ }
+
+ TaskShortcutFactory APP_INFO = new TaskShortcutFactory() {
+ @Override
+ public SystemShortcut getShortcut(BaseDraggingActivity activity,
+ TaskIdAttributeContainer taskContainer) {
+ return new AppInfo(activity, taskContainer.getItemInfo());
+ }
+
+ @Override
+ public boolean showForSplitscreen() {
+ return true;
+ }
+ };
abstract class MultiWindowFactory implements TaskShortcutFactory {
@@ -82,15 +99,16 @@
protected abstract boolean onActivityStarted(BaseDraggingActivity activity);
@Override
- public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView taskView) {
- final Task task = taskView.getTask();
+ public SystemShortcut getShortcut(BaseDraggingActivity activity,
+ TaskIdAttributeContainer taskContainer) {
+ final Task task = taskContainer.getTask();
if (!task.isDockable) {
return null;
}
if (!isAvailable(activity, task.key.displayId)) {
return null;
}
- return new MultiWindowSystemShortcut(mIconRes, mTextRes, activity, taskView, this,
+ return new MultiWindowSystemShortcut(mIconRes, mTextRes, activity, taskContainer, this,
mLauncherEvent);
}
}
@@ -123,13 +141,14 @@
private final LauncherEvent mLauncherEvent;
public MultiWindowSystemShortcut(int iconRes, int textRes, BaseDraggingActivity activity,
- TaskView taskView, MultiWindowFactory factory, LauncherEvent launcherEvent) {
- super(iconRes, textRes, activity, taskView.getItemInfo());
+ TaskIdAttributeContainer taskContainer, MultiWindowFactory factory,
+ LauncherEvent launcherEvent) {
+ super(iconRes, textRes, activity, taskContainer.getItemInfo());
mLauncherEvent = launcherEvent;
mHandler = new Handler(Looper.getMainLooper());
- mTaskView = taskView;
+ mTaskView = taskContainer.getTaskView();
mRecentsView = activity.getOverviewPanel();
- mThumbnailView = taskView.getThumbnail();
+ mThumbnailView = taskContainer.getThumbnailView();
mFactory = factory;
}
@@ -233,11 +252,13 @@
}
@Override
- public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView taskView) {
- SystemShortcut shortcut = super.getShortcut(activity, taskView);
+ public SystemShortcut getShortcut(BaseDraggingActivity activity,
+ TaskIdAttributeContainer taskContainer) {
+ SystemShortcut shortcut = super.getShortcut(activity, taskContainer);
if (shortcut != null && FeatureFlags.ENABLE_SPLIT_SELECT.get()) {
// Disable if there's only one recent app for split screen
- shortcut.setEnabled(taskView.getRecentsView().getTaskViewCount() > 1);
+ shortcut.setEnabled(taskContainer.getTaskView().
+ getRecentsView().getTaskViewCount() > 1);
}
return shortcut;
}
@@ -284,7 +305,7 @@
}
};
- TaskShortcutFactory PIN = (activity, tv) -> {
+ TaskShortcutFactory PIN = (activity, taskContainer) -> {
if (!SystemUiProxy.INSTANCE.get(activity).isActive()) {
return null;
}
@@ -295,7 +316,7 @@
// We shouldn't be able to pin while an app is locked.
return null;
}
- return new PinSystemShortcut(activity, tv);
+ return new PinSystemShortcut(activity, taskContainer);
};
class PinSystemShortcut extends SystemShortcut {
@@ -304,9 +325,11 @@
private final TaskView mTaskView;
- public PinSystemShortcut(BaseDraggingActivity target, TaskView tv) {
- super(R.drawable.ic_pin, R.string.recent_task_option_pin, target, tv.getItemInfo());
- mTaskView = tv;
+ public PinSystemShortcut(BaseDraggingActivity target,
+ TaskIdAttributeContainer taskContainer) {
+ super(R.drawable.ic_pin, R.string.recent_task_option_pin, target,
+ taskContainer.getItemInfo());
+ mTaskView = taskContainer.getTaskView();
}
@Override
@@ -320,20 +343,22 @@
}
}
- TaskShortcutFactory INSTALL = (activity, view) ->
+ TaskShortcutFactory INSTALL = (activity, taskContainer) ->
InstantAppResolver.newInstance(activity).isInstantApp(activity,
- view.getTask().getTopComponent().getPackageName())
- ? new SystemShortcut.Install(activity, view.getItemInfo()) : null;
+ taskContainer.getTask().getTopComponent().getPackageName())
+ ? new SystemShortcut.Install(activity, taskContainer.getItemInfo()) : null;
- TaskShortcutFactory WELLBEING = (activity, view) ->
- WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, view.getItemInfo());
+ TaskShortcutFactory WELLBEING = (activity, taskContainer) ->
+ WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, taskContainer.getItemInfo());
- TaskShortcutFactory SCREENSHOT = (activity, tv) -> tv.getThumbnail().getTaskOverlay()
- .getScreenshotShortcut(activity, tv.getItemInfo());
+ TaskShortcutFactory SCREENSHOT = (activity, taskContainer) ->
+ taskContainer.getThumbnailView().getTaskOverlay()
+ .getScreenshotShortcut(activity, taskContainer.getItemInfo());
- TaskShortcutFactory MODAL = (activity, tv) -> {
+ TaskShortcutFactory MODAL = (activity, taskContainer) -> {
if (ENABLE_OVERVIEW_SELECTIONS.get()) {
- return tv.getThumbnail().getTaskOverlay().getModalStateSystemShortcut(tv.getItemInfo());
+ return taskContainer.getThumbnailView()
+ .getTaskOverlay().getModalStateSystemShortcut(taskContainer.getItemInfo());
}
return null;
};
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index b1b4b54..72d3731 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -1,5 +1,8 @@
package com.android.quickstep.views;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
+
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -11,7 +14,6 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.util.RunnableList;
-import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.launcher3.util.TransformingTouchDelegate;
import com.android.quickstep.RecentsModel;
@@ -72,7 +74,9 @@
super.bind(primary, orientedState);
mSecondaryTask = secondary;
mTaskIdContainer[1] = secondary.key.id;
- mTaskIdAttributeContainer[1] = new TaskIdAttributeContainer(secondary, mSnapshotView2);
+ mTaskIdAttributeContainer[1] = new TaskIdAttributeContainer(secondary, mSnapshotView2,
+ STAGE_POSITION_BOTTOM_OR_RIGHT);
+ mTaskIdAttributeContainer[0].setStagePosition(STAGE_POSITION_TOP_OR_LEFT);
mSnapshotView2.bind(secondary);
mSplitBoundsConfig = splitBoundsConfig;
}
@@ -112,6 +116,10 @@
}
}
+ protected boolean showTaskMenuWithContainer(IconView iconView) {
+ return TaskMenuView.showForTask(mTaskIdAttributeContainer[iconView == mIconView ? 0 : 1]);
+ }
+
public void updateSplitBoundsConfig(StagedSplitBounds stagedSplitBounds) {
mSplitBoundsConfig = stagedSplitBounds;
invalidate();
@@ -143,14 +151,14 @@
@Override
public RunnableList launchTaskAnimated() {
getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
- SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT, null /*callback*/);
+ STAGE_POSITION_TOP_OR_LEFT, null /*callback*/);
return null;
}
@Override
public void launchTask(@NonNull Consumer<Boolean> callback, boolean freezeTaskList) {
getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
- SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT, callback);
+ STAGE_POSITION_TOP_OR_LEFT, callback);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index bfc7eea..5ddbf87 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,6 +16,8 @@
package com.android.quickstep.views;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
import android.animation.Animator;
@@ -39,6 +41,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
@@ -49,6 +52,7 @@
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.TaskCornerRadius;
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
/**
* Contains options for a recent task when long-pressing its icon.
@@ -65,6 +69,7 @@
private TextView mTaskName;
private AnimatorSet mOpenCloseAnimator;
private TaskView mTaskView;
+ private TaskIdAttributeContainer mTaskContainer;
private LinearLayout mOptionLayout;
public TaskMenuView(Context context, AttributeSet attrs) {
@@ -129,7 +134,8 @@
// Inset due to margin
PointF additionalInset = pagedOrientationHandler
.getAdditionalInsetForTaskMenu(mTaskInsetMargin);
- int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
+ DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+ int taskTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
float adjustedY = y + taskTopMargin - additionalInset.y;
float adjustedX = x - additionalInset.x;
@@ -137,7 +143,7 @@
// NOTE: Changing the pivots means the rotated view gets rotated about the new pivots set,
// which would render the X and Y position set here incorrect
setPivotX(0);
- if (mActivity.getDeviceProfile().overviewShowAsGrid) {
+ if (deviceProfile.overviewShowAsGrid) {
// In tablet, set pivotY to original position without mThumbnailTopMargin adjustment.
setPivotY(-taskTopMargin);
} else {
@@ -145,9 +151,26 @@
}
setRotation(pagedOrientationHandler.getDegreesRotated());
setX(pagedOrientationHandler.getTaskMenuX(adjustedX,
- mTaskView.getThumbnail(), overscrollShift));
+ mTaskContainer.getThumbnailView(), overscrollShift));
setY(pagedOrientationHandler.getTaskMenuY(
- adjustedY, mTaskView.getThumbnail(), overscrollShift));
+ adjustedY, mTaskContainer.getThumbnailView(), overscrollShift));
+
+ // TODO(b/193432925) temporary menu placement for split screen task menus
+ TaskIdAttributeContainer[] taskIdAttributeContainers =
+ mTaskView.getTaskIdAttributeContainers();
+ if (taskIdAttributeContainers[0].getStagePosition() != STAGE_POSITION_UNDEFINED) {
+ if (mTaskContainer.getStagePosition() != STAGE_POSITION_BOTTOM_OR_RIGHT) {
+ return;
+ }
+ Rect r = new Rect();
+ mTaskContainer.getThumbnailView().getBoundsOnScreen(r);
+ if (deviceProfile.isLandscape) {
+ setX(r.left);
+ } else {
+ setY(r.top);
+
+ }
+ }
}
public void onRotationChanged() {
@@ -162,19 +185,21 @@
}
}
- public static boolean showForTask(TaskView taskView) {
- BaseDraggingActivity activity = BaseDraggingActivity.fromContext(taskView.getContext());
+ public static boolean showForTask(TaskIdAttributeContainer taskContainer) {
+ BaseDraggingActivity activity = BaseDraggingActivity.fromContext(
+ taskContainer.getTaskView().getContext());
final TaskMenuView taskMenuView = (TaskMenuView) activity.getLayoutInflater().inflate(
R.layout.task_menu, activity.getDragLayer(), false);
- return taskMenuView.populateAndShowForTask(taskView);
+ return taskMenuView.populateAndShowForTask(taskContainer);
}
- private boolean populateAndShowForTask(TaskView taskView) {
+ private boolean populateAndShowForTask(TaskIdAttributeContainer taskContainer) {
if (isAttachedToWindow()) {
return false;
}
mActivity.getDragLayer().addView(this);
- mTaskView = taskView;
+ mTaskView = taskContainer.getTaskView();
+ mTaskContainer = taskContainer;
if (!populateAndLayoutMenu()) {
return false;
}
@@ -192,20 +217,21 @@
/** @return true if successfully able to populate task view menu, false otherwise */
private boolean populateAndLayoutMenu() {
- if (mTaskView.getTask().icon == null) {
+ if (mTaskContainer.getTask().icon == null) {
// Icon may not be loaded
return false;
}
- addMenuOptions(mTaskView);
- orientAroundTaskView(mTaskView);
+ addMenuOptions(mTaskContainer);
+ orientAroundTaskView(mTaskContainer);
return true;
}
- private void addMenuOptions(TaskView taskView) {
- mTaskName.setText(TaskUtils.getTitle(getContext(), taskView.getTask()));
+ private void addMenuOptions(TaskIdAttributeContainer taskContainer) {
+ mTaskName.setText(TaskUtils.getTitle(getContext(), taskContainer.getTask()));
mTaskName.setOnClickListener(v -> close(true));
- TaskOverlayFactory.getEnabledShortcuts(taskView, mActivity.getDeviceProfile())
+ TaskOverlayFactory.getEnabledShortcuts(mTaskView, mActivity.getDeviceProfile(),
+ taskContainer)
.forEach(this::addMenuOption);
}
@@ -223,23 +249,25 @@
mOptionLayout.addView(menuOptionView);
}
- private void orientAroundTaskView(TaskView taskView) {
- PagedOrientationHandler orientationHandler = taskView.getPagedOrientationHandler();
+ private void orientAroundTaskView(TaskIdAttributeContainer taskContainer) {
+ RecentsView recentsView = mActivity.getOverviewPanel();
+ PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
orientationHandler.setTaskMenuAroundTaskView(this, mTaskInsetMargin);
// Get Position
- mActivity.getDragLayer().getDescendantRectRelativeToSelf(taskView, sTempRect);
+ mActivity.getDragLayer().getDescendantRectRelativeToSelf(mTaskView, sTempRect);
Rect insets = mActivity.getDragLayer().getInsets();
BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams();
int padding = getResources()
.getDimensionPixelSize(R.dimen.task_menu_vertical_padding);
- params.width = orientationHandler.getTaskMenuWidth(taskView.getThumbnail()) - (2 * padding);
+ params.width = orientationHandler
+ .getTaskMenuWidth(taskContainer.getThumbnailView()) - (2 * padding);
// Gravity set to Left instead of Start as sTempRect.left measures Left distance not Start
params.gravity = Gravity.LEFT;
setLayoutParams(params);
- setScaleX(taskView.getScaleX());
- setScaleY(taskView.getScaleY());
+ setScaleX(mTaskView.getScaleX());
+ setScaleY(mTaskView.getScaleY());
// Set divider spacing
ShapeDrawable divider = new ShapeDrawable(new RectShape());
@@ -272,7 +300,7 @@
revealAnimator.setInterpolator(Interpolators.DEACCEL);
mOpenCloseAnimator.playTogether(revealAnimator,
ObjectAnimator.ofFloat(
- mTaskView.getThumbnail(), DIM_ALPHA,
+ mTaskContainer.getThumbnailView(), DIM_ALPHA,
closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA),
ObjectAnimator.ofFloat(this, ALPHA, closing ? 0 : 1));
mOpenCloseAnimator.addListener(new AnimationSuccessListener() {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 461a89b..053d07c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -18,13 +18,6 @@
import static android.view.Gravity.BOTTOM;
import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.Gravity.CENTER_VERTICAL;
-import static android.view.Gravity.END;
-import static android.view.Gravity.START;
-import static android.view.Gravity.TOP;
-import static android.view.Surface.ROTATION_180;
-import static android.view.Surface.ROTATION_270;
-import static android.view.Surface.ROTATION_90;
import static android.widget.Toast.LENGTH_SHORT;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
@@ -39,6 +32,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -58,7 +52,6 @@
import android.util.FloatProperty;
import android.util.Log;
import android.view.MotionEvent;
-import android.view.Surface;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
@@ -86,6 +79,7 @@
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.RunnableList;
+import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.TransformingTouchDelegate;
import com.android.launcher3.util.ViewPool.Reusable;
@@ -466,7 +460,10 @@
* Builds proto for logging
*/
public WorkspaceItemInfo getItemInfo() {
- final Task task = getTask();
+ return getItemInfo(mTask);
+ }
+
+ protected WorkspaceItemInfo getItemInfo(Task task) {
ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(task.key);
WorkspaceItemInfo stubInfo = new WorkspaceItemInfo();
stubInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK;
@@ -569,7 +566,8 @@
cancelPendingLoadTasks();
mTask = task;
mTaskIdContainer[0] = mTask.key.id;
- mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task, mSnapshotView);
+ mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task, mSnapshotView,
+ STAGE_POSITION_UNDEFINED);
mSnapshotView.bind(task);
setOrientationState(orientedState);
}
@@ -825,7 +823,7 @@
}
}
- private boolean showTaskMenu() {
+ private boolean showTaskMenu(IconView iconView) {
if (getRecentsView().mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
// Don't show menu when selecting second split screen app
return true;
@@ -837,10 +835,14 @@
} else {
mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
.log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS);
- return TaskMenuView.showForTask(this);
+ return showTaskMenuWithContainer(iconView);
}
}
+ protected boolean showTaskMenuWithContainer(IconView iconView) {
+ return TaskMenuView.showForTask(mTaskIdAttributeContainer[0]);
+ }
+
protected void setIcon(IconView iconView, Drawable icon) {
if (icon != null) {
iconView.setDrawable(icon);
@@ -850,14 +852,14 @@
recentsView.switchToScreenshot(
() -> recentsView.finishRecentsAnimation(true /* toRecents */,
false /* shouldPip */,
- this::showTaskMenu));
+ () -> showTaskMenu(iconView)));
} else {
- showTaskMenu();
+ showTaskMenu(iconView);
}
});
iconView.setOnLongClickListener(v -> {
requestDisallowInterceptTouchEvent(true);
- return showTaskMenu();
+ return showTaskMenu(iconView);
});
} else {
iconView.setDrawable(null);
@@ -1328,8 +1330,9 @@
getContext().getText(R.string.accessibility_close)));
final Context context = getContext();
+ // TODO(b/200609838) Determine which task to run A11y action on when in split screen
for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
- mActivity.getDeviceProfile())) {
+ mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) {
info.addAction(s.createAccessibilityAction(context));
}
@@ -1361,8 +1364,9 @@
return true;
}
+ // TODO(b/200609838) Determine which task to run A11y action on when in split screen
for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
- mActivity.getDeviceProfile())) {
+ mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) {
if (s.hasHandlerForAction(action)) {
s.onClick(this);
return true;
@@ -1581,20 +1585,40 @@
}
public class TaskIdAttributeContainer {
- private final TaskThumbnailView thumbnailView;
- private final Task task;
+ private final TaskThumbnailView mThumbnailView;
+ private final Task mTask;
+ /** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */
+ private @SplitConfigurationOptions.StagePosition int mStagePosition;
- public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView) {
- this.task = task;
- this.thumbnailView = thumbnailView;
+ public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView,
+ int stagePosition) {
+ this.mTask = task;
+ this.mThumbnailView = thumbnailView;
+ this.mStagePosition = stagePosition;
}
public TaskThumbnailView getThumbnailView() {
- return thumbnailView;
+ return mThumbnailView;
}
public Task getTask() {
- return task;
+ return mTask;
+ }
+
+ public WorkspaceItemInfo getItemInfo() {
+ return TaskView.this.getItemInfo(mTask);
+ }
+
+ public TaskView getTaskView() {
+ return TaskView.this;
+ }
+
+ public int getStagePosition() {
+ return mStagePosition;
+ }
+
+ void setStagePosition(@SplitConfigurationOptions.StagePosition int stagePosition) {
+ this.mStagePosition = stagePosition;
}
}
}
diff --git a/res/values/config.xml b/res/values/config.xml
index 72959b2..7c681a8 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -176,7 +176,7 @@
<item name="staggered_damping_ratio" type="dimen" format="float">0.7</item>
<item name="staggered_stiffness" type="dimen" format="float">150</item>
- <dimen name="unlock_staggered_velocity_dp_per_s">4dp</dimen>
+ <dimen name="unlock_staggered_velocity_dp_per_s">2dp</dimen>
<item name="hint_scale_damping_ratio" type="dimen" format="float">0.7</item>
<item name="hint_scale_stiffness" type="dimen" format="float">200</item>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 3121bfc..ce8cf3c 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -33,7 +33,6 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.DisplayMetrics;
-import android.util.Pair;
import android.view.Surface;
import com.android.launcher3.CellLayout.ContainerType;
@@ -215,8 +214,6 @@
// Whether Taskbar will inset the bottom of apps by taskbarSize.
public boolean isTaskbarPresentInApps;
public int taskbarSize;
- // How much of the bottom inset is due to Taskbar rather than other system elements.
- public int nonOverlappingTaskbarInset;
// DragController
public int flingToDeleteThresholdVelocity;
@@ -239,7 +236,7 @@
widthPx = windowBounds.bounds.width();
heightPx = windowBounds.bounds.height();
availableWidthPx = windowBounds.availableSize.x;
- int nonFinalAvailableHeightPx = windowBounds.availableSize.y;
+ availableHeightPx = windowBounds.availableSize.y;
mInfo = info;
// If the device's pixel density was scaled (usually via settings for A11y), use the
@@ -266,15 +263,8 @@
isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
&& FeatureFlags.ENABLE_TASKBAR.get();
if (isTaskbarPresent) {
- // Taskbar will be added later, but provides bottom insets that we should subtract
- // from availableHeightPx.
taskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_size);
- nonOverlappingTaskbarInset = taskbarSize - windowBounds.insets.bottom;
- if (nonOverlappingTaskbarInset > 0) {
- nonFinalAvailableHeightPx -= nonOverlappingTaskbarInset;
- }
}
- availableHeightPx = nonFinalAvailableHeightPx;
edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
@@ -842,7 +832,7 @@
padding.right = hotseatBarSizePx;
}
} else {
- int hotseatTop = isTaskbarPresent ? taskbarSize : hotseatBarSizePx;
+ int hotseatTop = hotseatBarSizePx;
int paddingBottom = hotseatTop + workspacePageIndicatorHeight
+ workspaceBottomPadding - mWorkspacePageIndicatorOverlapWorkspace;
if (isTablet) {
@@ -853,8 +843,7 @@
((inv.numColumns - 1) * cellWidthPx)));
availablePaddingX = (int) Math.min(availablePaddingX,
widthPx * MAX_HORIZONTAL_PADDING_PERCENT);
- int hotseatVerticalPadding = isTaskbarPresent ? 0
- : hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx;
+ int hotseatVerticalPadding = hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx;
int availablePaddingY = Math.max(0, heightPx - edgeMarginPx - paddingBottom
- (2 * inv.numRows * cellHeightPx) - hotseatVerticalPadding);
padding.set(availablePaddingX / 2, edgeMarginPx + availablePaddingY / 2,
@@ -886,9 +875,9 @@
mInsets.right + hotseatBarSidePaddingStartPx, mInsets.bottom);
}
} else if (isTaskbarPresent) {
- int hotseatHeight = workspacePadding.bottom + taskbarSize;
+ int hotseatHeight = workspacePadding.bottom;
int taskbarOffset = getTaskbarOffsetY();
- int hotseatTopDiff = hotseatHeight - taskbarSize - taskbarOffset;
+ int hotseatTopDiff = hotseatHeight - taskbarOffset;
int endOffset = ApiWrapper.getHotseatEndOffset(context);
int requiredWidth = iconSizePx * numShownHotseatIcons;
@@ -938,7 +927,8 @@
: hotseatBarSizePx - hotseatCellHeightPx - hotseatQsbHeight;
if (isScalableGrid && qsbBottomMarginPx > mInsets.bottom) {
- return Math.min(qsbBottomMarginPx, freeSpace);
+ // Note that taskbarSize = 0 unless isTaskbarPresent.
+ return Math.min(qsbBottomMarginPx + taskbarSize, freeSpace);
} else {
return (int) (freeSpace * QSB_CENTER_FACTOR)
+ (isTaskbarPresent ? taskbarSize : mInsets.bottom);
@@ -1116,10 +1106,7 @@
writer.println(prefix + "\tisTaskbarPresent:" + isTaskbarPresent);
writer.println(prefix + "\tisTaskbarPresentInApps:" + isTaskbarPresentInApps);
-
writer.println(prefix + pxToDpStr("taskbarSize", taskbarSize));
- writer.println(prefix + pxToDpStr("nonOverlappingTaskbarInset",
- nonOverlappingTaskbarInset));
writer.println(prefix + pxToDpStr("workspacePadding.left", workspacePadding.left));
writer.println(prefix + pxToDpStr("workspacePadding.top", workspacePadding.top));
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index f26cfe8..7de2ee4 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -4,15 +4,20 @@
import android.annotation.TargetApi;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.ViewDebug;
import android.view.WindowInsets;
+import androidx.annotation.RequiresApi;
+
import com.android.launcher3.graphics.SysUiScrim;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.uioverrides.ApiWrapper;
import java.util.Collections;
import java.util.List;
@@ -42,15 +47,8 @@
}
private void handleSystemWindowInsets(Rect insets) {
- DeviceProfile dp = mActivity.getDeviceProfile();
-
- // Taskbar provides insets, but we don't want that for most Launcher elements so remove it.
- mTempRect.set(insets);
- insets = mTempRect;
- insets.bottom = Math.max(0, insets.bottom - dp.nonOverlappingTaskbarInset);
-
// Update device profile before notifying the children.
- dp.updateInsets(insets);
+ mActivity.getDeviceProfile().updateInsets(insets);
boolean resetState = !insets.equals(mInsets);
setInsets(insets);
@@ -61,12 +59,69 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
- insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+ if (Utilities.ATLEAST_R) {
+ insets = updateInsetsDueToTaskbar(insets);
+ Insets systemWindowInsets = insets.getInsetsIgnoringVisibility(
+ WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
+ mTempRect.set(systemWindowInsets.left, systemWindowInsets.top, systemWindowInsets.right,
+ systemWindowInsets.bottom);
+ } else {
+ mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
+ insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+ }
handleSystemWindowInsets(mTempRect);
return insets;
}
+ /**
+ * Taskbar provides nav bar and tappable insets. However, taskbar is not attached immediately,
+ * and can be destroyed and recreated. Thus, instead of relying on taskbar being present to
+ * get its insets, we calculate them ourselves so they are stable regardless of whether taskbar
+ * is currently attached.
+ *
+ * @param oldInsets The system-provided insets, which we are modifying.
+ * @return The updated insets.
+ */
+ @RequiresApi(api = Build.VERSION_CODES.R)
+ private WindowInsets updateInsetsDueToTaskbar(WindowInsets oldInsets) {
+ if (!ApiWrapper.TASKBAR_DRAWN_IN_PROCESS) {
+ // 3P launchers based on Launcher3 should still be inset like normal.
+ return oldInsets;
+ }
+
+ WindowInsets.Builder updatedInsetsBuilder = new WindowInsets.Builder(oldInsets);
+
+ DeviceProfile dp = mActivity.getDeviceProfile();
+ Resources resources = getResources();
+
+ Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars());
+ Rect newNavInsets = new Rect(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right,
+ oldNavInsets.bottom);
+
+ if (dp.isLandscape) {
+ if (dp.isTablet) {
+ newNavInsets.bottom = ResourceUtils.getNavbarSize(
+ "navigation_bar_height_landscape", resources);
+ } else {
+ int navWidth = ResourceUtils.getNavbarSize("navigation_bar_width", resources);
+ if (dp.isSeascape()) {
+ newNavInsets.left = navWidth;
+ } else {
+ newNavInsets.right = navWidth;
+ }
+ }
+ } else {
+ newNavInsets.bottom = ResourceUtils.getNavbarSize("navigation_bar_height", resources);
+ }
+ updatedInsetsBuilder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(newNavInsets));
+ updatedInsetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(),
+ Insets.of(newNavInsets));
+
+ mActivity.updateWindowInsets(updatedInsetsBuilder, oldInsets);
+
+ return updatedInsetsBuilder.build();
+ }
+
@Override
public void setInsets(Rect insets) {
// If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 3faa3d0..c5e9dd2 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -314,8 +314,6 @@
Rect padding = grid.workspacePadding;
setPadding(padding.left, padding.top, padding.right, padding.bottom);
mInsets.set(insets);
- // Increase our bottom insets so we don't overlap with the taskbar.
- mInsets.bottom += grid.nonOverlappingTaskbarInset;
if (mWorkspaceFadeInAdjacentScreens) {
// In landscape mode the page spacing is set to the default.
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 63fd9a0..a701548 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -426,8 +426,7 @@
@Override
public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
if (Utilities.ATLEAST_Q) {
- mNavBarScrimHeight = insets.getTappableElementInsets().bottom
- - mLauncher.getDeviceProfile().nonOverlappingTaskbarInset;
+ mNavBarScrimHeight = insets.getTappableElementInsets().bottom;
} else {
mNavBarScrimHeight = insets.getStableInsetBottom();
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 382f7a7..c067291 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -271,6 +271,10 @@
"QUICK_WALLPAPER_PICKER", false,
"Shows quick wallpaper picker in long-press menu");
+ public static final BooleanFlag ENABLE_BACK_SWIPE_HOME_ANIMATION = getDebugFlag(
+ "ENABLE_BACK_SWIPE_HOME_ANIMATION", true,
+ "Enables home animation to icon when user swipes back.");
+
public static void initialize(Context context) {
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
index 9889a80..b74d0fc 100644
--- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
+++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
@@ -21,7 +21,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.pm.PackageInstallInfo;
import com.android.launcher3.util.InstantAppResolver;
@@ -73,13 +72,7 @@
dataModel.forAllWorkspaceItemInfos(mInstallInfo.user, si -> {
if (si.hasPromiseIconUi()
&& mInstallInfo.packageName.equals(si.getTargetPackage())) {
- int installProgress = mInstallInfo.progress;
-
- si.setProgressLevel(installProgress, PackageInstallInfo.STATUS_INSTALLING);
- if (mInstallInfo.state == PackageInstallInfo.STATUS_FAILED) {
- // Mark this info as broken.
- si.runtimeStatusFlags &= ~ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
- }
+ si.setProgressLevel(mInstallInfo);
updates.add(si);
}
});
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index 6813b97..a74c02f 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -24,6 +24,7 @@
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.FastBitmapDrawable;
+import com.android.launcher3.logging.FileLog;
import com.android.launcher3.pm.PackageInstallInfo;
import com.android.launcher3.util.PackageManagerHelper;
@@ -179,6 +180,12 @@
*/
public void setProgressLevel(PackageInstallInfo installInfo) {
setProgressLevel(installInfo.progress, installInfo.state);
+
+ if (installInfo.state == PackageInstallInfo.STATUS_FAILED) {
+ FileLog.d(TAG,
+ "Icon info: " + this + " marked broken with install info: " + installInfo,
+ new Exception());
+ }
}
/**
diff --git a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
index f73d782..c685891 100644
--- a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
@@ -268,9 +268,7 @@
} else {
lp.leftMargin = lp.rightMargin = 0;
lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
- lp.bottomMargin = grid.isTaskbarPresent
- ? grid.workspacePadding.bottom + grid.taskbarSize
- : grid.hotseatBarSizePx + insets.bottom;
+ lp.bottomMargin = grid.hotseatBarSizePx + insets.bottom;
}
setLayoutParams(lp);
}
diff --git a/src/com/android/launcher3/pm/PackageInstallInfo.java b/src/com/android/launcher3/pm/PackageInstallInfo.java
index fad904f..1797c1f 100644
--- a/src/com/android/launcher3/pm/PackageInstallInfo.java
+++ b/src/com/android/launcher3/pm/PackageInstallInfo.java
@@ -57,4 +57,28 @@
public static PackageInstallInfo fromState(int state, String packageName, UserHandle user) {
return new PackageInstallInfo(packageName, state, 0 /* progress */, user);
}
+
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "(" + dumpProperties() + ")";
+ }
+
+ private String dumpProperties() {
+ return "componentName=" + componentName
+ + "packageName=" + packageName
+ + " state=" + stateToString()
+ + " progress=" + progress
+ + " user=" + user;
+ }
+
+ private String stateToString() {
+ switch (state) {
+ case STATUS_INSTALLED : return "STATUS_INSTALLED";
+ case STATUS_INSTALLING : return "STATUS_INSTALLING";
+ case STATUS_INSTALLED_DOWNLOADING : return "STATUS_INSTALLED_DOWNLOADING";
+ case STATUS_FAILED : return "STATUS_FAILED";
+ default : return "INVALID STATE";
+ }
+ }
}
diff --git a/src/com/android/launcher3/statemanager/StatefulActivity.java b/src/com/android/launcher3/statemanager/StatefulActivity.java
index 8a35cb3..7a23caa 100644
--- a/src/com/android/launcher3/statemanager/StatefulActivity.java
+++ b/src/com/android/launcher3/statemanager/StatefulActivity.java
@@ -17,11 +17,15 @@
import static com.android.launcher3.LauncherState.FLAG_NON_INTERACTIVE;
+import android.graphics.Insets;
+import android.os.Build;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.WindowInsets;
import androidx.annotation.CallSuper;
+import androidx.annotation.RequiresApi;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.LauncherRootView;
@@ -173,4 +177,12 @@
mHandler.removeCallbacks(mHandleDeferredResume);
Utilities.postAsyncCallback(mHandler, mHandleDeferredResume);
}
+
+ /**
+ * Gives subclasses a chance to override some window insets (via
+ * {@link android.view.WindowInsets.Builder#setInsets(int, Insets)}).
+ */
+ @RequiresApi(api = Build.VERSION_CODES.R)
+ public void updateWindowInsets(WindowInsets.Builder updatedInsetsBuilder,
+ WindowInsets oldInsets) { }
}
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index 8db1dbe..5fe5450 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -59,11 +59,10 @@
float scale = grid.workspaceSpringLoadShrinkFactor;
Rect insets = launcher.getDragLayer().getInsets();
- int insetsBottom = grid.isTaskbarPresent ? grid.taskbarSize : insets.bottom;
float scaledHeight = scale * ws.getNormalChildHeight();
float shrunkTop = insets.top + grid.dropTargetBarSizePx;
- float shrunkBottom = ws.getMeasuredHeight() - insetsBottom
+ float shrunkBottom = ws.getMeasuredHeight() - insets.bottom
- grid.workspacePadding.bottom
- grid.workspaceSpringLoadedBottomSpace;
float totalShrunkSpace = shrunkBottom - shrunkTop;
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index 86acff7..5a9c074 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -116,9 +116,7 @@
return getUIProperty(Bundle::putParcelable, activity -> {
WindowInsets insets = activity.getWindow()
.getDecorView().getRootWindowInsets();
- return Insets.subtract(
- insets.getSystemWindowInsets(),
- Insets.of(0, 0, 0, mDeviceProfile.nonOverlappingTaskbarInset));
+ return insets.getSystemWindowInsets();
}, this::getCurrentActivity);
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index bb4638a..68532ca 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -36,7 +36,6 @@
import android.widget.TableRow;
import android.widget.TextView;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.WidgetItem;
@@ -70,7 +69,6 @@
private static final long EDUCATION_TIP_DELAY_MS = 300;
private ItemInfo mOriginalItemInfo;
- private final int mMaxTableHeight;
private int mMaxHorizontalSpan = DEFAULT_MAX_HORIZONTAL_SPANS;
private final int mWidgetCellHorizontalPadding;
@@ -110,10 +108,6 @@
public WidgetsBottomSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWillNotDraw(false);
- DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
- // Set the max table height to 2 / 3 of the grid height so that the bottom picker won't
- // take over the entire view vertically.
- mMaxTableHeight = deviceProfile.inv.numRows * 2 / 3 * deviceProfile.cellHeightPx;
if (!hasSeenEducationTip()) {
addOnLayoutChangeListener(mLayoutChangeListenerToShowTips);
}
@@ -162,13 +156,9 @@
setTranslationShift(mTranslationShift);
- // Ensure the scroll view height is not larger than mMaxTableHeight, which is a value
- // smaller than the entire screen height.
ScrollView widgetsTableScrollView = findViewById(R.id.widgets_table_scroll_view);
- if (widgetsTableScrollView.getMeasuredHeight() > mMaxTableHeight) {
- ViewGroup.LayoutParams layoutParams = widgetsTableScrollView.getLayoutParams();
- layoutParams.height = mMaxTableHeight;
- widgetsTableScrollView.setLayoutParams(layoutParams);
+ TableLayout widgetsTable = findViewById(R.id.widgets_table);
+ if (widgetsTable.getMeasuredHeight() > widgetsTableScrollView.getMeasuredHeight()) {
findViewById(R.id.collapse_handle).setVisibility(VISIBLE);
}
}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index cd0c7f2..1a6ce8c 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -153,6 +153,8 @@
public static String dumpHprofData() {
String result;
if (sDumpWasGenerated) {
+ Log.d("b/195319692", "dump has already been generated by another test",
+ new Exception());
result = "dump has already been generated by another test";
} else {
try {
@@ -167,6 +169,7 @@
"am dumpheap " + device.getLauncherPackageName() + " " + fileName);
}
sDumpWasGenerated = true;
+ Log.d("b/195319692", "sDumpWasGenerated := true", new Exception());
result = "memory dump filename: " + fileName;
} catch (Throwable e) {
Log.e(TAG, "dumpHprofData failed", e);