Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0f5db4a authored by Hyunyoung Song's avatar Hyunyoung Song
Browse files

Merging ub-launcher3-qt-r1-dev, build 5710902

Test: Manual

Bug:115582915 P2 [Testing] Make all launcher tests gesture-stable
Bug:127350205 P1 Ensure that Launcher is always created and is in right configuration
Bug:131116002 P2 Convert tests to TAPL and enable them
Bug:131356741 P1 use transferFocus to implement SWIPE DOWN on homescreen to open noti shade
Bug:133891845 P2 TAPL: need clearer diags when a crash dialog is over Launcher or there is lock screeen
Bug:136215685 P1 Flake: swiping up from Home to Overview in 2-button mode sometimes fails
Bug:136278866 P2 Temporary workarounds to make tests pass on Cuttlefish
Bug:136280872 P1 Flake: Flinging in all apps opens workspace
Bug:64712476 P3 Import translations for dev branches
Change-Id: I39841b30840e9d88a2b98b21c4aba1c44d2bc446
parents e303383f 70697e48
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -164,7 +164,7 @@ public abstract class RecentsUiFactory {
            }
        }

        if (FeatureFlags.PULL_DOWN_STATUS_BAR && Utilities.IS_DEBUG_DEVICE
        if (FeatureFlags.PULL_DOWN_STATUS_BAR
                && !launcher.getDeviceProfile().isMultiWindowMode
                && !launcher.getDeviceProfile().isVerticalBarLayout()) {
            list.add(new StatusBarTouchController(launcher));
+57 −0
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Region;
@@ -74,6 +76,8 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.logging.EventLogArray;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.SysUINavigationMode.Mode;
@@ -91,6 +95,7 @@ import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -152,6 +157,7 @@ public class TouchInteractionService extends Service implements
                    .asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
            MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
            MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
            MAIN_THREAD_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
        }

        @Override
@@ -502,6 +508,9 @@ public class TouchInteractionService extends Service implements
    }

    private void onInputEvent(InputEvent ev) {
        if (TestProtocol.sDebugTracing) {
            Log.d(TestProtocol.EVENTS_TO_OVERVIEW_MISSING_TAG, "onInputEvent " + ev);
        }
        if (!(ev instanceof MotionEvent)) {
            Log.e(TAG, "Unknown event " + ev);
            return;
@@ -684,6 +693,54 @@ public class TouchInteractionService extends Service implements
        }
    }

    private void preloadOverview(boolean fromInit) {
        if (!mIsUserUnlocked) {
            return;
        }

        final ActivityControlHelper<BaseDraggingActivity> activityControl =
                mOverviewComponentObserver.getActivityControlHelper();
        if (activityControl.getCreatedActivity() == null) {
            // Make sure that UI states will be initialized.
            activityControl.createActivityInitListener((activity, wasVisible) -> {
                AppLaunchTracker.INSTANCE.get(activity);
                return false;
            }).register();
        } else if (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.
            return;
        }

        // Pass null animation handler to indicate this start is preload.
        BackgroundExecutor.get().submit(
                () -> ActivityManagerWrapper.getInstance().startRecentsActivity(
                        mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(),
                        null /* assistDataReceiver */, null /* animationHandler */,
                        null /* resultCallback */, null /* resultCallbackHandler */));
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        if (!mIsUserUnlocked) {
            return;
        }
        final ActivityControlHelper activityControl =
                mOverviewComponentObserver.getActivityControlHelper();
        final BaseDraggingActivity activity = activityControl.getCreatedActivity();
        if (activity == null || activity.isStarted()) {
            // We only care about the existing background activity.
            return;
        }
        if (mOverviewComponentObserver.canHandleConfigChanges(activity.getComponentName(),
                activity.getResources().getConfiguration().diff(newConfig))) {
            return;
        }

        preloadOverview(false /* fromInit */);
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs) {
        if (rawArgs.length > 0 && Utilities.IS_DEBUG_DEVICE) {
+5 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;

import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;

@@ -26,6 +27,7 @@ import androidx.annotation.Nullable;

import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.Utilities;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.OverviewCallbacks;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -80,6 +82,9 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity>

    @Override
    public void onMotionEvent(MotionEvent ev) {
        if (TestProtocol.sDebugTracing) {
            Log.d(TestProtocol.EVENTS_TO_OVERVIEW_MISSING_TAG, "onMotionEvent " + ev);
        }
        if (!mProxyTouch) {
            return;
        }
+51 −17
Original line number Diff line number Diff line
@@ -17,17 +17,22 @@ package com.android.launcher3.uioverrides.touchcontrollers;

import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.ACTION_CANCEL;

import android.graphics.PointF;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowManager;

import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.touch.TouchEventTranslator;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.RecentsModel;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -36,18 +41,29 @@ import java.io.PrintWriter;

/**
 * TouchController for handling touch events that get sent to the StatusBar. Once the
 * Once the event delta y passes the touch slop, the events start getting forwarded.
 * Once the event delta mDownY passes the touch slop, the events start getting forwarded.
 * All events are offset by initial Y value of the pointer.
 */
public class StatusBarTouchController implements TouchController {

    private static final String TAG = "StatusBarController";

    /**
     * Window flag: Enable touches to slide out of a window into neighboring
     * windows in mid-gesture instead of being captured for the duration of
     * the gesture.
     *
     * This flag changes the behavior of touch focus for this window only.
     * Touches can slide out of the window but they cannot necessarily slide
     * back in (unless the other window with touch focus permits it).
     */
    private static final int FLAG_SLIPPERY = 0x20000000;

    protected final Launcher mLauncher;
    protected final TouchEventTranslator mTranslator;
    private final float mTouchSlop;
    private ISystemUiProxy mSysUiProxy;
    private int mLastAction;
    private final SparseArray<PointF> mDownEvents;

    /* If {@code false}, this controller should not handle the input {@link MotionEvent}.*/
    private boolean mCanIntercept;
@@ -56,7 +72,7 @@ public class StatusBarTouchController implements TouchController {
        mLauncher = l;
        // Guard against TAPs by increasing the touch slop.
        mTouchSlop = 2 * ViewConfiguration.get(l).getScaledTouchSlop();
        mTranslator = new TouchEventTranslator((MotionEvent ev)-> dispatchTouchEvent(ev));
        mDownEvents = new SparseArray<>();
    }

    @Override
@@ -64,7 +80,6 @@ public class StatusBarTouchController implements TouchController {
        writer.println(prefix + "mCanIntercept:" + mCanIntercept);
        writer.println(prefix + "mLastAction:" + MotionEvent.actionToString(mLastAction));
        writer.println(prefix + "mSysUiProxy available:" + (mSysUiProxy != null));

    }

    private void dispatchTouchEvent(MotionEvent ev) {
@@ -81,26 +96,31 @@ public class StatusBarTouchController implements TouchController {
    @Override
    public final boolean onControllerInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getActionMasked();
        int idx = ev.getActionIndex();
        int pid = ev.getPointerId(idx);
        if (action == ACTION_DOWN) {
            mCanIntercept = canInterceptTouch(ev);
            if (!mCanIntercept) {
                return false;
            }
            mTranslator.reset();
            mTranslator.setDownParameters(0, ev);
            mDownEvents.put(pid, new PointF(ev.getX(), ev.getY()));
        } else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
           // Check!! should only set it only when threshold is not entered.
            mTranslator.setDownParameters(ev.getActionIndex(), ev);
           mDownEvents.put(pid, new PointF(ev.getX(idx), ev.getY(idx)));
        }
        if (!mCanIntercept) {
            return false;
        }
        if (action == ACTION_MOVE) {
            float dy = ev.getY() - mTranslator.getDownY();
            float dx = ev.getX() - mTranslator.getDownX();
            if (dy > mTouchSlop && dy > Math.abs(dx)) {
                mTranslator.dispatchDownEvents(ev);
                mTranslator.processMotionEvent(ev);
            float dy = ev.getY(idx) - mDownEvents.get(pid).y;
            float dx = ev.getX(idx) - mDownEvents.get(pid).x;
            // Currently input dispatcher will not do touch transfer if there are more than
            // one touch pointer. Hence, even if slope passed, only set the slippery flag
            // when there is single touch event. (context: InputDispatcher.cpp line 1445)
            if (dy > mTouchSlop && dy > Math.abs(dx) && ev.getPointerCount() == 1) {
                ev.setAction(ACTION_DOWN);
                dispatchTouchEvent(ev);
                setWindowSlippery(true);
                return true;
            }
            if (Math.abs(dx) > mTouchSlop) {
@@ -110,12 +130,26 @@ public class StatusBarTouchController implements TouchController {
        return false;
    }


    @Override
    public final boolean onControllerTouchEvent(MotionEvent ev) {
        mTranslator.processMotionEvent(ev);
        if (ev.getAction() == ACTION_UP || ev.getAction() == ACTION_CANCEL) {
            dispatchTouchEvent(ev);
            setWindowSlippery(false);
            return true;
        }
        return true;
    }

    private void setWindowSlippery(boolean enable) {
        Window w = mLauncher.getWindow();
        WindowManager.LayoutParams wlp = w.getAttributes();
        if (enable) {
            wlp.flags |= FLAG_SLIPPERY;
        } else {
            wlp.flags &= ~FLAG_SLIPPERY;
        }
        w.setAttributes(wlp);
    }

    private boolean canInterceptTouch(MotionEvent ev) {
        if (!mLauncher.isInState(LauncherState.NORMAL) ||
+63 −28
Original line number Diff line number Diff line
@@ -29,11 +29,15 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.util.SparseIntArray;

import com.android.systemui.shared.system.PackageManagerWrapper;

import java.util.ArrayList;
import java.util.Objects;

/**
 * Class to keep track of the current overview component based off user preferences and app updates
@@ -53,22 +57,41 @@ public final class OverviewComponentObserver {
        }
    };
    private final Context mContext;
    private final ComponentName mMyHomeComponent;
    private final Intent mCurrentHomeIntent;
    private final Intent mMyHomeIntent;
    private final Intent mFallbackIntent;
    private final SparseIntArray mConfigChangesMap = new SparseIntArray();
    private String mUpdateRegisteredPackage;
    private ActivityControlHelper mActivityControlHelper;
    private Intent mOverviewIntent;
    private Intent mHomeIntent;
    private int mSystemUiStateFlags;
    private boolean mIsHomeAndOverviewSame;
    private boolean mIsDefaultHome;

    public OverviewComponentObserver(Context context) {
        mContext = context;

        Intent myHomeIntent = new Intent(Intent.ACTION_MAIN)
        mCurrentHomeIntent = new Intent(Intent.ACTION_MAIN)
                .addCategory(Intent.CATEGORY_HOME)
                .setPackage(mContext.getPackageName());
        ResolveInfo info = context.getPackageManager().resolveActivity(myHomeIntent, 0);
        mMyHomeComponent = new ComponentName(context.getPackageName(), info.activityInfo.name);
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mMyHomeIntent = new Intent(mCurrentHomeIntent).setPackage(mContext.getPackageName());
        ResolveInfo info = context.getPackageManager().resolveActivity(mMyHomeIntent, 0);
        ComponentName myHomeComponent =
                new ComponentName(context.getPackageName(), info.activityInfo.name);
        mMyHomeIntent.setComponent(myHomeComponent);
        mConfigChangesMap.append(myHomeComponent.hashCode(), info.activityInfo.configChanges);

        ComponentName fallbackComponent = new ComponentName(mContext, RecentsActivity.class);
        mFallbackIntent = new Intent(Intent.ACTION_MAIN)
                .addCategory(Intent.CATEGORY_DEFAULT)
                .setComponent(fallbackComponent)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        try {
            ActivityInfo fallbackInfo = context.getPackageManager().getActivityInfo(
                    mFallbackIntent.getComponent(), 0 /* flags */);
            mConfigChangesMap.append(fallbackComponent.hashCode(), fallbackInfo.configChanges);
        } catch (PackageManager.NameNotFoundException ignored) { /* Impossible */ }

        mContext.registerReceiver(mUserPreferenceChangeReceiver,
                new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED));
@@ -92,17 +115,14 @@ public final class OverviewComponentObserver {
        ComponentName defaultHome = PackageManagerWrapper.getInstance()
                .getHomeActivities(new ArrayList<>());

        final String overviewIntentCategory;
        ComponentName overviewComponent;
        mHomeIntent = null;

        if ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 &&
                (defaultHome == null || mMyHomeComponent.equals(defaultHome))) {
        mIsDefaultHome = Objects.equals(mMyHomeIntent.getComponent(), defaultHome);
        if ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0
                && (defaultHome == null || mIsDefaultHome)) {
            // User default home is same as out home app. Use Overview integrated in Launcher.
            overviewComponent = mMyHomeComponent;
            mActivityControlHelper = new LauncherActivityControllerHelper();
            mIsHomeAndOverviewSame = true;
            overviewIntentCategory = Intent.CATEGORY_HOME;
            mOverviewIntent = mMyHomeIntent;
            mCurrentHomeIntent.setComponent(mMyHomeIntent.getComponent());

            if (mUpdateRegisteredPackage != null) {
                // Remove any update listener as we don't care about other packages.
@@ -111,14 +131,11 @@ public final class OverviewComponentObserver {
            }
        } else {
            // The default home app is a different launcher. Use the fallback Overview instead.
            overviewComponent = new ComponentName(mContext, RecentsActivity.class);
            mActivityControlHelper = new FallbackActivityControllerHelper();
            mIsHomeAndOverviewSame = false;
            overviewIntentCategory = Intent.CATEGORY_DEFAULT;
            mOverviewIntent = mFallbackIntent;
            mCurrentHomeIntent.setComponent(defaultHome);

            mHomeIntent = new Intent(Intent.ACTION_MAIN)
                    .addCategory(Intent.CATEGORY_HOME)
                    .setComponent(defaultHome);
            // User's default home app can change as a result of package updates of this app (such
            // as uninstalling the app or removing the "Launcher" feature in an update).
            // Listen for package updates of this app (and remove any previously attached
@@ -138,14 +155,6 @@ public final class OverviewComponentObserver {
                        ACTION_PACKAGE_REMOVED));
            }
        }

        mOverviewIntent = new Intent(Intent.ACTION_MAIN)
                .addCategory(overviewIntentCategory)
                .setComponent(overviewComponent)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (mHomeIntent == null) {
            mHomeIntent = mOverviewIntent;
        }
    }

    /**
@@ -160,6 +169,32 @@ public final class OverviewComponentObserver {
        }
    }

    /**
     * @return {@code true} if the overview component is able to handle the configuration changes.
     */
    boolean canHandleConfigChanges(ComponentName component, int changes) {
        final int orientationChange =
                ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_SCREEN_SIZE;
        if ((changes & orientationChange) == orientationChange) {
            // This is just an approximate guess for simple orientation change because the changes
            // may contain non-public bits (e.g. window configuration).
            return true;
        }

        int configMask = mConfigChangesMap.get(component.hashCode());
        return configMask != 0 && (~configMask & changes) == 0;
    }

    /**
     * Get the intent for overview activity. It is used when lockscreen is shown and home was died
     * in background, we still want to restart the one that will be used after unlock.
     *
     * @return the overview intent
     */
    Intent getOverviewIntentIgnoreSysUiState() {
        return mIsDefaultHome ? mMyHomeIntent : mOverviewIntent;
    }

    /**
     * Get the current intent for going to the overview activity.
     *
@@ -173,7 +208,7 @@ public final class OverviewComponentObserver {
     * Get the current intent for going to the home activity.
     */
    public Intent getHomeIntent() {
        return mHomeIntent;
        return mCurrentHomeIntent;
    }

    /**
Loading