abstracting fallback views to support container instead of activity

Test: Built and tested locally

Flag: NONE just abstracting in this cl

Bug:292269949

Change-Id: I0ce5efb4f193211216430f373605107c87de2c1a
This commit is contained in:
randypfohl
2024-07-30 11:24:27 -07:00
parent f0123c9129
commit f29dc7c5ec
28 changed files with 515 additions and 194 deletions
@@ -100,7 +100,7 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
public TaskbarDragLayer(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, 1 /* alphaChannelCount */);
mBackgroundRenderer = new TaskbarBackgroundRenderer(mActivity);
mBackgroundRenderer = new TaskbarBackgroundRenderer(mContainer);
mTaskbarBackgroundAlpha = new MultiPropertyFactory<>(this, BG_ALPHA, INDEX_COUNT,
(a, b) -> a * b, 1f);
@@ -109,7 +109,7 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
public void init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks) {
mControllerCallbacks = callbacks;
mBackgroundRenderer.updateStashedHandleWidth(mActivity, getResources());
mBackgroundRenderer.updateStashedHandleWidth(mContainer, getResources());
recreateControllers();
}
@@ -275,7 +275,7 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mContainer);
if (topView != null && topView.canHandleBack()) {
topView.onBackInvoked();
// Handled by the floating view.
@@ -73,7 +73,7 @@ public class TaskbarOverlayDragLayer extends
@Override
public void recreateControllers() {
List<TouchController> controllers = new ArrayList<>();
controllers.add(mActivity.getDragController());
controllers.add(mContainer.getDragController());
controllers.addAll(mTouchControllers);
mControllers = controllers.toArray(new TouchController[0]);
}
@@ -87,7 +87,7 @@ public class TaskbarOverlayDragLayer extends
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mContainer);
if (topView != null && topView.canHandleBack()) {
topView.onBackInvoked();
return true;
@@ -96,7 +96,7 @@ public class TaskbarOverlayDragLayer extends
&& event.getKeyCode() == KeyEvent.KEYCODE_ESCAPE && event.hasNoModifiers()) {
// Ignore escape if pressed in conjunction with any modifier keys. Close each
// floating view one at a time for each key press.
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mContainer);
if (topView != null) {
topView.close(/* animate= */ true);
return true;
@@ -107,7 +107,7 @@ public class TaskbarOverlayDragLayer extends
@Override
public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) {
if (mActivity.isAnySystemDragInProgress()) {
if (mContainer.isAnySystemDragInProgress()) {
inoutInfo.touchableRegion.setEmpty();
inoutInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
}
@@ -123,7 +123,7 @@ public class TaskbarOverlayDragLayer extends
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
mActivity.getOverlayController().maybeCloseWindow();
mContainer.getOverlayController().maybeCloseWindow();
}
/** Adds a {@link TouchController} to this drag layer. */
@@ -147,14 +147,14 @@ public class TaskbarOverlayDragLayer extends
* 2) Sets tappableInsets bottom inset to 0.
*/
private WindowInsets updateInsetsDueToStashing(WindowInsets oldInsets) {
if (!DisplayController.isTransientTaskbar(mActivity)) {
if (!DisplayController.isTransientTaskbar(mContainer)) {
return oldInsets;
}
WindowInsets.Builder updatedInsetsBuilder = new WindowInsets.Builder(oldInsets);
Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars());
Insets newNavInsets = Insets.of(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right,
mActivity.getStashedTaskbarHeight());
mContainer.getStashedTaskbarHeight());
updatedInsetsBuilder.setInsets(WindowInsets.Type.navigationBars(), newNavInsets);
Insets oldTappableInsets = oldInsets.getInsets(WindowInsets.Type.tappableElement());
@@ -36,7 +36,6 @@ import android.animation.AnimatorSet;
import android.view.MotionEvent;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
@@ -124,13 +123,6 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
return activity != null && activity.isStarted();
}
@UiThread
@Nullable
public abstract <T extends RecentsView> T getVisibleRecentsView();
@UiThread
public abstract boolean switchToRecentsIfVisible(Animator.AnimatorListener animatorListener);
public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
TaskbarUIController controller = getTaskbarController();
boolean isEventOverBubbleBarStashHandle =
@@ -34,6 +34,7 @@ import android.view.RemoteAnimationTarget;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Flags;
@@ -59,8 +60,16 @@ import java.util.function.Predicate;
public abstract class BaseContainerInterface<STATE_TYPE extends BaseState<STATE_TYPE>,
CONTAINER_TYPE extends RecentsViewContainer> {
public boolean rotationSupportedByActivity = false;
@UiThread
@Nullable
public abstract <T extends RecentsView<?,?>> T getVisibleRecentsView();
@UiThread
public abstract boolean switchToRecentsIfVisible(Animator.AnimatorListener animatorListener);
@Nullable
public abstract CONTAINER_TYPE getCreatedContainer();
@@ -126,6 +135,8 @@ public abstract class BaseContainerInterface<STATE_TYPE extends BaseState<STATE_
return false;
}
abstract void runOnInitBackgroundStateUI(Runnable callback);
@Nullable
public DesktopVisibilityController getDesktopVisibilityController() {
CONTAINER_TYPE container = getCreatedContainer();
@@ -82,7 +82,7 @@ import java.util.function.Consumer;
* Handles the navigation gestures when a 3rd party launcher is the default home activity.
*/
public class FallbackSwipeHandler extends
AbsSwipeUpHandler<RecentsActivity, FallbackRecentsView, RecentsState> {
AbsSwipeUpHandler<RecentsActivity, FallbackRecentsView<RecentsActivity>, RecentsState> {
private static final String TAG = "FallbackSwipeHandler";
@@ -0,0 +1,257 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quickstep;
import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
import static com.android.quickstep.fallback.RecentsState.BACKGROUND_APP;
import static com.android.quickstep.fallback.RecentsState.DEFAULT;
import static com.android.quickstep.fallback.RecentsState.HOME;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.content.Context;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.RemoteAnimationTarget;
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.taskbar.FallbackTaskbarUIController;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.GestureState.GestureEndTarget;
import com.android.quickstep.fallback.RecentsState;
import com.android.quickstep.fallback.window.RecentsWindowManager;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.views.RecentsView;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* {@link BaseActivityInterface} for recents when the default launcher is different than the
* currently running one and apps should interact with the {@link RecentsActivity} as opposed
* to the in-launcher one.
*/
public final class FallbackWindowInterface extends BaseWindowInterface{
private static FallbackWindowInterface INSTANCE;
private final RecentsWindowManager mRecentsWindowManager;
@Nullable
public static FallbackWindowInterface getInstance(){
return INSTANCE;
}
public static FallbackWindowInterface init(RecentsWindowManager recentsWindowManager) {
if (INSTANCE == null) {
INSTANCE = new FallbackWindowInterface(recentsWindowManager);
}
return INSTANCE;
}
private FallbackWindowInterface(RecentsWindowManager recentsWindowManager) {
super(DEFAULT, BACKGROUND_APP);
mRecentsWindowManager = recentsWindowManager;
}
public void destroy() {
INSTANCE = null;
}
/** 2 */
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect,
RecentsPagedOrientationHandler orientationHandler) {
calculateTaskSize(context, dp, outRect, orientationHandler);
if (dp.isVerticalBarLayout() && DisplayController.getNavigationMode(context) != NO_BUTTON) {
return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right);
} else {
return dp.heightPx - outRect.bottom;
}
}
/** 5 */
@Override
public void onAssistantVisibilityChanged(float visibility) {
// This class becomes active when the screen is locked.
// Rather than having it handle assistant visibility changes, the assistant visibility is
// set to zero prior to this class becoming active.
}
/** 6 */
@Override
public BaseWindowInterface.AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState
deviceState, boolean activityVisible,
Consumer<AnimatorControllerWithResistance> callback) {
notifyRecentsOfOrientation(deviceState.getRotationTouchHelper());
BaseWindowInterface.DefaultAnimationFactory factory =
new BaseWindowInterface.DefaultAnimationFactory(callback);
factory.initBackgroundStateUI();
return factory;
}
@Override
public ActivityInitListener createActivityInitListener(
Predicate<Boolean> onInitListener) {
//todo figure out how to properly replace this
return new ActivityInitListener<>((activity, alreadyOnHome) ->
onInitListener.test(alreadyOnHome), RecentsActivity.ACTIVITY_TRACKER);
}
@Nullable
@Override
public RecentsWindowManager getCreatedContainer() {
return mRecentsWindowManager;
}
@Override
public FallbackTaskbarUIController getTaskbarController() {
RecentsWindowManager manager = getCreatedContainer();
if (manager == null) {
return null;
}
return null;
// todo b/365775636: pass a taskbar implementation
// return manager.getTaskbarUIController();
}
@Override
public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTarget target) {
// TODO: Remove this once b/77875376 is fixed
return target.screenSpaceBounds;
}
@Nullable
@Override
public <T extends RecentsView<?, ?>> T getVisibleRecentsView() {
RecentsWindowManager manager = getCreatedContainer();
if(manager.isStarted() || isInLiveTileMode()){
return getCreatedContainer().getOverviewPanel();
}
return null;
}
@Override
public boolean switchToRecentsIfVisible(Animator.AnimatorListener animatorListener) {
return false;
}
@Override
protected int getOverviewScrimColorForState(RecentsWindowManager container,
RecentsState state) {
return state.getScrimColor(container.asContext());
}
@Override
public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
// In non-gesture mode, user might be clicking on the home button which would directly
// start the home activity instead of going through recents. In that case, defer starting
// recents until we are sure it is a gesture.
return false;
// return !deviceState.isFullyGesturalNavMode();
// || super.deferStartingActivity(deviceState, ev);
}
@Override
public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) {
final StateManager<RecentsState, RecentsWindowManager> stateManager =
getCreatedContainer().getStateManager();
if (stateManager.getState() == HOME) {
exitRunnable.run();
notifyRecentsOfOrientation(deviceState);
return;
}
stateManager.addStateListener(
new StateManager.StateListener<RecentsState>() {
@Override
public void onStateTransitionComplete(RecentsState toState) {
// Are we going from Recents to Workspace?
if (toState == HOME) {
exitRunnable.run();
notifyRecentsOfOrientation(deviceState);
stateManager.removeStateListener(this);
}
}
});
}
@Override
public boolean isInLiveTileMode() {
RecentsWindowManager windowManager = getCreatedContainer();
return windowManager != null && windowManager.getStateManager().getState() == DEFAULT &&
windowManager.isStarted();
}
@Override
public void onLaunchTaskFailed() {
// TODO: probably go back to overview instead.
RecentsWindowManager manager = getCreatedContainer();
if (manager == null) {
return;
}
manager.<RecentsView>getOverviewPanel().startHome();
}
@Override
public RecentsState stateFromGestureEndTarget(GestureEndTarget endTarget) {
switch (endTarget) {
case RECENTS:
return DEFAULT;
case NEW_TASK:
case LAST_TASK:
return BACKGROUND_APP;
case HOME:
case ALL_APPS:
default:
return HOME;
}
}
private void notifyRecentsOfOrientation(RotationTouchHelper rotationTouchHelper) {
// reset layout on swipe to home
RecentsView recentsView = getCreatedContainer().getOverviewPanel();
recentsView.setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(),
rotationTouchHelper.getDisplayRotation());
}
@Override
public @Nullable Animator getParallelAnimationToLauncher(GestureEndTarget endTarget,
long duration, RecentsAnimationCallbacks callbacks) {
FallbackTaskbarUIController uiController = getTaskbarController();
Animator superAnimator = super.getParallelAnimationToLauncher(
endTarget, duration, callbacks);
if (uiController == null) {
return superAnimator;
}
RecentsState toState = stateFromGestureEndTarget(endTarget);
Animator taskbarAnimator = uiController.createAnimToRecentsState(toState, duration);
if (taskbarAnimator == null) {
return superAnimator;
}
if (superAnimator == null) {
return taskbarAnimator;
}
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(superAnimator, taskbarAnimator);
return animatorSet;
}
}
@@ -190,7 +190,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
public GestureState(OverviewComponentObserver componentObserver, int gestureId) {
mHomeIntent = componentObserver.getHomeIntent();
mOverviewIntent = componentObserver.getOverviewIntent();
mContainerInterface = componentObserver.getActivityInterface();
mContainerInterface = componentObserver.getContainerInterface();
mStateCallback = new MultiStateCallback(
STATE_NAMES.toArray(new String[0]), GestureState::getTrackedEventForState);
mGestureId = gestureId;
@@ -50,15 +50,15 @@ import com.android.quickstep.views.RecentsViewContainer
import com.android.quickstep.views.TaskView
import com.android.systemui.shared.recents.model.ThumbnailData
import com.android.systemui.shared.system.InteractionJankMonitorWrapper
import java.io.PrintWriter
import java.util.concurrent.ConcurrentLinkedDeque
import kotlin.coroutines.resume
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeout
import java.io.PrintWriter
import java.util.concurrent.ConcurrentLinkedDeque
import kotlin.coroutines.resume
/** Helper class to handle various atomic commands for switching between Overview. */
class OverviewCommandHelper
@@ -80,11 +80,11 @@ constructor(
*/
private var keyboardTaskFocusIndex = -1
private val activityInterface: BaseActivityInterface<*, *>
get() = overviewComponentObserver.activityInterface
private val containerInterface: BaseContainerInterface<*, *>
get() = overviewComponentObserver.containerInterface
private val visibleRecentsView: RecentsView<*, *>?
get() = activityInterface.getVisibleRecentsView<RecentsView<*, *>>()
get() = containerInterface.getVisibleRecentsView<RecentsView<*, *>>()
/**
* Adds a command to be executed next, after all pending tasks are completed. Max commands that
@@ -258,10 +258,10 @@ constructor(
command: CommandInfo,
onCallbackResult: () -> Unit,
): Boolean {
val recentsViewContainer = activityInterface.getCreatedContainer() as? RecentsViewContainer
val recentsViewContainer = containerInterface.getCreatedContainer()
val recentsView: RecentsView<*, *>? = recentsViewContainer?.getOverviewPanel()
val deviceProfile = recentsViewContainer?.getDeviceProfile()
val uiController = activityInterface.getTaskbarController()
val uiController = containerInterface.getTaskbarController()
val allowQuickSwitch =
uiController != null &&
deviceProfile != null &&
@@ -316,13 +316,13 @@ constructor(
onCallbackResult()
}
}
if (activityInterface.switchToRecentsIfVisible(animatorListener)) {
if (containerInterface.switchToRecentsIfVisible(animatorListener)) {
Log.d(TAG, "switching to Overview state - waiting: $command")
// If successfully switched, wait until animation finishes
return false
}
val activity = activityInterface.getCreatedContainer()
val activity = containerInterface.getCreatedContainer()
if (activity != null) {
InteractionJankMonitorWrapper.begin(activity.rootView, Cuj.CUJ_LAUNCHER_QUICK_SWITCH)
}
@@ -352,7 +352,7 @@ constructor(
Log.d(TAG, "recents animation started: $command")
updateRecentsViewFocus(command)
logShowOverviewFrom(command.type)
activityInterface.runOnInitBackgroundStateUI {
containerInterface.runOnInitBackgroundStateUI {
Log.d(TAG, "recents animation started - onInitBackgroundStateUI: $command")
interactionHandler.onGestureEnded(0f, PointF())
}
@@ -366,7 +366,7 @@ constructor(
interactionHandler.onGestureCancelled()
command.removeListener(this)
activityInterface.getCreatedContainer() ?: return
containerInterface.getCreatedContainer() ?: return
recentsView?.onRecentsAnimationComplete()
}
}
@@ -473,7 +473,7 @@ constructor(
}
private fun logShowOverviewFrom(commandType: CommandType) {
val container = activityInterface.getCreatedContainer() as? RecentsViewContainer ?: return
val container = containerInterface.getCreatedContainer() ?: return
val event =
when (commandType) {
SHOW -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT
@@ -73,7 +73,7 @@ public final class OverviewComponentObserver {
private Consumer<Boolean> mOverviewChangeListener = b -> { };
private String mUpdateRegisteredPackage;
private BaseActivityInterface mActivityInterface;
private BaseContainerInterface mContainerInterface;
private Intent mOverviewIntent;
private boolean mIsHomeAndOverviewSame;
private boolean mIsDefaultHome;
@@ -150,8 +150,8 @@ public final class OverviewComponentObserver {
// Set assistant visibility to 0 from launcher's perspective, ensures any elements that
// launcher made invisible become visible again before the new activity control helper
// becomes active.
if (mActivityInterface != null) {
mActivityInterface.onAssistantVisibilityChanged(0.f);
if (mContainerInterface != null) {
mContainerInterface.onAssistantVisibilityChanged(0.f);
}
if (SEPARATE_RECENTS_ACTIVITY.get()) {
@@ -168,7 +168,7 @@ public final class OverviewComponentObserver {
if (!mIsHomeDisabled && (defaultHome == null || mIsDefaultHome)) {
// User default home is same as out home app. Use Overview integrated in Launcher.
mActivityInterface = LauncherActivityInterface.INSTANCE;
mContainerInterface = LauncherActivityInterface.INSTANCE;
mIsHomeAndOverviewSame = true;
mOverviewIntent = mMyHomeIntent;
mCurrentHomeIntent.setComponent(mMyHomeIntent.getComponent());
@@ -178,7 +178,7 @@ public final class OverviewComponentObserver {
} else {
// The default home app is a different launcher. Use the fallback Overview instead.
mActivityInterface = FallbackActivityInterface.INSTANCE;
mContainerInterface = FallbackActivityInterface.INSTANCE;
mIsHomeAndOverviewSame = false;
mOverviewIntent = mFallbackIntent;
mCurrentHomeIntent.setComponent(defaultHome);
@@ -266,21 +266,12 @@ public final class OverviewComponentObserver {
}
/**
* Get the current activity control helper for managing interactions to the overview activity.
* Get the current control helper for managing interactions to the overview container.
*
* @return the current activity control helper
* @return the current control helper
*/
public BaseActivityInterface getActivityInterface() {
return mActivityInterface;
}
/**
* Get the current container control helper for managing interactions to the overview activity.
*
* @return the current container control helper
*/
public BaseContainerInterface<?, ?> getContainerInterface() {
return mActivityInterface;
public BaseContainerInterface<?,?> getContainerInterface() {
return mContainerInterface;
}
public void dump(PrintWriter pw) {
@@ -7,6 +7,7 @@ import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.WindowInsets;
import androidx.annotation.Nullable;
@@ -203,11 +204,12 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
}
@Override
protected Activity getCurrentActivity() {
protected WindowInsets getWindowInsets() {
RecentsAnimationDeviceState rads = new RecentsAnimationDeviceState(mContext);
OverviewComponentObserver observer = new OverviewComponentObserver(mContext, rads);
try {
return observer.getActivityInterface().getCreatedContainer();
return observer.getContainerInterface()
.getCreatedContainer().getRootView().getRootWindowInsets();
} finally {
observer.onDestroy();
rads.destroy();
@@ -198,7 +198,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> implem
}
@Override
protected void onHandleConfigurationChanged() {
public void onHandleConfigurationChanged() {
initDeviceProfile();
AbstractFloatingView.closeOpenViews(this, true,
@@ -83,7 +83,6 @@ import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.ConstantItem;
import com.android.launcher3.EncryptionType;
import com.android.launcher3.Flags;
@@ -324,10 +323,10 @@ public class TouchInteractionService extends Service {
@Override
public void enterStageSplitFromRunningApp(boolean leftOrTop) {
executeForTouchInteractionService(tis -> {
StatefulActivity activity =
tis.mOverviewComponentObserver.getActivityInterface().getCreatedContainer();
if (activity != null) {
activity.enterStageSplitFromRunningApp(leftOrTop);
RecentsViewContainer container = tis.mOverviewComponentObserver
.getContainerInterface().getCreatedContainer();
if (container != null) {
container.enterStageSplitFromRunningApp(leftOrTop);
}
});
}
@@ -761,11 +760,12 @@ public class TouchInteractionService extends Service {
private void onOverviewTargetChange(boolean isHomeAndOverviewSame) {
mAllAppsActionManager.setHomeAndOverviewSame(isHomeAndOverviewSame);
StatefulActivity<?> newOverviewActivity =
mOverviewComponentObserver.getActivityInterface().getCreatedContainer();
if (newOverviewActivity != null) {
mTaskbarManager.setActivity(newOverviewActivity);
RecentsViewContainer newOverviewContainer =
mOverviewComponentObserver.getContainerInterface().getCreatedContainer();
if (newOverviewContainer != null
&& newOverviewContainer instanceof StatefulActivity activity) {
//TODO(b/368030750) refactor taskbarManager to accept RecentsViewContainer
mTaskbarManager.setActivity(activity);
}
mTISBinder.onOverviewTargetChange();
}
@@ -795,7 +795,7 @@ public class TouchInteractionService extends Service {
@UiThread
private void onAssistantVisibilityChanged() {
if (LockedUserState.get(this).isUserUnlocked()) {
mOverviewComponentObserver.getActivityInterface().onAssistantVisibilityChanged(
mOverviewComponentObserver.getContainerInterface().onAssistantVisibilityChanged(
mDeviceState.getAssistantVisibility());
}
}
@@ -1575,11 +1575,11 @@ public class TouchInteractionService extends Service {
return;
}
final BaseActivityInterface activityInterface =
mOverviewComponentObserver.getActivityInterface();
final BaseContainerInterface containerInterface =
mOverviewComponentObserver.getContainerInterface();
final Intent overviewIntent = new Intent(
mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState());
if (activityInterface.getCreatedContainer() != null && fromInit) {
if (containerInterface.getCreatedContainer() != null && fromInit) {
// The activity has been created before the initialization of overview service. It is
// usually happens when booting or launcher is the top activity, so we should already
// have the latest state.
@@ -1599,18 +1599,18 @@ public class TouchInteractionService extends Service {
if (!LockedUserState.get(this).isUserUnlocked()) {
return;
}
final BaseActivityInterface activityInterface =
mOverviewComponentObserver.getActivityInterface();
final BaseDraggingActivity activity = activityInterface.getCreatedContainer();
if (activity == null || activity.isStarted()) {
final BaseContainerInterface containerInterface =
mOverviewComponentObserver.getContainerInterface();
final RecentsViewContainer container = containerInterface.getCreatedContainer();
if (container == null || container.isStarted()) {
// We only care about the existing background activity.
return;
}
Configuration oldConfig = activity.getResources().getConfiguration();
Configuration oldConfig = container.asContext().getResources().getConfiguration();
boolean isFoldUnfold = isTablet(oldConfig) != isTablet(newConfig);
if (!isFoldUnfold && mOverviewComponentObserver.canHandleConfigChanges(
activity.getComponentName(),
activity.getResources().getConfiguration().diff(newConfig))) {
container.getComponentName(),
container.asContext().getResources().getConfiguration().diff(newConfig))) {
// Since navBar gestural height are different between portrait and landscape,
// can handle orientation changes and refresh navigation gestural region through
// onOneHandedModeChanged()
@@ -1649,11 +1649,11 @@ public class TouchInteractionService extends Service {
pw.println("\tmInputEventReceiver=" + mInputEventReceiver);
DisplayController.INSTANCE.get(this).dump(pw);
pw.println("TouchState:");
BaseDraggingActivity createdOverviewActivity = mOverviewComponentObserver == null ? null
: mOverviewComponentObserver.getActivityInterface().getCreatedContainer();
RecentsViewContainer createdOverviewContainer = mOverviewComponentObserver == null ? null
: mOverviewComponentObserver.getContainerInterface().getCreatedContainer();
boolean resumed = mOverviewComponentObserver != null
&& mOverviewComponentObserver.getActivityInterface().isResumed();
pw.println("\tcreatedOverviewActivity=" + createdOverviewActivity);
&& mOverviewComponentObserver.getContainerInterface().isResumed();
pw.println("\tcreatedOverviewActivity=" + createdOverviewContainer);
pw.println("\tresumed=" + resumed);
pw.println("\tmConsumer=" + mConsumer.getName());
ActiveGestureLog.INSTANCE.dump("", pw);
@@ -1661,8 +1661,8 @@ public class TouchInteractionService extends Service {
if (mTaskAnimationManager != null) {
mTaskAnimationManager.dump("", pw);
}
if (createdOverviewActivity != null) {
createdOverviewActivity.getDeviceProfile().dump(this, "", pw);
if (createdOverviewContainer != null) {
createdOverviewContainer.getDeviceProfile().dump(this, "", pw);
}
mTaskbarManager.dumpLogs("", pw);
mDesktopVisibilityController.dumpLogs("", pw);
@@ -47,9 +47,9 @@ import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.RecentsViewContainer;
/**
* State controller for fallback recents activity
@@ -57,12 +57,12 @@ import com.android.quickstep.views.RecentsView;
public class FallbackRecentsStateController implements StateHandler<RecentsState> {
private final StateAnimationConfig mNoConfig = new StateAnimationConfig();
private final RecentsActivity mActivity;
private final RecentsViewContainer mRecentsViewContainer;
private final FallbackRecentsView mRecentsView;
public FallbackRecentsStateController(RecentsActivity activity) {
mActivity = activity;
mRecentsView = activity.getOverviewPanel();
public FallbackRecentsStateController(RecentsViewContainer container) {
mRecentsViewContainer = container;
mRecentsView = container.getOverviewPanel();
}
@Override
@@ -96,10 +96,10 @@ public class FallbackRecentsStateController implements StateHandler<RecentsState
setter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
clearAllButtonAlpha, LINEAR);
float overviewButtonAlpha = state.hasOverviewActions() ? 1 : 0;
setter.setFloat(mActivity.getActionsView().getVisibilityAlpha(),
setter.setFloat(mRecentsViewContainer.getActionsView().getVisibilityAlpha(),
AnimatedFloat.VALUE, overviewButtonAlpha, LINEAR);
float[] scaleAndOffset = state.getOverviewScaleAndOffset(mActivity);
float[] scaleAndOffset = state.getOverviewScaleAndOffset(mRecentsViewContainer);
setter.setFloat(mRecentsView, RECENTS_SCALE_PROPERTY, scaleAndOffset[0],
config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR));
setter.setFloat(mRecentsView, ADJACENT_PAGE_HORIZONTAL_OFFSET, scaleAndOffset[1],
@@ -110,16 +110,19 @@ public class FallbackRecentsStateController implements StateHandler<RecentsState
setter.setFloat(mRecentsView, TASK_MODALNESS, state.getOverviewModalness(),
config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR));
setter.setFloat(mRecentsView, FULLSCREEN_PROGRESS, state.isFullScreen() ? 1 : 0, LINEAR);
boolean showAsGrid = state.displayOverviewTasksAsGrid(mActivity.getDeviceProfile());
boolean showAsGrid =
state.displayOverviewTasksAsGrid(mRecentsViewContainer.getDeviceProfile());
setter.setFloat(mRecentsView, RECENTS_GRID_PROGRESS, showAsGrid ? 1f : 0f,
getOverviewInterpolator(state));
setter.setFloat(mRecentsView, TASK_THUMBNAIL_SPLASH_ALPHA,
state.showTaskThumbnailSplash() ? 1f : 0f, getOverviewInterpolator(state));
setter.setViewBackgroundColor(mActivity.getScrimView(), state.getScrimColor(mActivity),
setter.setViewBackgroundColor(mRecentsViewContainer.getScrimView(),
state.getScrimColor(mRecentsViewContainer.asContext()),
config.getInterpolator(ANIM_SCRIM_FADE, LINEAR));
if (isSplitSelectionState(state)) {
int duration = state.getTransitionDuration(mActivity, true /* isToState */);
int duration =
state.getTransitionDuration(mRecentsViewContainer.asContext(), true);
// TODO (b/246851887): Pass in setter as a NO_ANIM PendingAnimation instead
PendingAnimation pa = new PendingAnimation(duration);
mRecentsView.createSplitSelectInitAnimation(pa, duration);
@@ -129,7 +132,7 @@ public class FallbackRecentsStateController implements StateHandler<RecentsState
Pair<FloatProperty<RecentsView>, FloatProperty<RecentsView>> taskViewsFloat =
mRecentsView.getPagedOrientationHandler().getSplitSelectTaskOffset(
TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
mActivity.getDeviceProfile());
mRecentsViewContainer.getDeviceProfile());
setter.setFloat(mRecentsView, taskViewsFloat.first, isSplitSelectionState(state)
? mRecentsView.getSplitSelectTranslation() : 0, LINEAR);
setter.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
@@ -38,6 +38,7 @@ import com.android.launcher3.desktop.DesktopRecentsTransitionController;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.statemanager.StatefulContainer;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
import com.android.quickstep.FallbackActivityInterface;
@@ -49,6 +50,7 @@ import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.RecentsViewContainer;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
@@ -56,7 +58,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsState>
public class FallbackRecentsView<CONTAINER_TYPE extends Context & RecentsViewContainer
& StatefulContainer<RecentsState>> extends RecentsView<CONTAINER_TYPE, RecentsState>
implements StateListener<RecentsState> {
private static final int TASK_DISMISS_DURATION = 150;
@@ -93,7 +96,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
}
@Override
public StateManager<RecentsState, RecentsActivity> getStateManager() {
public StateManager<RecentsState, ?> getStateManager() {
return mContainer.getStateManager();
}
@@ -20,13 +20,12 @@ import android.util.AttributeSet;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.views.RecentsViewContainer;
/**
* Drag layer for fallback recents activity
*/
public class RecentsDragLayer extends BaseDragLayer<RecentsActivity> {
public class RecentsDragLayer<T extends Context & RecentsViewContainer> extends BaseDragLayer<T> {
public RecentsDragLayer(Context context, AttributeSet attrs) {
super(context, attrs, 1 /* alphaChannelCount */);
}
@@ -34,8 +33,8 @@ public class RecentsDragLayer extends BaseDragLayer<RecentsActivity> {
@Override
public void recreateControllers() {
mControllers = new TouchController[] {
new RecentsTaskController(mActivity),
new FallbackNavBarTouchController(mActivity),
new RecentsTaskController(mContainer),
new FallbackNavBarTouchController(mContainer),
};
}
}
@@ -15,18 +15,22 @@
*/
package com.android.quickstep.fallback;
import android.content.Context;
import com.android.launcher3.statemanager.StatefulContainer;
import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.views.RecentsViewContainer;
public class RecentsTaskController extends TaskViewTouchController<RecentsActivity> {
public RecentsTaskController(RecentsActivity activity) {
super(activity);
public class RecentsTaskController<T extends Context & RecentsViewContainer &
StatefulContainer<RecentsState>> extends TaskViewTouchController<T> {
public RecentsTaskController(T container) {
super(container);
}
@Override
protected boolean isRecentsInteractive() {
return mContainer.hasWindowFocus() || mContainer.getStateManager().getState().hasLiveTile();
return mContainer.getRootView().hasWindowFocus()
|| mContainer.getStateManager().getState().hasLiveTile();
}
@Override
@@ -17,6 +17,7 @@
package com.android.quickstep.views;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.LocusId;
@@ -31,7 +32,6 @@ import androidx.annotation.Nullable;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.ScrimView;
@@ -54,11 +54,6 @@ public interface RecentsViewContainer extends ActivityContext {
}
}
/**
* Returns {@link SystemUiController} to manage various window flags to control system UI.
*/
SystemUiController getSystemUiController();
/**
* Returns {@link ScrimView}
*/
@@ -95,7 +90,7 @@ public interface RecentsViewContainer extends ActivityContext {
/**
* Returns overview actions view as a view
*/
View getActionsView();
OverviewActionsView getActionsView();
/**
* @see BaseActivity#addForceInvisibleFlag(int)
@@ -143,10 +138,10 @@ public interface RecentsViewContainer extends ActivityContext {
void runOnBindToTouchInteractionService(Runnable r);
/**
* @see Activity#getWindow()
* @return Window
* @see Activity#getComponentName()
* @return ComponentName
*/
Window getWindow();
ComponentName getComponentName();
/**
* @see
@@ -176,6 +171,25 @@ public interface RecentsViewContainer extends ActivityContext {
*/
boolean isRecentsViewVisible();
/**
* Begins transition to start home through container
*/
default void startHome(){
// no op
}
/**
* Checks container to see if we can start home transition safely
*/
boolean canStartHomeSafely();
/**
* Enter staged split directly from the current running app.
* @param leftOrTop if the staged split will be positioned left or top.
*/
default void enterStageSplitFromRunningApp(boolean leftOrTop){}
/**
* Overwrites any logged item in Launcher that doesn't have a container with the
* {@link com.android.launcher3.touch.PagedOrientationHandler} in use for Overview.
@@ -30,7 +30,7 @@ import org.mockito.Mock;
public class FallbackSwipeHandlerTestCase extends AbsSwipeUpHandlerTestCase<
RecentsActivity,
RecentsState,
FallbackRecentsView,
FallbackRecentsView<RecentsActivity>,
RecentsActivity,
FallbackActivityInterface,
FallbackSwipeHandler> {
@@ -11,6 +11,7 @@ import android.view.WindowInsets;
import com.android.launcher3.graphics.SysUiScrim;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.statemanager.StatefulContainer;
import com.android.launcher3.util.window.WindowManagerProxy;
import java.util.Collections;
@@ -20,7 +21,7 @@ public class LauncherRootView extends InsettableFrameLayout {
private final Rect mTempRect = new Rect();
private final StatefulActivity mActivity;
private final StatefulContainer mStatefulContainer;
@ViewDebug.ExportedProperty(category = "launcher")
private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
@@ -36,24 +37,25 @@ public class LauncherRootView extends InsettableFrameLayout {
public LauncherRootView(Context context, AttributeSet attrs) {
super(context, attrs);
mActivity = StatefulActivity.fromContext(context);
mStatefulContainer = StatefulContainer.fromContext(context);
mSysUiScrim = new SysUiScrim(this);
}
private void handleSystemWindowInsets(Rect insets) {
// Update device profile before notifying the children.
mActivity.getDeviceProfile().updateInsets(insets);
mStatefulContainer.getDeviceProfile().updateInsets(insets);
boolean resetState = !insets.equals(mInsets);
setInsets(insets);
if (resetState) {
mActivity.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
mStatefulContainer.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
}
}
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
mActivity.handleConfigurationChanged(mActivity.getResources().getConfiguration());
mStatefulContainer.handleConfigurationChanged(
mStatefulContainer.getContext().getResources().getConfiguration());
insets = WindowManagerProxy.INSTANCE.get(getContext())
.normalizeWindowInsets(getContext(), insets, mTempRect);
@@ -72,7 +74,7 @@ public class LauncherRootView extends InsettableFrameLayout {
}
public void dispatchInsets() {
mActivity.getDeviceProfile().updateInsets(mInsets);
mStatefulContainer.getDeviceProfile().updateInsets(mInsets);
super.setInsets(mInsets);
}
@@ -121,7 +121,7 @@ public class DragLayer extends BaseDragLayer<Launcher> implements LauncherOverla
@Override
public void recreateControllers() {
mControllers = mActivity.createTouchControllers();
mControllers = mContainer.createTouchControllers();
}
public ViewGroupFocusHelper getFocusIndicatorHelper() {
@@ -134,15 +134,15 @@ public class DragLayer extends BaseDragLayer<Launcher> implements LauncherOverla
}
private boolean isEventOverAccessibleDropTargetBar(MotionEvent ev) {
return isInAccessibleDrag() && isEventOverView(mActivity.getDropTargetBar(), ev);
return isInAccessibleDrag() && isEventOverView(mContainer.getDropTargetBar(), ev);
}
@Override
public boolean onInterceptHoverEvent(MotionEvent ev) {
if (mActivity == null || mActivity.getWorkspace() == null) {
if (mContainer == null || mContainer.getWorkspace() == null) {
return false;
}
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mContainer);
if (!(topView instanceof Folder)) {
return false;
} else {
@@ -197,7 +197,7 @@ public class DragLayer extends BaseDragLayer<Launcher> implements LauncherOverla
private boolean isInAccessibleDrag() {
return mActivity.getAccessibilityDelegate().isInAccessibleDrag();
return mContainer.getAccessibilityDelegate().isInAccessibleDrag();
}
@Override
@@ -210,12 +210,12 @@ public class DragLayer extends BaseDragLayer<Launcher> implements LauncherOverla
@Override
public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
View topView = AbstractFloatingView.getTopOpenViewWithType(mActivity,
View topView = AbstractFloatingView.getTopOpenViewWithType(mContainer,
AbstractFloatingView.TYPE_ACCESSIBLE);
if (topView != null) {
addAccessibleChildToList(topView, childrenForAccessibility);
if (isInAccessibleDrag()) {
addAccessibleChildToList(mActivity.getDropTargetBar(), childrenForAccessibility);
addAccessibleChildToList(mContainer.getDropTargetBar(), childrenForAccessibility);
}
} else {
super.addChildrenForAccessibility(childrenForAccessibility);
@@ -420,14 +420,14 @@ public class DragLayer extends BaseDragLayer<Launcher> implements LauncherOverla
public void onViewAdded(View child) {
super.onViewAdded(child);
updateChildIndices();
mActivity.onDragLayerHierarchyChanged();
mContainer.onDragLayerHierarchyChanged();
}
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
updateChildIndices();
mActivity.onDragLayerHierarchyChanged();
mContainer.onDragLayerHierarchyChanged();
}
@Override
@@ -32,10 +32,10 @@ import android.view.View;
import androidx.annotation.ColorInt;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.statemanager.StatefulContainer;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.ScreenOnTracker;
import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener;
@@ -84,7 +84,7 @@ public class SysUiScrim implements View.OnAttachStateChangeListener {
private final int mBottomMaskHeight;
private final View mRoot;
private final BaseDraggingActivity mActivity;
private final StatefulContainer mContainer;
private final boolean mHideSysUiScrim;
private boolean mSkipScrimAnimationForTest = false;
@@ -94,8 +94,8 @@ public class SysUiScrim implements View.OnAttachStateChangeListener {
public SysUiScrim(View view) {
mRoot = view;
mActivity = BaseDraggingActivity.fromContext(view.getContext());
DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
mContainer = StatefulContainer.fromContext(view.getContext());
DisplayMetrics dm = mContainer.getContext().getResources().getDisplayMetrics();
mTopMaskHeight = ResourceUtils.pxFromDp(TOP_MASK_HEIGHT_DP, dm);
mBottomMaskHeight = ResourceUtils.pxFromDp(BOTTOM_MASK_HEIGHT_DP, dm);
@@ -130,7 +130,7 @@ public class SysUiScrim implements View.OnAttachStateChangeListener {
ObjectAnimator oa = mSysUiAnimMultiplier.animateToValue(1);
oa.setDuration(600);
oa.setStartDelay(mActivity.getWindow().getTransitionBackgroundFadeDuration());
oa.setStartDelay(mContainer.getWindow().getTransitionBackgroundFadeDuration());
oa.start();
mAnimateScrimOnNextDraw = false;
}
@@ -166,19 +166,19 @@ public class SysUiScrim implements View.OnAttachStateChangeListener {
* horizontal
*/
public void onInsetsChanged(Rect insets) {
DeviceProfile dp = mActivity.getDeviceProfile();
DeviceProfile dp = mContainer.getDeviceProfile();
mDrawTopScrim = insets.top > 0;
mDrawBottomScrim = !dp.isVerticalBarLayout() && !dp.isGestureMode && !dp.isTaskbarPresent;
}
@Override
public void onViewAttachedToWindow(View view) {
ScreenOnTracker.INSTANCE.get(mActivity).addListener(mScreenOnListener);
ScreenOnTracker.INSTANCE.get(mContainer.getContext()).addListener(mScreenOnListener);
}
@Override
public void onViewDetachedFromWindow(View view) {
ScreenOnTracker.INSTANCE.get(mActivity).removeListener(mScreenOnListener);
ScreenOnTracker.INSTANCE.get(mContainer.getContext()).removeListener(mScreenOnListener);
}
/**
@@ -213,7 +213,7 @@ public class SysUiScrim implements View.OnAttachStateChangeListener {
}
private Bitmap createDitheredAlphaMask(int height, @ColorInt int[] colors, float[] positions) {
DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
DisplayMetrics dm = mContainer.getContext().getResources().getDisplayMetrics();
int width = ResourceUtils.pxFromDp(ALPHA_MASK_BITMAP_WIDTH_DP, dm);
Bitmap dst = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Canvas c = new Canvas(dst);
@@ -65,7 +65,7 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
@Override
public void recreateControllers() {
mControllers = new TouchController[]{new CloseAllAppsTouchController(),
mActivity.getDragController()};
mContainer.getDragController()};
}
/**
@@ -79,10 +79,10 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
mAppsView = findViewById(R.id.apps_view);
// Setup workspace
mWorkspace = findViewById(R.id.workspace_grid);
mPinnedAppsAdapter = new PinnedAppsAdapter(mActivity, mAppsView.getAppsStore(),
mPinnedAppsAdapter = new PinnedAppsAdapter(mContainer, mAppsView.getAppsStore(),
this::onIconLongClicked);
mWorkspace.setAdapter(mPinnedAppsAdapter);
mWorkspace.setNumColumns(mActivity.getDeviceProfile().inv.numColumns);
mWorkspace.setNumColumns(mContainer.getDeviceProfile().inv.numColumns);
}
/**
@@ -112,7 +112,7 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
DeviceProfile grid = mActivity.getDeviceProfile();
DeviceProfile grid = mContainer.getDeviceProfile();
int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
@@ -153,17 +153,17 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
if (!mActivity.isAppDrawerShown()) {
if (!mContainer.isAppDrawerShown()) {
return false;
}
if (AbstractFloatingView.getTopOpenView(mActivity) != null) {
if (AbstractFloatingView.getTopOpenView(mContainer) != null) {
return false;
}
if (ev.getAction() == MotionEvent.ACTION_DOWN
&& !isEventOverView(mActivity.getAppsView(), ev)) {
mActivity.showAppDrawer(false);
&& !isEventOverView(mContainer.getAppsView(), ev)) {
mContainer.showAppDrawer(false);
return true;
}
return false;
@@ -178,7 +178,7 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
if (!(v instanceof BubbleTextView)) {
return false;
}
if (PopupContainerWithArrow.getOpen(mActivity) != null) {
if (PopupContainerWithArrow.getOpen(mContainer) != null) {
// There is already an items container open, so don't open this one.
v.clearFocus();
return false;
@@ -187,32 +187,32 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
if (!ShortcutUtil.supportsShortcuts(item)) {
return false;
}
PopupDataProvider popupDataProvider = mActivity.getPopupDataProvider();
PopupDataProvider popupDataProvider = mContainer.getPopupDataProvider();
if (popupDataProvider == null) {
return false;
}
// order of this list will reflect in the popup
List<SystemShortcut> systemShortcuts = new ArrayList<>();
systemShortcuts.add(APP_INFO.getShortcut(mActivity, item, v));
systemShortcuts.add(APP_INFO.getShortcut(mContainer, item, v));
// Hide redundant pin shortcut for app drawer icons if drag-n-drop is enabled.
if (!FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.get() || !mActivity.isAppDrawerShown()) {
if (!FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.get() || !mContainer.isAppDrawerShown()) {
systemShortcuts.add(mPinnedAppsAdapter.getSystemShortcut(item, v));
}
int deepShortcutCount = popupDataProvider.getShortcutCountForItem(item);
final PopupContainerWithArrow<SecondaryDisplayLauncher> container;
container = (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
R.layout.popup_container, mActivity.getDragLayer(), false);
container = (PopupContainerWithArrow) mContainer.getLayoutInflater().inflate(
R.layout.popup_container, mContainer.getDragLayer(), false);
container.populateAndShowRows((BubbleTextView) v, deepShortcutCount,
systemShortcuts);
container.requestFocus();
if (!FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.get() || !mActivity.isAppDrawerShown()) {
if (!FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.get() || !mContainer.isAppDrawerShown()) {
return true;
}
DragOptions options = new DragOptions();
DeviceProfile grid = mActivity.getDeviceProfile();
DeviceProfile grid = mContainer.getDeviceProfile();
options.intrinsicIconScaleFactor = (float) grid.allAppsIconSizePx / grid.iconSizePx;
options.preDragCondition = container.createPreDragCondition(false);
if (options.preDragCondition == null) {
@@ -229,7 +229,7 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
mDragView = dragObject.dragView;
if (!shouldStartDrag(0)) {
mDragView.setOnScaleAnimEndCallback(() ->
mActivity.beginDragShared(v, mActivity.getAppsView(), options));
mContainer.beginDragShared(v, mContainer.getAppsView(), options));
}
}
@@ -239,7 +239,7 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
}
};
}
mActivity.beginDragShared(v, mActivity.getAppsView(), options);
mContainer.beginDragShared(v, mContainer.getAppsView(), options);
return true;
}
}
@@ -20,6 +20,7 @@ import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
import static com.android.launcher3.LauncherState.FLAG_NON_INTERACTIVE;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
@@ -195,15 +196,15 @@ public abstract class StatefulActivity<STATE_TYPE extends BaseState<STATE_TYPE>>
mOldRotation = rotation;
}
@Override
public Context getContext() {
return this;
}
/**
* Logic for when device configuration changes (rotation, screen size change, multi-window,
* etc.)
*/
protected abstract void onHandleConfigurationChanged();
/**
* Enter staged split directly from the current running app.
* @param leftOrTop if the staged split will be positioned left or top.
*/
public void enterStageSplitFromRunningApp(boolean leftOrTop) { }
}
@@ -20,6 +20,12 @@ package com.android.launcher3.statemanager;
import static com.android.launcher3.LauncherState.FLAG_CLOSE_POPUPS;
import static com.android.launcher3.statemanager.BaseState.FLAG_NON_INTERACTIVE;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.view.Window;
import androidx.annotation.CallSuper;
import com.android.launcher3.AbstractFloatingView;
@@ -35,6 +41,23 @@ import java.util.List;
public interface StatefulContainer<STATE_TYPE extends BaseState<STATE_TYPE>> extends
ActivityContext {
/**
* Returns an instance of an implementation of StatefulContainer
*
* @param context will find instance of StatefulContainer from given context.
*/
static <T extends StatefulContainer> T fromContext(Context context) {
if (context instanceof StatefulContainer) {
return (T) context;
} else if (context instanceof ContextWrapper) {
return fromContext(((ContextWrapper) context).getBaseContext());
} else {
throw new IllegalArgumentException("Cannot find StatefulContainer in parent tree");
}
}
Context getContext();
/**
* Creates a factory for atomic state animations
*/
@@ -54,12 +77,15 @@ public interface StatefulContainer<STATE_TYPE extends BaseState<STATE_TYPE>> ext
/**
* Called when transition to state ends
*
* @param state current state of State_Type
*/
default void onStateSetEnd(STATE_TYPE state) { }
default void onStateSetEnd(STATE_TYPE state) {
}
/**
* Called when transition to state starts
*
* @param state current state of State_Type
*/
@CallSuper
@@ -71,6 +97,7 @@ public interface StatefulContainer<STATE_TYPE extends BaseState<STATE_TYPE>> ext
/**
* Returns true if the activity is in the provided state
*
* @param state current state of State_Type
*/
default boolean isInState(STATE_TYPE state) {
@@ -81,4 +108,8 @@ public interface StatefulContainer<STATE_TYPE extends BaseState<STATE_TYPE>> ext
* Returns true if state change should transition with animation
*/
boolean shouldAnimateStateChange();
default void handleConfigurationChanged(Configuration configuration){
//no op
}
}
@@ -168,21 +168,14 @@ public class TestInformationHandler implements ResourceBasedOverride {
}
case TestProtocol.REQUEST_TARGET_INSETS: {
return getUIProperty(Bundle::putParcelable, activity -> {
WindowInsets insets = activity.getWindow()
.getDecorView().getRootWindowInsets();
return Insets.max(
insets.getSystemGestureInsets(),
insets.getSystemWindowInsets());
}, this::getCurrentActivity);
return getUIProperty(Bundle::putParcelable, insets -> Insets.max(
insets.getSystemGestureInsets(),
insets.getSystemWindowInsets()), this::getWindowInsets);
}
case TestProtocol.REQUEST_WINDOW_INSETS: {
return getUIProperty(Bundle::putParcelable, activity -> {
WindowInsets insets = activity.getWindow()
.getDecorView().getRootWindowInsets();
return insets.getSystemWindowInsets();
}, this::getCurrentActivity);
return getUIProperty(Bundle::putParcelable,
WindowInsets::getSystemWindowInsets, this::getWindowInsets);
}
case TestProtocol.REQUEST_CELL_LAYOUT_BOARDER_HEIGHT: {
@@ -192,13 +185,13 @@ public class TestInformationHandler implements ResourceBasedOverride {
}
case TestProtocol.REQUEST_SYSTEM_GESTURE_REGION: {
return getUIProperty(Bundle::putParcelable, activity -> {
WindowInsetsCompat insets = WindowInsetsCompat.toWindowInsetsCompat(
activity.getWindow().getDecorView().getRootWindowInsets());
return getUIProperty(Bundle::putParcelable, windowInsets -> {
WindowInsetsCompat insets =
WindowInsetsCompat.toWindowInsetsCompat(windowInsets);
return insets.getInsets(WindowInsetsCompat.Type.ime()
| WindowInsetsCompat.Type.systemGestures())
.toPlatformInsets();
}, this::getCurrentActivity);
}, this::getWindowInsets);
}
case TestProtocol.REQUEST_ICON_HEIGHT: {
@@ -486,8 +479,9 @@ public class TestInformationHandler implements ResourceBasedOverride {
|| LauncherAppState.getInstance(mContext).getModel().isModelLoaded();
}
protected Activity getCurrentActivity() {
return Launcher.ACTIVITY_TRACKER.getCreatedActivity();
protected WindowInsets getWindowInsets(){
return Launcher.ACTIVITY_TRACKER.getCreatedActivity().getWindow().getDecorView()
.getRootWindowInsets();
}
/**
@@ -26,6 +26,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
@@ -46,6 +47,7 @@ import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.AccessibilityDelegate;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.view.inputmethod.InputMethodManager;
@@ -80,6 +82,7 @@ import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;
@@ -172,7 +175,16 @@ public interface ActivityContext {
/**
* The root view to support drag-and-drop and popup support.
*/
BaseDragLayer getDragLayer();
BaseDragLayer<?> getDragLayer();
/**
* @see Activity#getWindow()
* @return Window
*/
@Nullable
default Window getWindow() {
return null;
}
/**
* The all apps container, if it exists in this context.
@@ -216,6 +228,11 @@ public interface ActivityContext {
return null;
}
@Nullable
default SystemUiController getSystemUiController() {
return null;
}
/**
* Handler for actions taken on drop targets that require launcher
*/
@@ -107,7 +107,7 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
protected final RectF mSystemGestureRegion = new RectF();
private int mTouchDispatchState = 0;
protected final T mActivity;
protected final T mContainer;
private final MultiValueAlpha mMultiValueAlpha;
// All the touch controllers for the view
@@ -121,7 +121,7 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
public BaseDragLayer(Context context, AttributeSet attrs, int alphaChannelCount) {
super(context, attrs);
mActivity = ActivityContext.lookupContext(context);
mContainer = ActivityContext.lookupContext(context);
mMultiValueAlpha = new MultiValueAlpha(this, alphaChannelCount);
}
@@ -159,7 +159,7 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
}
mTouchCompleteListener = null;
} else if (action == MotionEvent.ACTION_DOWN) {
mActivity.finishAutoCancelActionMode();
mContainer.finishAutoCancelActionMode();
}
return findActiveController(ev);
}
@@ -173,7 +173,7 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
}
private TouchController findControllerToHandleTouch(MotionEvent ev) {
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mContainer);
if (topView != null
&& (isEventWithinSystemGestureRegion(ev)
|| topView.canInterceptEventsInSystemGestureRegion())
@@ -207,7 +207,7 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
@Override
public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
// Shortcuts can appear above folder
View topView = AbstractFloatingView.getTopOpenViewWithType(mActivity,
View topView = AbstractFloatingView.getTopOpenViewWithType(mContainer,
AbstractFloatingView.TYPE_ACCESSIBLE);
if (topView != null) {
if (child == topView) {
@@ -222,7 +222,7 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
@Override
public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
View topView = AbstractFloatingView.getTopOpenViewWithType(mActivity,
View topView = AbstractFloatingView.getTopOpenViewWithType(mContainer,
AbstractFloatingView.TYPE_ACCESSIBLE);
if (topView != null) {
// Only add the top view as a child for accessibility when it is open
@@ -458,7 +458,7 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
View topView = AbstractFloatingView.getTopOpenView(mActivity);
View topView = AbstractFloatingView.getTopOpenView(mContainer);
if (topView != null) {
return topView.requestFocus(direction, previouslyFocusedRect);
} else {
@@ -468,7 +468,7 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
@Override
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
View topView = AbstractFloatingView.getTopOpenView(mActivity);
View topView = AbstractFloatingView.getTopOpenView(mContainer);
if (topView != null) {
topView.addFocusables(views, direction);
} else {
@@ -555,7 +555,7 @@ public abstract class BaseDragLayer<T extends Context & ActivityContext>
Insets gestureInsets = insets.getMandatorySystemGestureInsets();
int gestureInsetBottom = gestureInsets.bottom;
Insets imeInset = insets.getInsets(WindowInsets.Type.ime());
DeviceProfile dp = mActivity.getDeviceProfile();
DeviceProfile dp = mContainer.getDeviceProfile();
if (dp.isTaskbarPresent) {
// Ignore taskbar gesture insets to avoid interfering with TouchControllers.
gestureInsetBottom = ResourceUtils.getNavbarSize(
@@ -29,7 +29,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Px;
import androidx.core.graphics.ColorUtils;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.Insettable;
import com.android.launcher3.util.SystemUiController;
@@ -143,7 +142,8 @@ public class ScrimView extends View implements Insettable {
private SystemUiController getSystemUiController() {
if (mSystemUiController == null) {
mSystemUiController = BaseActivity.fromContext(getContext()).getSystemUiController();
mSystemUiController =
ActivityContext.lookupContext(getContext()).getSystemUiController();
}
return mSystemUiController;
}