Snap for 7941279 from 9119e1fab3 to tm-release
Change-Id: Iefadbd16c1def8924fc8d1a7de3395aa255a78ae
This commit is contained in:
@@ -17,7 +17,6 @@ package com.android.launcher3.taskbar;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
|
||||
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y_LONG_CLICK;
|
||||
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
|
||||
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME;
|
||||
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH;
|
||||
@@ -90,7 +89,6 @@ public class NavbarButtonsViewController {
|
||||
|
||||
private static final int MASK_IME_SWITCHER_VISIBLE = FLAG_SWITCHER_SUPPORTED | FLAG_IME_VISIBLE;
|
||||
|
||||
private View.OnLongClickListener mA11yLongClickListener;
|
||||
private final ArrayList<StatePropertyHolder> mPropertyHolders = new ArrayList<>();
|
||||
private final ArrayList<ImageView> mAllButtons = new ArrayList<>();
|
||||
private int mState;
|
||||
@@ -142,11 +140,6 @@ public class NavbarButtonsViewController {
|
||||
mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize;
|
||||
mNavButtonTranslationYMultiplier.value = 1;
|
||||
|
||||
mA11yLongClickListener = view -> {
|
||||
mControllers.navButtonController.onButtonClick(BUTTON_A11Y_LONG_CLICK);
|
||||
return true;
|
||||
};
|
||||
|
||||
mPropertyHolders.add(new StatePropertyHolder(
|
||||
mControllers.taskbarViewController.getTaskbarIconAlpha()
|
||||
.getProperty(ALPHA_INDEX_IME),
|
||||
@@ -285,7 +278,6 @@ public class NavbarButtonsViewController {
|
||||
mPropertyHolders.add(new StatePropertyHolder(mA11yButton,
|
||||
flags -> (flags & FLAG_A11Y_VISIBLE) != 0
|
||||
&& (flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0));
|
||||
mA11yButton.setOnLongClickListener(mA11yLongClickListener);
|
||||
}
|
||||
|
||||
private void parseSystemUiFlags(int sysUiStateFlags) {
|
||||
@@ -441,6 +433,8 @@ public class NavbarButtonsViewController {
|
||||
ImageView buttonView = addButton(parent, id, layoutId);
|
||||
buttonView.setImageResource(drawableId);
|
||||
buttonView.setOnClickListener(view -> navButtonController.onButtonClick(buttonType));
|
||||
buttonView.setOnLongClickListener(view ->
|
||||
navButtonController.onButtonLongClick(buttonType));
|
||||
return buttonView;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
package com.android.launcher3.taskbar;
|
||||
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS;
|
||||
import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_KEY;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
|
||||
@@ -35,11 +37,9 @@ import java.lang.annotation.RetentionPolicy;
|
||||
* Controller for 3 button mode in the taskbar.
|
||||
* Handles all the functionality of the various buttons, making/routing the right calls into
|
||||
* launcher or sysui/system.
|
||||
*
|
||||
* TODO: Create callbacks to hook into UI layer since state will change for more context buttons/
|
||||
* assistant invocation.
|
||||
*/
|
||||
public class TaskbarNavButtonController {
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(value = {
|
||||
BUTTON_BACK,
|
||||
@@ -47,7 +47,6 @@ public class TaskbarNavButtonController {
|
||||
BUTTON_RECENTS,
|
||||
BUTTON_IME_SWITCH,
|
||||
BUTTON_A11Y,
|
||||
BUTTON_A11Y_LONG_CLICK
|
||||
})
|
||||
|
||||
public @interface TaskbarButton {}
|
||||
@@ -57,7 +56,6 @@ public class TaskbarNavButtonController {
|
||||
static final int BUTTON_RECENTS = BUTTON_HOME << 1;
|
||||
static final int BUTTON_IME_SWITCH = BUTTON_RECENTS << 1;
|
||||
static final int BUTTON_A11Y = BUTTON_IME_SWITCH << 1;
|
||||
static final int BUTTON_A11Y_LONG_CLICK = BUTTON_A11Y << 1;
|
||||
|
||||
private final TouchInteractionService mService;
|
||||
|
||||
@@ -82,9 +80,22 @@ public class TaskbarNavButtonController {
|
||||
case BUTTON_A11Y:
|
||||
notifyImeClick(false /* longClick */);
|
||||
break;
|
||||
case BUTTON_A11Y_LONG_CLICK:
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onButtonLongClick(@TaskbarButton int buttonType) {
|
||||
switch (buttonType) {
|
||||
case BUTTON_HOME:
|
||||
startAssistant();
|
||||
return true;
|
||||
case BUTTON_A11Y:
|
||||
notifyImeClick(true /* longClick */);
|
||||
break;
|
||||
return true;
|
||||
case BUTTON_BACK:
|
||||
case BUTTON_IME_SWITCH:
|
||||
case BUTTON_RECENTS:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,4 +124,11 @@ public class TaskbarNavButtonController {
|
||||
systemUiProxy.notifyAccessibilityButtonClicked(mService.getDisplayId());
|
||||
}
|
||||
}
|
||||
|
||||
private void startAssistant() {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
|
||||
SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate();
|
||||
systemUiProxy.startAssistant(args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.android.wm.shell.recents.IRecentTasksListener;
|
||||
import com.android.wm.shell.util.GroupedRecentTaskInfo;
|
||||
import com.android.wm.shell.util.StagedSplitBounds;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
@@ -219,6 +220,26 @@ public class RecentTasksList {
|
||||
return newTasks;
|
||||
}
|
||||
|
||||
public void dump(String prefix, PrintWriter writer) {
|
||||
writer.println(prefix + "RecentTasksList:");
|
||||
writer.println(prefix + " mChangeId=" + mChangeId);
|
||||
writer.println(prefix + " mResultsUi=[id=" + mResultsUi.mRequestId + ", tasks=");
|
||||
for (GroupTask task : mResultsUi) {
|
||||
writer.println(prefix + " t1=" + task.task1.key.id
|
||||
+ " t2=" + (task.hasMultipleTasks() ? task.task2.key.id : "-1"));
|
||||
}
|
||||
writer.println(prefix + " ]");
|
||||
int currentUserId = Process.myUserHandle().getIdentifier();
|
||||
ArrayList<GroupedRecentTaskInfo> rawTasks =
|
||||
mSysUiProxy.getRecentTasks(Integer.MAX_VALUE, currentUserId);
|
||||
writer.println(prefix + " rawTasks=[");
|
||||
for (GroupedRecentTaskInfo task : rawTasks) {
|
||||
writer.println(prefix + " t1=" + task.mTaskInfo1.taskId
|
||||
+ " t2=" + (task.mTaskInfo2 != null ? task.mTaskInfo2.taskId : "-1"));
|
||||
}
|
||||
writer.println(prefix + " ]");
|
||||
}
|
||||
|
||||
private static class TaskLoadResult extends ArrayList<GroupTask> {
|
||||
|
||||
final int mRequestId;
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.android.systemui.shared.system.KeyguardManagerCompat;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -220,6 +221,11 @@ public class RecentsModel extends TaskStackChangeListener implements IconChangeL
|
||||
mThumbnailChangeListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void dump(String prefix, PrintWriter writer) {
|
||||
writer.println(prefix + "RecentsModel:");
|
||||
mTaskList.dump(" ", writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for receiving various task properties changes
|
||||
*/
|
||||
|
||||
@@ -83,14 +83,16 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
MAIN_EXECUTOR.execute(() -> clearProxy());
|
||||
};
|
||||
|
||||
// Save the listeners passed into the proxy since when set/register these listeners,
|
||||
// setProxy may not have been called, eg. OverviewProxyService is not connected yet.
|
||||
private IPipAnimationListener mPendingPipAnimationListener;
|
||||
private ISplitScreenListener mPendingSplitScreenListener;
|
||||
private IStartingWindowListener mPendingStartingWindowListener;
|
||||
private ISmartspaceCallback mPendingSmartspaceCallback;
|
||||
private IRecentTasksListener mPendingRecentTasksListener;
|
||||
private final ArrayList<RemoteTransitionCompat> mPendingRemoteTransitions = new ArrayList<>();
|
||||
// Save the listeners passed into the proxy since OverviewProxyService may not have been bound
|
||||
// yet, and we'll need to set/register these listeners with SysUI when they do. Note that it is
|
||||
// up to the caller to clear the listeners to prevent leaks as these can be held indefinitely
|
||||
// in case SysUI needs to rebind.
|
||||
private IPipAnimationListener mPipAnimationListener;
|
||||
private ISplitScreenListener mSplitScreenListener;
|
||||
private IStartingWindowListener mStartingWindowListener;
|
||||
private ISmartspaceCallback mSmartspaceCallback;
|
||||
private IRecentTasksListener mRecentTasksListener;
|
||||
private final ArrayList<RemoteTransitionCompat> mRemoteTransitions = new ArrayList<>();
|
||||
|
||||
// Used to dedupe calls to SystemUI
|
||||
private int mLastShelfHeight;
|
||||
@@ -167,29 +169,23 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
mRecentTasks = recentTasks;
|
||||
linkToDeath();
|
||||
// re-attach the listeners once missing due to setProxy has not been initialized yet.
|
||||
if (mPendingPipAnimationListener != null && mPip != null) {
|
||||
setPinnedStackAnimationListener(mPendingPipAnimationListener);
|
||||
mPendingPipAnimationListener = null;
|
||||
if (mPipAnimationListener != null && mPip != null) {
|
||||
setPinnedStackAnimationListener(mPipAnimationListener);
|
||||
}
|
||||
if (mPendingSplitScreenListener != null && mSplitScreen != null) {
|
||||
registerSplitScreenListener(mPendingSplitScreenListener);
|
||||
mPendingSplitScreenListener = null;
|
||||
if (mSplitScreenListener != null && mSplitScreen != null) {
|
||||
registerSplitScreenListener(mSplitScreenListener);
|
||||
}
|
||||
if (mPendingStartingWindowListener != null && mStartingWindow != null) {
|
||||
setStartingWindowListener(mPendingStartingWindowListener);
|
||||
mPendingStartingWindowListener = null;
|
||||
if (mStartingWindowListener != null && mStartingWindow != null) {
|
||||
setStartingWindowListener(mStartingWindowListener);
|
||||
}
|
||||
if (mPendingSmartspaceCallback != null && mSmartspaceTransitionController != null) {
|
||||
setSmartspaceCallback(mPendingSmartspaceCallback);
|
||||
mPendingSmartspaceCallback = null;
|
||||
if (mSmartspaceCallback != null && mSmartspaceTransitionController != null) {
|
||||
setSmartspaceCallback(mSmartspaceCallback);
|
||||
}
|
||||
for (int i = mPendingRemoteTransitions.size() - 1; i >= 0; --i) {
|
||||
registerRemoteTransition(mPendingRemoteTransitions.get(i));
|
||||
for (int i = mRemoteTransitions.size() - 1; i >= 0; --i) {
|
||||
registerRemoteTransition(mRemoteTransitions.get(i));
|
||||
}
|
||||
mPendingRemoteTransitions.clear();
|
||||
if (mPendingRecentTasksListener != null && mRecentTasks != null) {
|
||||
registerRecentTasksListener(mPendingRecentTasksListener);
|
||||
mPendingRecentTasksListener = null;
|
||||
if (mRecentTasksListener != null && mRecentTasks != null) {
|
||||
registerRecentTasksListener(mRecentTasksListener);
|
||||
}
|
||||
|
||||
if (mPendingSetNavButtonAlpha != null) {
|
||||
@@ -513,9 +509,8 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call setPinnedStackAnimationListener", e);
|
||||
}
|
||||
} else {
|
||||
mPendingPipAnimationListener = listener;
|
||||
}
|
||||
mPipAnimationListener = listener;
|
||||
}
|
||||
|
||||
public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
|
||||
@@ -553,9 +548,8 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call registerSplitScreenListener");
|
||||
}
|
||||
} else {
|
||||
mPendingSplitScreenListener = listener;
|
||||
}
|
||||
mSplitScreenListener = listener;
|
||||
}
|
||||
|
||||
public void unregisterSplitScreenListener(ISplitScreenListener listener) {
|
||||
@@ -566,7 +560,7 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
Log.w(TAG, "Failed call unregisterSplitScreenListener");
|
||||
}
|
||||
}
|
||||
mPendingSplitScreenListener = null;
|
||||
mSplitScreenListener = null;
|
||||
}
|
||||
|
||||
/** Start multiple tasks in split-screen simultaneously. */
|
||||
@@ -687,9 +681,8 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call registerRemoteTransition");
|
||||
}
|
||||
} else {
|
||||
mPendingRemoteTransitions.add(remoteTransition);
|
||||
}
|
||||
mRemoteTransitions.add(remoteTransition);
|
||||
}
|
||||
|
||||
public void unregisterRemoteTransition(RemoteTransitionCompat remoteTransition) {
|
||||
@@ -700,7 +693,7 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
Log.w(TAG, "Failed call registerRemoteTransition");
|
||||
}
|
||||
}
|
||||
mPendingRemoteTransitions.remove(remoteTransition);
|
||||
mRemoteTransitions.remove(remoteTransition);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -717,9 +710,8 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call setStartingWindowListener", e);
|
||||
}
|
||||
} else {
|
||||
mPendingStartingWindowListener = listener;
|
||||
}
|
||||
mStartingWindowListener = listener;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -733,9 +725,8 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call setStartingWindowListener", e);
|
||||
}
|
||||
} else {
|
||||
mPendingSmartspaceCallback = callback;
|
||||
}
|
||||
mSmartspaceCallback = callback;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -749,9 +740,8 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call registerRecentTasksListener", e);
|
||||
}
|
||||
} else {
|
||||
mPendingRecentTasksListener = listener;
|
||||
}
|
||||
mRecentTasksListener = listener;
|
||||
}
|
||||
|
||||
public void unregisterRecentTasksListener(IRecentTasksListener listener) {
|
||||
@@ -762,7 +752,7 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
Log.w(TAG, "Failed call unregisterRecentTasksListener");
|
||||
}
|
||||
}
|
||||
mPendingRecentTasksListener = null;
|
||||
mRecentTasksListener = null;
|
||||
}
|
||||
|
||||
public ArrayList<GroupedRecentTaskInfo> getRecentTasks(int numTasks, int userId) {
|
||||
|
||||
@@ -72,7 +72,13 @@ public interface TaskShortcutFactory {
|
||||
@Override
|
||||
public SystemShortcut getShortcut(BaseDraggingActivity activity,
|
||||
TaskIdAttributeContainer taskContainer) {
|
||||
return new AppInfo(activity, taskContainer.getItemInfo());
|
||||
TaskView taskView = taskContainer.getTaskView();
|
||||
AppInfo.SplitAccessibilityInfo accessibilityInfo =
|
||||
new AppInfo.SplitAccessibilityInfo(taskView.containsMultipleTasks(),
|
||||
TaskUtils.getTitle(taskView.getContext(), taskContainer.getTask()),
|
||||
taskContainer.getA11yNodeId()
|
||||
);
|
||||
return new AppInfo(activity, taskContainer.getItemInfo(), accessibilityInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -951,6 +951,7 @@ public class TouchInteractionService extends Service
|
||||
pw.println(" resumed=" + resumed);
|
||||
pw.println(" mConsumer=" + mConsumer.getName());
|
||||
ActiveGestureLog.INSTANCE.dump("", pw);
|
||||
RecentsModel.INSTANCE.get(this).dump("", pw);
|
||||
pw.println("ProtoTrace:");
|
||||
pw.println(" file=" + ProtoTracer.INSTANCE.get(this).getTraceFile());
|
||||
}
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import android.graphics.HardwareRenderer;
|
||||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
import android.view.ViewRootImpl;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.systemui.shared.system.ViewRootImplCompat;
|
||||
@@ -45,9 +47,9 @@ public class ViewUtils {
|
||||
return new FrameHandler(view, onFinishRunnable, canceled).schedule();
|
||||
}
|
||||
|
||||
private static class FrameHandler implements LongConsumer {
|
||||
private static class FrameHandler implements HardwareRenderer.FrameDrawingCallback {
|
||||
|
||||
final ViewRootImplCompat mViewRoot;
|
||||
final ViewRootImpl mViewRoot;
|
||||
final Runnable mFinishCallback;
|
||||
final BooleanSupplier mCancelled;
|
||||
final Handler mHandler;
|
||||
@@ -55,14 +57,14 @@ public class ViewUtils {
|
||||
int mDeferFrameCount = 1;
|
||||
|
||||
FrameHandler(View view, Runnable finishCallback, BooleanSupplier cancelled) {
|
||||
mViewRoot = new ViewRootImplCompat(view);
|
||||
mViewRoot = view.getViewRootImpl();
|
||||
mFinishCallback = finishCallback;
|
||||
mCancelled = cancelled;
|
||||
mHandler = new Handler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(long l) {
|
||||
public void onFrameDraw(long frame) {
|
||||
Utilities.postAsyncCallback(mHandler, this::onFrame);
|
||||
}
|
||||
|
||||
@@ -83,7 +85,7 @@ public class ViewUtils {
|
||||
}
|
||||
|
||||
private boolean schedule() {
|
||||
if (mViewRoot.isValid()) {
|
||||
if (mViewRoot.getView() != null) {
|
||||
mViewRoot.registerRtFrameCallback(this);
|
||||
mViewRoot.getView().invalidate();
|
||||
return true;
|
||||
|
||||
@@ -24,6 +24,8 @@ import static android.view.MotionEvent.ACTION_POINTER_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_POINTER_UP;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_GESTURE;
|
||||
import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_KEY;
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -64,8 +66,6 @@ public class AssistantInputConsumer extends DelegateInputConsumer {
|
||||
private static final String OPA_BUNDLE_TRIGGER = "triggered_by";
|
||||
// From //java/com/google/android/apps/gsa/assistant/shared/proto/opa_trigger.proto.
|
||||
private static final int OPA_BUNDLE_TRIGGER_DIAG_SWIPE_GESTURE = 83;
|
||||
private static final String INVOCATION_TYPE_KEY = "invocation_type";
|
||||
private static final int INVOCATION_TYPE_GESTURE = 1;
|
||||
|
||||
private final PointF mDownPos = new PointF();
|
||||
private final PointF mLastPos = new PointF();
|
||||
|
||||
@@ -22,10 +22,10 @@ import android.os.Message;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
import android.view.View;
|
||||
import android.view.ViewRootImpl;
|
||||
|
||||
import com.android.quickstep.RemoteAnimationTargets.ReleaseCheck;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
|
||||
import com.android.systemui.shared.system.ViewRootImplCompat;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -41,7 +41,7 @@ public class SurfaceTransactionApplier extends ReleaseCheck {
|
||||
private static final int MSG_UPDATE_SEQUENCE_NUMBER = 0;
|
||||
|
||||
private final SurfaceControl mBarrierSurfaceControl;
|
||||
private final ViewRootImplCompat mTargetViewRootImpl;
|
||||
private final ViewRootImpl mTargetViewRootImpl;
|
||||
private final Handler mApplyHandler;
|
||||
|
||||
private int mLastSequenceNumber = 0;
|
||||
@@ -50,8 +50,8 @@ public class SurfaceTransactionApplier extends ReleaseCheck {
|
||||
* @param targetView The view in the surface that acts as synchronization anchor.
|
||||
*/
|
||||
public SurfaceTransactionApplier(View targetView) {
|
||||
mTargetViewRootImpl = new ViewRootImplCompat(targetView);
|
||||
mBarrierSurfaceControl = mTargetViewRootImpl.getRenderSurfaceControl();
|
||||
mTargetViewRootImpl = targetView.getViewRootImpl();
|
||||
mBarrierSurfaceControl = mTargetViewRootImpl.getSurfaceControl();
|
||||
mApplyHandler = new Handler(this::onApplyMessage);
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class SurfaceTransactionApplier extends ReleaseCheck {
|
||||
if (targetView == null) {
|
||||
// No target view, no applier
|
||||
callback.accept(null);
|
||||
} else if (new ViewRootImplCompat(targetView).isValid()) {
|
||||
} else if (targetView.isAttachedToWindow()) {
|
||||
// Already attached, we're good to go
|
||||
callback.accept(new SurfaceTransactionApplier(targetView));
|
||||
} else {
|
||||
|
||||
@@ -136,7 +136,7 @@ final class FloatingWidgetBackgroundView extends View {
|
||||
}
|
||||
|
||||
/** Returns the maximum corner radius of {@param drawable}. */
|
||||
private static float getMaxRadius(Drawable drawable) {
|
||||
private static float getMaxRadius(@Nullable Drawable drawable) {
|
||||
if (!(drawable instanceof GradientDrawable)) return 0;
|
||||
float[] cornerRadii = ((GradientDrawable) drawable).getCornerRadii();
|
||||
float cornerRadius = ((GradientDrawable) drawable).getCornerRadius();
|
||||
|
||||
@@ -87,6 +87,14 @@ public class IconView extends View {
|
||||
return mDrawable;
|
||||
}
|
||||
|
||||
public int getDrawableWidth() {
|
||||
return mDrawableWidth;
|
||||
}
|
||||
|
||||
public int getDrawableHeight() {
|
||||
return mDrawableHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
|
||||
@@ -2612,10 +2612,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
clampToProgress(FINAL_FRAME, 0, 0.5f));
|
||||
});
|
||||
}
|
||||
boolean isTaskInBottomGridRow = showAsGrid() && !mTopRowIdSet.contains(
|
||||
taskView.getTaskViewId()) && taskView.getTaskViewId() != mFocusedTaskViewId;
|
||||
anim.setFloat(taskView, VIEW_ALPHA, 0,
|
||||
clampToProgress(isTaskInBottomGridRow ? ACCEL : FINAL_FRAME, 0, 0.5f));
|
||||
clampToProgress(isOnGridBottomRow(taskView) ? ACCEL : FINAL_FRAME, 0, 0.5f));
|
||||
FloatProperty<TaskView> secondaryViewTranslate =
|
||||
taskView.getSecondaryDissmissTranslationProperty();
|
||||
int secondaryTaskDimension = mOrientationHandler.getSecondaryDimension(taskView);
|
||||
@@ -4681,6 +4679,15 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
return position != -1 ? position : bottomRowIdArray.indexOf(taskView.getTaskViewId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the task in on the top of the grid
|
||||
*/
|
||||
public boolean isOnGridBottomRow(TaskView taskView) {
|
||||
return showAsGrid()
|
||||
&& !mTopRowIdSet.contains(taskView.getTaskViewId())
|
||||
&& taskView.getTaskViewId() != mFocusedTaskViewId;
|
||||
}
|
||||
|
||||
public Consumer<MotionEvent> getEventDispatcher(float navbarRotation) {
|
||||
float degreesRotated;
|
||||
if (navbarRotation == 0) {
|
||||
|
||||
@@ -45,7 +45,10 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
companion object {
|
||||
const val TAG = "TaskMenuViewWithArrow"
|
||||
|
||||
fun showForTask(taskContainer: TaskIdAttributeContainer): Boolean {
|
||||
fun showForTask(
|
||||
taskContainer: TaskIdAttributeContainer,
|
||||
alignSecondRow: Boolean = false
|
||||
): Boolean {
|
||||
val activity = BaseDraggingActivity
|
||||
.fromContext<BaseDraggingActivity>(taskContainer.taskView.context)
|
||||
val taskMenuViewWithArrow = activity.layoutInflater
|
||||
@@ -55,7 +58,7 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
false
|
||||
) as TaskMenuViewWithArrow<*>
|
||||
|
||||
return taskMenuViewWithArrow.populateAndShowForTask(taskContainer)
|
||||
return taskMenuViewWithArrow.populateAndShowForTask(taskContainer, alignSecondRow)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +81,9 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
CLOSE_FADE_DURATION = CLOSE_CHILD_FADE_DURATION
|
||||
}
|
||||
|
||||
private var alignSecondRow: Boolean = false
|
||||
private val extraSpaceForSecondRowAlignment: Int
|
||||
get() = if (alignSecondRow) optionMeasuredHeight else 0
|
||||
private val menuWidth = context.resources.getDimensionPixelSize(R.dimen.task_menu_width_grid)
|
||||
|
||||
private lateinit var taskView: TaskView
|
||||
@@ -91,6 +97,10 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
else
|
||||
0
|
||||
|
||||
private var iconView: IconView? = null
|
||||
private var scrim: View? = null
|
||||
private val scrimAlpha = 0.8f
|
||||
|
||||
override fun isOfType(type: Int): Boolean = type and TYPE_TASK_MENU != 0
|
||||
|
||||
override fun getTargetObjectLocation(outPos: Rect?) {
|
||||
@@ -112,18 +122,35 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
optionLayout = findViewById(KtR.id.menu_option_layout)
|
||||
}
|
||||
|
||||
private fun populateAndShowForTask(taskContainer: TaskIdAttributeContainer): Boolean {
|
||||
private fun populateAndShowForTask(
|
||||
taskContainer: TaskIdAttributeContainer,
|
||||
alignSecondRow: Boolean
|
||||
): Boolean {
|
||||
if (isAttachedToWindow) {
|
||||
return false
|
||||
}
|
||||
|
||||
taskView = taskContainer.taskView
|
||||
this.taskContainer = taskContainer
|
||||
this.alignSecondRow = alignSecondRow
|
||||
if (!populateMenu()) return false
|
||||
addScrim()
|
||||
show()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun addScrim() {
|
||||
scrim = View(context).apply {
|
||||
layoutParams = FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
FrameLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
setBackgroundColor(Themes.getAttrColor(context, R.attr.overviewScrimColor))
|
||||
alpha = 0f
|
||||
}
|
||||
popupContainer.addView(scrim)
|
||||
}
|
||||
|
||||
/** @return true if successfully able to populate task view menu, false otherwise
|
||||
*/
|
||||
private fun populateMenu(): Boolean {
|
||||
@@ -180,18 +207,50 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
}
|
||||
|
||||
override fun onCreateOpenAnimation(anim: AnimatorSet) {
|
||||
anim.play(
|
||||
ObjectAnimator.ofFloat(
|
||||
taskContainer.thumbnailView, TaskThumbnailView.DIM_ALPHA,
|
||||
TaskView.MAX_PAGE_SCRIM_ALPHA
|
||||
scrim?.let {
|
||||
anim.play(
|
||||
ObjectAnimator.ofFloat(it, View.ALPHA, 0f, scrimAlpha)
|
||||
.setDuration(OPEN_DURATION.toLong())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateCloseAnimation(anim: AnimatorSet) {
|
||||
anim.play(
|
||||
ObjectAnimator.ofFloat(taskContainer.thumbnailView, TaskThumbnailView.DIM_ALPHA, 0f)
|
||||
)
|
||||
scrim?.let {
|
||||
anim.play(
|
||||
ObjectAnimator.ofFloat(it, View.ALPHA, scrimAlpha, 0f)
|
||||
.setDuration(CLOSE_DURATION.toLong())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun closeComplete() {
|
||||
super.closeComplete()
|
||||
popupContainer.removeView(scrim)
|
||||
popupContainer.removeView(iconView)
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the iconView from taskView to dragLayer so it can stay on top of the scrim.
|
||||
* It needs to be called after [getTargetObjectLocation] because [mTempRect] needs to be
|
||||
* populated.
|
||||
*/
|
||||
private fun copyIconToDragLayer(insets: Rect) {
|
||||
iconView = IconView(context).apply {
|
||||
layoutParams = FrameLayout.LayoutParams(
|
||||
taskContainer.iconView.width,
|
||||
taskContainer.iconView.height
|
||||
)
|
||||
x = mTempRect.left.toFloat() - insets.left
|
||||
y = mTempRect.top.toFloat() - insets.top
|
||||
drawable = taskContainer.iconView.drawable
|
||||
setDrawableSize(
|
||||
taskContainer.iconView.drawableWidth,
|
||||
taskContainer.iconView.drawableHeight
|
||||
)
|
||||
}
|
||||
|
||||
popupContainer.addView(iconView)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,7 +276,10 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
val dragLayer: InsettableFrameLayout = popupContainer
|
||||
val insets = dragLayer.insets
|
||||
|
||||
// Put to the right of the icon if there is space, which means left aligned with the menu
|
||||
copyIconToDragLayer(insets)
|
||||
|
||||
// Put this menu to the right of the icon if there is space,
|
||||
// which means the arrow is left aligned with the menu
|
||||
val rightAlignedMenuStartX = mTempRect.left - widthWithArrow
|
||||
val leftAlignedMenuStartX = mTempRect.right + extraHorizontalSpace
|
||||
mIsLeftAligned = if (mIsRtl) {
|
||||
@@ -229,18 +291,17 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
|
||||
var menuStartX = if (mIsLeftAligned) leftAlignedMenuStartX else rightAlignedMenuStartX
|
||||
|
||||
// Offset y so that the arrow and first row are center-aligned with the original icon.
|
||||
// Offset y so that the arrow and row are center-aligned with the original icon.
|
||||
val iconHeight = mTempRect.height()
|
||||
val optionHeight = optionMeasuredHeight
|
||||
val yOffset = (optionHeight - iconHeight) / 2
|
||||
var menuStartY = mTempRect.top - yOffset
|
||||
val yOffset = (optionMeasuredHeight - iconHeight) / 2
|
||||
var menuStartY = mTempRect.top - yOffset - extraSpaceForSecondRowAlignment
|
||||
|
||||
// Insets are added later, so subtract them now.
|
||||
menuStartX -= insets.left
|
||||
menuStartY -= insets.top
|
||||
|
||||
setX(menuStartX.toFloat())
|
||||
setY(menuStartY.toFloat())
|
||||
x = menuStartX.toFloat()
|
||||
y = menuStartY.toFloat()
|
||||
|
||||
val lp = layoutParams as FrameLayout.LayoutParams
|
||||
val arrowLp = mArrow.layoutParams as FrameLayout.LayoutParams
|
||||
@@ -251,7 +312,8 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
||||
override fun addArrow() {
|
||||
popupContainer.addView(mArrow)
|
||||
mArrow.x = getArrowX()
|
||||
mArrow.y = y + (optionMeasuredHeight / 2) - (mArrowHeight / 2)
|
||||
mArrow.y = y + (optionMeasuredHeight / 2) - (mArrowHeight / 2) +
|
||||
extraSpaceForSecondRowAlignment
|
||||
|
||||
updateArrowColor()
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
|
||||
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_BOTTOM_OR_RIGHT;
|
||||
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
@@ -38,6 +39,7 @@ import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.IdRes;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -840,7 +842,9 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
TaskIdAttributeContainer menuContainer =
|
||||
mTaskIdAttributeContainer[iconView == mIconView ? 0 : 1];
|
||||
if (mActivity.getDeviceProfile().overviewShowAsGrid) {
|
||||
return TaskMenuViewWithArrow.Companion.showForTask(menuContainer);
|
||||
boolean alignSecondRow = getRecentsView().isOnGridBottomRow(menuContainer.getTaskView())
|
||||
&& mActivity.getDeviceProfile().isLandscape;
|
||||
return TaskMenuViewWithArrow.Companion.showForTask(menuContainer, alignSecondRow);
|
||||
} else {
|
||||
return TaskMenuView.showForTask(menuContainer);
|
||||
}
|
||||
@@ -1302,10 +1306,14 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
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(), mTaskIdAttributeContainer[0])) {
|
||||
info.addAction(s.createAccessibilityAction(context));
|
||||
for (TaskIdAttributeContainer taskContainer : mTaskIdAttributeContainer) {
|
||||
if (taskContainer == null) {
|
||||
continue;
|
||||
}
|
||||
for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
|
||||
mActivity.getDeviceProfile(), taskContainer)) {
|
||||
info.addAction(s.createAccessibilityAction(context));
|
||||
}
|
||||
}
|
||||
|
||||
if (mDigitalWellBeingToast.hasLimit()) {
|
||||
@@ -1336,12 +1344,16 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
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(), mTaskIdAttributeContainer[0])) {
|
||||
if (s.hasHandlerForAction(action)) {
|
||||
s.onClick(this);
|
||||
return true;
|
||||
for (TaskIdAttributeContainer taskContainer : mTaskIdAttributeContainer) {
|
||||
if (taskContainer == null) {
|
||||
continue;
|
||||
}
|
||||
for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
|
||||
mActivity.getDeviceProfile(), taskContainer)) {
|
||||
if (s.hasHandlerForAction(action)) {
|
||||
s.onClick(this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1558,7 +1570,6 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
mScale = previewWidth / (previewWidth + currentInsetsLeft + currentInsetsRight);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class TaskIdAttributeContainer {
|
||||
@@ -1567,6 +1578,8 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
private final IconView mIconView;
|
||||
/** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */
|
||||
private @SplitConfigurationOptions.StagePosition int mStagePosition;
|
||||
@IdRes
|
||||
private final int mA11yNodeId;
|
||||
|
||||
public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView,
|
||||
IconView iconView, int stagePosition) {
|
||||
@@ -1574,6 +1587,8 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
this.mThumbnailView = thumbnailView;
|
||||
this.mIconView = iconView;
|
||||
this.mStagePosition = stagePosition;
|
||||
this.mA11yNodeId = (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) ?
|
||||
R.id.split_bottomRight_appInfo : R.id.split_topLeft_appInfo;
|
||||
}
|
||||
|
||||
public TaskThumbnailView getThumbnailView() {
|
||||
@@ -1603,5 +1618,9 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
void setStagePosition(@SplitConfigurationOptions.StagePosition int stagePosition) {
|
||||
this.mStagePosition = stagePosition;
|
||||
}
|
||||
|
||||
public int getA11yNodeId() {
|
||||
return mA11yNodeId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
<item type="id" name="view_type_widgets_list" />
|
||||
<item type="id" name="view_type_widgets_header" />
|
||||
<item type="id" name="view_type_widgets_search_header" />
|
||||
<!-- Used for A11y actions in staged split to identify each task uniquely -->
|
||||
<item type="id" name="split_topLeft_appInfo" />
|
||||
<item type="id" name="split_bottomRight_appInfo" />
|
||||
|
||||
|
||||
<!-- Do not change, must be kept in sync with sysui navbar button IDs for tests! -->
|
||||
<item type="id" name="home" />
|
||||
|
||||
@@ -40,9 +40,10 @@
|
||||
<!-- Options for recent tasks -->
|
||||
<!-- Title for an option to enter split screen mode for a given app -->
|
||||
<string name="recent_task_option_split_screen">Split screen</string>
|
||||
<string translatable="false" name="split_screen_position_top">Split top</string>
|
||||
<string translatable="false" name="split_screen_position_left">Split left</string>
|
||||
<string translatable="false" name="split_screen_position_right">Split right</string>
|
||||
<string name="split_screen_position_top">Split top</string>
|
||||
<string name="split_screen_position_left">Split left</string>
|
||||
<string name="split_screen_position_right">Split right</string>
|
||||
<string name="split_app_info_accessibility">App info for %1$s</string>
|
||||
|
||||
<!-- Widgets -->
|
||||
<!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
|
||||
|
||||
@@ -41,8 +41,8 @@ public abstract class SystemShortcut<T extends Context & ActivityContext> extend
|
||||
implements View.OnClickListener {
|
||||
|
||||
private final int mIconResId;
|
||||
private final int mLabelResId;
|
||||
private final int mAccessibilityActionId;
|
||||
protected final int mLabelResId;
|
||||
protected int mAccessibilityActionId;
|
||||
|
||||
protected final T mTarget;
|
||||
protected final ItemInfo mItemInfo;
|
||||
@@ -142,11 +142,43 @@ public abstract class SystemShortcut<T extends Context & ActivityContext> extend
|
||||
|
||||
public static class AppInfo<T extends Context & ActivityContext> extends SystemShortcut<T> {
|
||||
|
||||
@Nullable
|
||||
private SplitAccessibilityInfo mSplitA11yInfo;
|
||||
|
||||
public AppInfo(T target, ItemInfo itemInfo) {
|
||||
super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label, target,
|
||||
itemInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used by overview for staged split to provide custom A11y information.
|
||||
*
|
||||
* Future improvements considerations:
|
||||
* Have the logic in {@link #createAccessibilityAction(Context)} be moved to super
|
||||
* call in {@link SystemShortcut#createAccessibilityAction(Context)} by having
|
||||
* SystemShortcut be aware of TaskContainers and staged split.
|
||||
* That way it could directly create the correct node info for any shortcut that supports
|
||||
* split, but then we'll need custom resIDs for each pair of shortcuts.
|
||||
*/
|
||||
public AppInfo(T target, ItemInfo itemInfo, SplitAccessibilityInfo accessibilityInfo) {
|
||||
this(target, itemInfo);
|
||||
mSplitA11yInfo = accessibilityInfo;
|
||||
mAccessibilityActionId = accessibilityInfo.nodeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibilityNodeInfo.AccessibilityAction createAccessibilityAction(
|
||||
Context context) {
|
||||
if (mSplitA11yInfo != null && mSplitA11yInfo.containsMultipleTasks) {
|
||||
String accessibilityLabel = context.getString(R.string.split_app_info_accessibility,
|
||||
mSplitA11yInfo.taskTitle);
|
||||
return new AccessibilityNodeInfo.AccessibilityAction(mAccessibilityActionId,
|
||||
accessibilityLabel);
|
||||
} else {
|
||||
return super.createAccessibilityAction(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
dismissTaskMenuView(mTarget);
|
||||
@@ -156,6 +188,19 @@ public abstract class SystemShortcut<T extends Context & ActivityContext> extend
|
||||
mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo)
|
||||
.log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP);
|
||||
}
|
||||
|
||||
public static class SplitAccessibilityInfo {
|
||||
public final boolean containsMultipleTasks;
|
||||
public final CharSequence taskTitle;
|
||||
public final int nodeId;
|
||||
|
||||
public SplitAccessibilityInfo(boolean containsMultipleTasks,
|
||||
CharSequence taskTitle, int nodeId) {
|
||||
this.containsMultipleTasks = containsMultipleTasks;
|
||||
this.taskTitle = taskTitle;
|
||||
this.nodeId = nodeId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final Factory<BaseDraggingActivity> INSTALL = (activity, itemInfo) -> {
|
||||
|
||||
Reference in New Issue
Block a user