Snap for 7688365 from cf1f1d1966 to tm-release

Change-Id: I9b04e1af4c6ed6d47574d6a1c0d455f4b581911d
This commit is contained in:
Android Build Coastguard Worker
2021-08-31 03:07:50 +00:00
12 changed files with 141 additions and 75 deletions
@@ -104,6 +104,23 @@
</LinearLayout>
<!-- 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"
@@ -96,7 +96,11 @@ public class DepthController implements StateHandler<LauncherState>,
public void onDraw() {
View view = mLauncher.getDragLayer();
ViewRootImpl viewRootImpl = view.getViewRootImpl();
setSurface(viewRootImpl != null ? viewRootImpl.getSurfaceControl() : null);
boolean applied = setSurface(
viewRootImpl != null ? viewRootImpl.getSurfaceControl() : null);
if (!applied) {
dispatchTransactionSurface(mDepth);
}
view.post(() -> view.getViewTreeObserver().removeOnDrawListener(this));
}
};
@@ -202,20 +206,22 @@ public class DepthController implements StateHandler<LauncherState>,
/**
* Sets the specified app target surface to apply the blur to.
* @return true when surface was valid and transaction was dispatched.
*/
public void setSurface(SurfaceControl surface) {
public boolean setSurface(SurfaceControl surface) {
// Set launcher as the SurfaceControl when we don't need an external target anymore.
if (surface == null) {
ViewRootImpl viewRootImpl = mLauncher.getDragLayer().getViewRootImpl();
surface = viewRootImpl != null ? viewRootImpl.getSurfaceControl() : null;
}
if (mSurface != surface) {
mSurface = surface;
if (surface != null) {
dispatchTransactionSurface(mDepth);
return true;
}
}
return false;
}
@Override
@@ -229,6 +235,8 @@ public class DepthController implements StateHandler<LauncherState>,
setDepth(toDepth);
} else if (toState == LauncherState.OVERVIEW) {
dispatchTransactionSurface(mDepth);
} else if (toState == LauncherState.BACKGROUND_APP) {
mLauncher.getDragLayer().getViewTreeObserver().addOnDrawListener(mOnDrawListener);
}
}
@@ -123,11 +123,9 @@ public class TaskbarDragLayerController {
*/
public void updateInsetsTouchability(InsetsInfo insetsInfo) {
insetsInfo.touchableRegion.setEmpty();
if (mActivity.isThreeButtonNav()) {
// Always have nav buttons be touchable
mControllers.navbarButtonsViewController.addVisibleButtonsRegion(
mTaskbarDragLayer, insetsInfo.touchableRegion);
}
// Always have nav buttons be touchable
mControllers.navbarButtonsViewController.addVisibleButtonsRegion(
mTaskbarDragLayer, insetsInfo.touchableRegion);
if (mTaskbarDragLayer.getAlpha() < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
// Let touches pass through us.
@@ -71,7 +71,7 @@ class QuickstepInteractionHandler implements RemoteViews.InteractionHandler {
}
}
activityOptions.options.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY);
Object itemInfo = hostView.getTag();
if (itemInfo instanceof ItemInfo) {
mLauncher.addLaunchCookie((ItemInfo) itemInfo, activityOptions.options);
@@ -366,8 +366,8 @@ public final class TaskViewUtils {
* device is considered in multiWindowMode and things like insets and stuff change
* and calculations have to be adjusted in the animations for that
*/
public static void composeRecentsSplitLaunchAnimator(@NonNull TaskView initialView,
@NonNull TaskView v, @NonNull TransitionInfo transitionInfo,
public static void composeRecentsSplitLaunchAnimator(@NonNull Task initalTask,
@NonNull Task secondTask, @NonNull TransitionInfo transitionInfo,
SurfaceControl.Transaction t, @NonNull Runnable finishCallback) {
final TransitionInfo.Change[] splitRoots = new TransitionInfo.Change[2];
@@ -377,7 +377,7 @@ public final class TaskViewUtils {
final int mode = change.getMode();
// Find the target tasks' root tasks since those are the split stages that need to
// be animated (the tasks themselves are children and thus inherit animation).
if (taskId == initialView.getTask().key.id || taskId == v.getTask().key.id) {
if (taskId == initalTask.key.id || taskId == secondTask.key.id) {
if (!(mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT)) {
throw new IllegalStateException(
"Expected task to be showing, but it is " + mode);
@@ -386,7 +386,7 @@ public final class TaskViewUtils {
throw new IllegalStateException("Initiating multi-split launch but the split"
+ "root of " + taskId + " is already visible or has broken hierarchy.");
}
splitRoots[taskId == initialView.getTask().key.id ? 0 : 1] =
splitRoots[taskId == initalTask.key.id ? 0 : 1] =
transitionInfo.getChange(change.getParent());
}
}
@@ -406,8 +406,8 @@ public final class TaskViewUtils {
}
/** Legacy version (until shell transitions are enabled) */
public static void composeRecentsSplitLaunchAnimatorLegacy(@NonNull TaskView initialView,
@NonNull TaskView v, @NonNull RemoteAnimationTargetCompat[] appTargets,
public static void composeRecentsSplitLaunchAnimatorLegacy(@NonNull Task initialTask,
@NonNull Task secondTask, @NonNull RemoteAnimationTargetCompat[] appTargets,
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
@NonNull RemoteAnimationTargetCompat[] nonAppTargets,
@NonNull Runnable finishCallback) {
@@ -416,12 +416,12 @@ public final class TaskViewUtils {
for (int i = 0; i < appTargets.length; ++i) {
final int taskId = appTargets[i].taskInfo != null ? appTargets[i].taskInfo.taskId : -1;
final int mode = appTargets[i].mode;
if (taskId == initialView.getTask().key.id || taskId == v.getTask().key.id) {
if (taskId == initialTask.key.id || taskId == secondTask.key.id) {
if (mode != MODE_OPENING) {
throw new IllegalStateException(
"Expected task to be opening, but it is " + mode);
}
splitRoots[taskId == initialView.getTask().key.id ? 0 : 1] = i;
splitRoots[taskId == initialTask.key.id ? 0 : 1] = i;
}
}
@@ -33,7 +33,7 @@ import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -47,23 +47,21 @@ import com.android.systemui.shared.system.RemoteTransitionRunner;
public class SplitSelectStateController {
private final SystemUiProxy mSystemUiProxy;
private TaskView mInitialTaskView;
private TaskView mSecondTaskView;
private @StagePosition int mStagePosition;
private Task mInitialTask;
private Task mSecondTask;
private Rect mInitialBounds;
private final Handler mHandler;
public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy) {
mSystemUiProxy = systemUiProxy;
mHandler = handler;
}
/**
* To be called after first task selected
*/
public void setInitialTaskSelect(TaskView taskView, @StagePosition int stagePosition,
public void setInitialTaskSelect(Task taskView, @StagePosition int stagePosition,
Rect initialBounds) {
mInitialTaskView = taskView;
mInitialTask = taskView;
mStagePosition = stagePosition;
mInitialBounds = initialBounds;
}
@@ -71,21 +69,28 @@ public class SplitSelectStateController {
/**
* To be called after second task selected
*/
public void setSecondTaskId(TaskView taskView) {
mSecondTaskView = taskView;
public void setSecondTaskId(Task taskView) {
mSecondTask = taskView;
launchTasks(mInitialTask, mSecondTask, mStagePosition);
}
/**
* @param stagePosition representing location of task1
*/
public void launchTasks(Task task1, Task task2, @StagePosition int stagePosition) {
// Assume initial task is for top/left part of screen
final int[] taskIds = mStagePosition == STAGE_POSITION_TOP_OR_LEFT
? new int[]{mInitialTaskView.getTask().key.id, taskView.getTask().key.id}
: new int[]{taskView.getTask().key.id, mInitialTaskView.getTask().key.id};
final int[] taskIds = stagePosition == STAGE_POSITION_TOP_OR_LEFT
? new int[]{task1.key.id, task2.key.id}
: new int[]{task2.key.id, task1.key.id};
if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
RemoteSplitLaunchTransitionRunner animationRunner =
new RemoteSplitLaunchTransitionRunner(mInitialTaskView, taskView);
new RemoteSplitLaunchTransitionRunner(task1, task2);
mSystemUiProxy.startTasks(taskIds[0], null /* mainOptions */, taskIds[1],
null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT,
new RemoteTransitionCompat(animationRunner, MAIN_EXECUTOR));
} else {
RemoteSplitLaunchAnimationRunner animationRunner =
new RemoteSplitLaunchAnimationRunner(mInitialTaskView, taskView);
new RemoteSplitLaunchAnimationRunner(task1, task2);
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
RemoteAnimationAdapterCompat.wrapRemoteAnimationRunner(animationRunner),
300, 150,
@@ -105,19 +110,19 @@ public class SplitSelectStateController {
*/
private class RemoteSplitLaunchTransitionRunner implements RemoteTransitionRunner {
private final TaskView mInitialTaskView;
private final TaskView mTaskView;
private final Task mInitialTask;
private final Task mSecondTask;
RemoteSplitLaunchTransitionRunner(TaskView initialTaskView, TaskView taskView) {
mInitialTaskView = initialTaskView;
mTaskView = taskView;
RemoteSplitLaunchTransitionRunner(Task initialTask, Task secondTask) {
mInitialTask = initialTask;
mSecondTask = secondTask;
}
@Override
public void startAnimation(IBinder transition, TransitionInfo info,
SurfaceControl.Transaction t, Runnable finishCallback) {
TaskViewUtils.composeRecentsSplitLaunchAnimator(mInitialTaskView, mTaskView,
info, t, finishCallback);
TaskViewUtils.composeRecentsSplitLaunchAnimator(mInitialTask,
mSecondTask, info, t, finishCallback);
// After successful launch, call resetState
resetState();
}
@@ -129,20 +134,20 @@ public class SplitSelectStateController {
*/
private class RemoteSplitLaunchAnimationRunner implements RemoteAnimationRunnerCompat {
private final TaskView mInitialTaskView;
private final TaskView mTaskView;
private final Task mInitialTask;
private final Task mSecondTask;
RemoteSplitLaunchAnimationRunner(TaskView initialTaskView, TaskView taskView) {
mInitialTaskView = initialTaskView;
mTaskView = taskView;
RemoteSplitLaunchAnimationRunner(Task initialTask, Task secondTask) {
mInitialTask = initialTask;
mSecondTask = secondTask;
}
@Override
public void onAnimationStart(int transit, RemoteAnimationTargetCompat[] apps,
RemoteAnimationTargetCompat[] wallpapers, RemoteAnimationTargetCompat[] nonApps,
Runnable finishedCallback) {
TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(mInitialTaskView, mTaskView, apps,
wallpapers, nonApps, finishedCallback);
TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(mInitialTask,
mSecondTask, apps, wallpapers, nonApps, finishedCallback);
// After successful launch, call resetState
resetState();
}
@@ -157,8 +162,8 @@ public class SplitSelectStateController {
* To be called if split select was cancelled
*/
public void resetState() {
mInitialTaskView = null;
mSecondTaskView = null;
mInitialTask = null;
mSecondTask = null;
mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
mInitialBounds = null;
}
@@ -168,7 +173,7 @@ public class SplitSelectStateController {
* chosen
*/
public boolean isSplitSelectActive() {
return mInitialTaskView != null && mSecondTaskView == null;
return mInitialTask != null && mSecondTask == null;
}
public Rect getInitialBounds() {
@@ -4,6 +4,7 @@ import android.content.Context;
import android.util.AttributeSet;
import com.android.launcher3.R;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskThumbnailCache;
@@ -94,6 +95,13 @@ public class GroupedTaskView extends TaskView {
}
}
@Override
public RunnableList launchTaskAnimated() {
getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT);
return null;
}
@Override
public void onRecycle() {
super.onRecycle();
@@ -3568,7 +3568,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
mSplitHiddenTaskView = taskView;
Rect initialBounds = new Rect(taskView.getLeft(), taskView.getTop(), taskView.getRight(),
taskView.getBottom());
mSplitSelectStateController.setInitialTaskSelect(taskView, stagePosition, initialBounds);
mSplitSelectStateController.setInitialTaskSelect(taskView.getTask(),
stagePosition, initialBounds);
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
finishRecentsAnimation(true, null);
@@ -3609,7 +3610,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
secondTaskEndingBounds, taskView.getThumbnail(),
true /*fadeWithThumbnail*/);
pendingAnimation.addEndListener(aBoolean -> {
mSplitSelectStateController.setSecondTaskId(taskView);
mSplitSelectStateController.setSecondTaskId(taskView.getTask());
resetFromSplitSelectionState();
});
mSecondSplitHiddenTaskView = taskView;
@@ -454,7 +454,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.WORK].recyclerView);
if (mUsingTabs) {
setupWorkToggle();
mAH[AdapterHolder.MAIN].setup(mViewPager.getChildAt(0), mPersonalMatcher);
mAH[AdapterHolder.WORK].setup(mViewPager.getChildAt(1), mWorkMatcher);
mAH[AdapterHolder.WORK].recyclerView.setId(R.id.apps_list_view_work);
@@ -485,6 +484,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
}
private void setupWorkToggle() {
removeWorkToggle();
if (Utilities.ATLEAST_P) {
mWorkModeSwitch = (WorkModeSwitch) mLauncher.getLayoutInflater().inflate(
R.layout.work_mode_fab, this, false);
@@ -497,6 +497,14 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
}
}
private void removeWorkToggle() {
if (mWorkModeSwitch == null) return;
if (mWorkModeSwitch.getParent() == this) {
this.removeView(mWorkModeSwitch);
}
mWorkModeSwitch = null;
}
private void replaceRVContainer(boolean showTabs) {
for (int i = 0; i < mAH.length; i++) {
AllAppsRecyclerView rv = mAH[i].recyclerView;
@@ -519,8 +527,10 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
mViewPager = (AllAppsPagedView) newView;
mViewPager.initParentViews(this);
mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
setupWorkToggle();
} else {
mViewPager = null;
removeWorkToggle();
}
}
@@ -539,14 +549,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
mWorkModeSwitch.setWorkTabVisible(currentActivePage == AdapterHolder.WORK
&& mAllAppsStore.hasModelFlag(
FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION));
if (currentActivePage == AdapterHolder.WORK) {
if (mWorkModeSwitch.getParent() == null) {
addView(mWorkModeSwitch);
}
} else {
removeView(mWorkModeSwitch);
}
}
}
@@ -51,6 +51,7 @@ public class WorkModeSwitch extends Button implements Insettable, View.OnClickLi
@Nullable
private KeyboardInsetAnimationCallback mKeyboardInsetAnimationCallback;
private boolean mWorkTabVisible;
public WorkModeSwitch(Context context) {
this(context, null, 0);
@@ -91,11 +92,10 @@ public class WorkModeSwitch extends Button implements Insettable, View.OnClickLi
*/
public void setWorkTabVisible(boolean workTabVisible) {
clearAnimation();
if (workTabVisible) {
mWorkTabVisible = workTabVisible;
if (workTabVisible && mWorkEnabled) {
setEnabled(true);
if (mWorkEnabled) {
setVisibility(VISIBLE);
}
setVisibility(VISIBLE);
setAlpha(0);
animate().alpha(1).start();
} else {
@@ -105,7 +105,7 @@ public class WorkModeSwitch extends Button implements Insettable, View.OnClickLi
@Override
public void onClick(View view) {
if (Utilities.ATLEAST_P) {
if (Utilities.ATLEAST_P && mWorkTabVisible) {
setEnabled(false);
Launcher.fromContext(getContext()).getStatsLogManager().logger().log(
LAUNCHER_TURN_OFF_WORK_APPS_TAP);
@@ -137,7 +137,7 @@ public class WorkModeSwitch extends Button implements Insettable, View.OnClickLi
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (Utilities.ATLEAST_R) {
if (Utilities.ATLEAST_R && mWorkTabVisible) {
setTranslationY(0);
if (insets.isVisible(WindowInsets.Type.ime())) {
Insets keyboardInsets = insets.getInsets(WindowInsets.Type.ime());
@@ -76,6 +76,22 @@ public class StatsLogManager implements ResourceBasedOverride {
}
public interface EventEnum {
/**
* Tag used to request new UI Event IDs via presubmit analysis.
*
* <p>Use RESERVE_NEW_UI_EVENT_ID as the constructor parameter for a new {@link EventEnum}
* to signal the presubmit analyzer to reserve a new ID for the event. The new ID will be
* returned as a Gerrit presubmit finding. Do not submit {@code RESERVE_NEW_UI_EVENT_ID} as
* the constructor parameter for any event.
*
* <pre>
* &#064;UiEvent(doc = "Briefly describe the interaction when this event will be logged")
* UNIQUE_EVENT_NAME(RESERVE_NEW_UI_EVENT_ID);
* </pre>
*/
int RESERVE_NEW_UI_EVENT_ID = Integer.MIN_VALUE; // Negative IDs are ignored by the logger.
int getId();
}
@@ -489,8 +505,7 @@ public class StatsLogManager implements ResourceBasedOverride {
LAUNCHER_TURN_OFF_WORK_APPS_TAP(839),
@UiEvent(doc = "Launcher item drop failed since there was not enough room on the screen.")
LAUNCHER_ITEM_DROP_FAILED_INSUFFICIENT_SPACE(872)
;
LAUNCHER_ITEM_DROP_FAILED_INSUFFICIENT_SPACE(872);
// ADD MORE
@@ -15,6 +15,7 @@ import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -66,15 +67,18 @@ public class FailureWatcher extends TestWatcher {
onError(mDevice, description, e);
}
static File diagFile(Description description, String prefix, String ext) {
return new File(getInstrumentation().getTargetContext().getFilesDir(),
prefix + "-" + description.getTestClass().getSimpleName() + "."
+ description.getMethodName() + "." + ext);
}
public static void onError(UiDevice device, Description description, Throwable e) {
Log.d("b/196820244", "onError 1");
if (device == null) return;
Log.d("b/196820244", "onError 2");
final File parentFile = getInstrumentation().getTargetContext().getFilesDir();
final File sceenshot = new File(parentFile,
"TestScreenshot-" + description.getMethodName() + ".png");
final File hierarchy = new File(parentFile,
"Hierarchy-" + description.getMethodName() + ".zip");
final File sceenshot = diagFile(description, "TestScreenshot", "png");
final File hierarchy = diagFile(description, "Hierarchy", "zip");
// Dump window hierarchy
try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(hierarchy))) {
@@ -97,13 +101,13 @@ public class FailureWatcher extends TestWatcher {
device.takeScreenshot(sceenshot);
// Dump accessibility hierarchy
final File accessibilityHierarchyFile = new File(parentFile,
"AccessibilityHierarchy-" + description.getMethodName() + ".uix");
try {
device.dumpWindowHierarchy(accessibilityHierarchyFile);
device.dumpWindowHierarchy(diagFile(description, "AccessibilityHierarchy", "uix"));
} catch (IOException ex) {
Log.e(TAG, "Failed to save accessibility hierarchy", ex);
}
dumpCommand("logcat -d -s TestRunner", diagFile(description, "FilteredLogcat", "txt"));
}
private static void dumpStringCommand(String cmd, OutputStream out) throws IOException {
@@ -111,6 +115,14 @@ public class FailureWatcher extends TestWatcher {
dumpCommand(cmd, out);
}
private static void dumpCommand(String cmd, File out) {
try (BufferedOutputStream buffered = new BufferedOutputStream(
new FileOutputStream(out))) {
dumpCommand(cmd, buffered);
} catch (IOException ex) {
}
}
private static void dumpCommand(String cmd, OutputStream out) throws IOException {
try (AutoCloseInputStream in = new AutoCloseInputStream(getInstrumentation()
.getUiAutomation().executeShellCommand(cmd))) {