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

Commit 1461f48e authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Merging ub-launcher3-qt-dev, build 5662436

Test: Manual

Bug:109954539 P4 Clock widget is not adaptively changing color based on wallpaper
Bug:122345781 P1 Inflation happens and a binder call during swipe up gesture, that may cause jank
Bug:130687624 P1 [B1C1][B4S4][QT][CTS-Verifier]OTHER-Screen Pinning Test
Bug:131698448 P2 Launcher makes a binder call to check Keygaurd.isDeviceLocked
Bug:132900132 P1 Apparently, tests start running while provisioning is still in progress
Bug:132906035 P1 [Metrics] add Home / Back button events even when Launcher is in the background
Bug:132915522 P1 Snap the window to the bottom if touch Y is below a threshold
Bug:133867119 P2 Lab-only flake: want to switch from workspace to all apps; Swipe failed to receive an event for the swipe end
Bug:134172603 P1 Tracing for lab-only flakes
Bug:135130011 P1 16ms delay when opening app due to dynamic icon loading
Bug:135214165 P1 Quickstep slop do not respect density changes
Bug:135257548 P1 Adding shortcut can crash Launcher
Bug:64712476 P3 Import translations for dev branches
Change-Id: I9af1d8260b45fba32841877d88bad5a53f2e5746
parents 0e57817a f46e3956
Loading
Loading
Loading
Loading
+0 −7
Original line number Diff line number Diff line
<com.android.quickstep.hints.ProactiveHintsContainer
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal|bottom"
    android:gravity="center_horizontal">
</com.android.quickstep.hints.ProactiveHintsContainer>
 No newline at end of file
+6 −9
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_S
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.KeyguardManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -234,7 +233,6 @@ public class TouchInteractionService extends Service implements
    private final InputConsumer mResetGestureInputConsumer =
            new ResetGestureInputConsumer(mSwipeSharedState);

    private KeyguardManager mKM;
    private ActivityManagerWrapper mAM;
    private RecentsModel mRecentsModel;
    private ISystemUiProxy mISystemUiProxy;
@@ -280,7 +278,6 @@ public class TouchInteractionService extends Service implements

        // Initialize anything here that is needed in direct boot mode.
        // Everything else should be initialized in initWhenUserUnlocked() below.
        mKM = getSystemService(KeyguardManager.class);
        mMainChoreographer = Choreographer.getInstance();
        mAM = ActivityManagerWrapper.getInstance();

@@ -547,6 +544,10 @@ public class TouchInteractionService extends Service implements
                        (mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0, base,
                        mInputMonitorCompat, mSwipeTouchRegion);
            }
        } else {
            if ((mSystemUiStateFlags & SYSUI_STATE_SCREEN_PINNING) != 0) {
                base = mResetGestureInputConsumer;
            }
        }
        return base;
    }
@@ -556,11 +557,8 @@ public class TouchInteractionService extends Service implements
        if (!useSharedState) {
            mSwipeSharedState.clearAllState();
        }
        if ((mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0
                || mKM.isDeviceLocked()) {
            // This handles apps launched in direct boot mode (e.g. dialer) as well as apps launched
            // while device is locked after exiting direct boot mode (e.g. camera), or if the
            // app is showing over the lockscreen (even if not locked)
        if ((mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0) {
            // This handles apps showing over the lockscreen (e.g. camera)
            return createDeviceLockedInputConsumer(runningTaskInfo);
        }

@@ -665,7 +663,6 @@ public class TouchInteractionService extends Service implements
            pw.println("  systemUiFlags=" + mSystemUiStateFlags);
            pw.println("  systemUiFlagsDesc="
                    + QuickStepContract.getSystemUiStateString(mSystemUiStateFlags));
            pw.println("  isDeviceLocked=" + mKM.isDeviceLocked());
            pw.println("  assistantAvailable=" + mAssistantAvailable);
            pw.println("  assistantDisabled="
                    + QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags));
+31 −27
Original line number Diff line number Diff line
@@ -22,10 +22,9 @@ 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 android.view.MotionEvent.INVALID_POINTER_ID;

import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_LANDSCAPE;
import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_SEASCAPE;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
@@ -45,10 +44,7 @@ import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;

import androidx.annotation.UiThread;

import com.android.launcher3.R;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
@@ -68,10 +64,11 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.QuickStepContract;

import java.util.function.Consumer;

import androidx.annotation.UiThread;

/**
 * Input consumer for handling events originating from an activity other than Launcher
 */
@@ -81,6 +78,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
    public static final String DOWN_EVT = "OtherActivityInputConsumer.DOWN";
    private static final String UP_EVT = "OtherActivityInputConsumer.UP";

    // TODO: Move to quickstep contract
    private static final float QUICKSTEP_TOUCH_SLOP_RATIO = 3;

    private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
    private final RunningTaskInfo mRunningTask;
    private final RecentsModel mRecentsModel;
@@ -107,14 +107,16 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
    private final PointF mLastPos = new PointF();
    private int mActivePointerId = INVALID_POINTER_ID;

    private final float mDragSlop;
    // Distance after which we start dragging the window.
    private final float mTouchSlop;

    private final float mSquaredTouchSlop;
    private final boolean mDisableHorizontalSwipe;

    // Slop used to check when we start moving window.
    private boolean mPassedDragSlop;
    private boolean mPaddedWindowMoveSlop;
    // Slop used to determine when we say that the gesture has started.
    private boolean mPassedTouchSlop;
    private boolean mPassedPilferInputSlop;

    // Might be displacement in X or Y, depending on the direction we are swiping from the nav bar.
    private float mStartDisplacement;
@@ -156,12 +158,13 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
        mSwipeSharedState = swipeSharedState;

        mNavBarPosition = new NavBarPosition(base);
        mDragSlop = QuickStepContract.getQuickStepDragSlopPx();
        float slop = QuickStepContract.getQuickStepTouchSlopPx();
        mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();

        float slop = QUICKSTEP_TOUCH_SLOP_RATIO * mTouchSlop;
        mSquaredTouchSlop = slop * slop;

        mPassedTouchSlop = mPassedDragSlop = continuingPreviousGesture;
        mDisableHorizontalSwipe = !mPassedTouchSlop && disableHorizontalSwipe;
        mPassedPilferInputSlop = mPaddedWindowMoveSlop = continuingPreviousGesture;
        mDisableHorizontalSwipe = !mPassedPilferInputSlop && disableHorizontalSwipe;
    }

    @Override
@@ -183,7 +186,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
        }

        // Proxy events to recents view
        if (mPassedDragSlop && mInteractionHandler != null
        if (mPaddedWindowMoveSlop && mInteractionHandler != null
                && !mRecentsViewDispatcher.hasConsumer()) {
            mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher(
                    mNavBarPosition.getRotationMode()));
@@ -217,7 +220,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
                break;
            }
            case ACTION_POINTER_DOWN: {
                if (!mPassedTouchSlop) {
                if (!mPassedPilferInputSlop) {
                    // Cancel interaction in case of multi-touch interaction
                    int ptrIdx = ev.getActionIndex();
                    if (!mSwipeTouchRegion.contains(ev.getX(ptrIdx), ev.getY(ptrIdx))) {
@@ -248,18 +251,18 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
                float displacement = getDisplacement(ev);
                float displacementX = mLastPos.x - mDownPos.x;

                if (!mPassedDragSlop) {
                if (!mPaddedWindowMoveSlop) {
                    if (!mIsDeferredDownTarget) {
                        // Normal gesture, ensure we pass the drag slop before we start tracking
                        // the gesture
                        if (Math.abs(displacement) > mDragSlop) {
                            mPassedDragSlop = true;
                            mStartDisplacement = displacement;
                        if (Math.abs(displacement) > mTouchSlop) {
                            mPaddedWindowMoveSlop = true;
                            mStartDisplacement = Math.min(displacement, -mTouchSlop);
                        }
                    }
                }

                if (!mPassedTouchSlop) {
                if (!mPassedPilferInputSlop) {
                    float displacementY = mLastPos.y - mDownPos.y;
                    if (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop) {
                        if (mDisableHorizontalSwipe
@@ -269,23 +272,24 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
                            break;
                        }

                        mPassedTouchSlop = true;
                        mPassedPilferInputSlop = true;

                        if (mIsDeferredDownTarget) {
                            // Deferred gesture, start the animation and gesture tracking once
                            // we pass the actual touch slop
                            startTouchTrackingForWindowAnimation(ev.getEventTime());
                        }
                        if (!mPassedDragSlop) {
                            mPassedDragSlop = true;
                            mStartDisplacement = displacement;
                        if (!mPaddedWindowMoveSlop) {
                            mPaddedWindowMoveSlop = true;
                            mStartDisplacement = Math.min(displacement, -mTouchSlop);

                        }
                        notifyGestureStarted();
                    }
                }

                if (mInteractionHandler != null) {
                    if (mPassedDragSlop) {
                    if (mPaddedWindowMoveSlop) {
                        // Move
                        mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
                    }
@@ -362,7 +366,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
        RaceConditionTracker.onEvent(UP_EVT, ENTER);
        TraceHelper.endSection("TouchInt");

        if (mPassedDragSlop && mInteractionHandler != null) {
        if (mPaddedWindowMoveSlop && mInteractionHandler != null) {
            if (ev.getActionMasked() == ACTION_CANCEL) {
                mInteractionHandler.onGestureCancelled();
            } else {
@@ -448,6 +452,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC

    @Override
    public boolean allowInterceptByParent() {
        return !mPassedTouchSlop;
        return !mPassedPilferInputSlop;
    }
}
+65 −40
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@ package com.android.quickstep.views;

import static android.provider.Settings.ACTION_APP_USAGE_SETTINGS;

import static com.android.launcher3.Utilities.prefixTextWithIcon;

import android.annotation.TargetApi;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.AppUsageLimit;
@@ -28,16 +30,16 @@ import android.icu.text.MeasureFormat;
import android.icu.text.MeasureFormat.FormatWidth;
import android.icu.util.Measure;
import android.icu.util.MeasureUnit;
import android.os.Build;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.StringRes;

import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -46,45 +48,72 @@ import com.android.systemui.shared.recents.model.Task;
import java.time.Duration;
import java.util.Locale;

public final class DigitalWellBeingToast extends LinearLayout {
@TargetApi(Build.VERSION_CODES.Q)
public final class DigitalWellBeingToast {
    static final Intent OPEN_APP_USAGE_SETTINGS_TEMPLATE = new Intent(ACTION_APP_USAGE_SETTINGS);
    static final int MINUTE_MS = 60000;
    private final LauncherApps mLauncherApps;

    public interface InitializeCallback {
        void call(String contentDescription);
    }

    private static final String TAG = DigitalWellBeingToast.class.getSimpleName();

    private final BaseDraggingActivity mActivity;
    private final TaskView mTaskView;
    private final LauncherApps mLauncherApps;

    private Task mTask;
    private TextView mText;
    private boolean mHasLimit;
    private long mAppRemainingTimeMs;

    public DigitalWellBeingToast(Context context, AttributeSet attrs) {
        super(context, attrs);
        setLayoutDirection(Utilities.isRtl(getResources()) ?
                View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
        setOnClickListener((view) -> openAppUsageSettings());
        mLauncherApps = context.getSystemService(LauncherApps.class);
    public DigitalWellBeingToast(BaseDraggingActivity activity, TaskView taskView) {
        mActivity = activity;
        mTaskView = taskView;
        mLauncherApps = activity.getSystemService(LauncherApps.class);
    }

    public TextView getTextView() {
        return mText;
    private void setTaskFooter(View view) {
        View oldFooter = mTaskView.setFooter(TaskView.INDEX_DIGITAL_WELLBEING_TOAST, view);
        if (oldFooter != null) {
            oldFooter.setOnClickListener(null);
            mActivity.getViewCache().recycleView(R.layout.digital_wellbeing_toast, oldFooter);
        }
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
    private void setNoLimit() {
        mHasLimit = false;
        mTaskView.setContentDescription(mTask.titleDescription);
        setTaskFooter(null);
        mAppRemainingTimeMs = 0;
    }

        mText = findViewById(R.id.digital_well_being_remaining_time);
    private void setLimit(long appUsageLimitTimeMs, long appRemainingTimeMs) {
        mAppRemainingTimeMs = appRemainingTimeMs;
        mHasLimit = true;
        TextView toast = mActivity.getViewCache().getView(R.layout.digital_wellbeing_toast,
                mActivity, mTaskView);
        toast.setText(prefixTextWithIcon(mActivity, R.drawable.ic_hourglass_top, getText()));
        toast.setOnClickListener(this::openAppUsageSettings);
        setTaskFooter(toast);

        mTaskView.setContentDescription(
                getContentDescriptionForTask(mTask, appUsageLimitTimeMs, appRemainingTimeMs));
        RecentsView rv = mTaskView.getRecentsView();
        if (rv != null) {
            rv.onDigitalWellbeingToastShown();
        }
    }

    public String getText() {
        return getText(mAppRemainingTimeMs);
    }

    public void initialize(Task task, InitializeCallback callback) {
    public boolean hasLimit() {
        return mHasLimit;
    }

    public void initialize(Task task) {
        mTask = task;

        if (task.key.userId != UserHandle.myUserId()) {
            setVisibility(GONE);
            callback.call(task.titleDescription);
            setNoLimit();
            return;
        }

@@ -98,16 +127,12 @@ public final class DigitalWellBeingToast extends LinearLayout {
            final long appRemainingTimeMs =
                    usageLimit != null ? usageLimit.getUsageRemaining() : -1;

            post(() -> {
            mTaskView.post(() -> {
                if (appUsageLimitTimeMs < 0 || appRemainingTimeMs < 0) {
                    setVisibility(GONE);
                    setNoLimit();
                } else {
                    setVisibility(VISIBLE);
                    mText.setText(getText(appRemainingTimeMs));
                    setLimit(appUsageLimitTimeMs, appRemainingTimeMs);
                }

                callback.call(getContentDescriptionForTask(
                        task, appUsageLimitTimeMs, appRemainingTimeMs));
            });
        });
    }
@@ -146,7 +171,7 @@ public final class DigitalWellBeingToast extends LinearLayout {

        // Use a specific string for usage less than one minute but non-zero.
        if (duration.compareTo(Duration.ZERO) > 0) {
            return getResources().getString(durationLessThanOneMinuteStringId);
            return mActivity.getString(durationLessThanOneMinuteStringId);
        }

        // Otherwise, return 0-minute string.
@@ -176,24 +201,24 @@ public final class DigitalWellBeingToast extends LinearLayout {
    }

    private String getText(long remainingTime) {
        return getResources().getString(
        return mActivity.getString(
                R.string.time_left_for_app,
                getRoundedUpToMinuteReadableDuration(remainingTime));
    }

    public void openAppUsageSettings() {
    public void openAppUsageSettings(View view) {
        final Intent intent = new Intent(OPEN_APP_USAGE_SETTINGS_TEMPLATE)
                .putExtra(Intent.EXTRA_PACKAGE_NAME,
                        mTask.getTopComponent().getPackageName()).addFlags(
                        Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        try {
            final BaseActivity activity = BaseActivity.fromContext(getContext());
            final BaseActivity activity = BaseActivity.fromContext(view.getContext());
            final ActivityOptions options = ActivityOptions.makeScaleUpAnimation(
                    this, 0, 0,
                    getWidth(), getHeight());
                    view, 0, 0,
                    view.getWidth(), view.getHeight());
            activity.startActivity(intent, options.toBundle());
            activity.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP,
                    LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this);
                    LauncherLogProto.ControlType.APP_USAGE_SETTINGS, view);
        } catch (ActivityNotFoundException e) {
            Log.e(TAG, "Failed to open app usage settings for task "
                    + mTask.getTopComponent().getPackageName(), e);
@@ -203,7 +228,7 @@ public final class DigitalWellBeingToast extends LinearLayout {
    private String getContentDescriptionForTask(
            Task task, long appUsageLimitTimeMs, long appRemainingTimeMs) {
        return appUsageLimitTimeMs >= 0 && appRemainingTimeMs >= 0 ?
                getResources().getString(
                mActivity.getString(
                        R.string.task_contents_description_with_remaining_time,
                        task.titleDescription,
                        getText(appRemainingTimeMs)) :
+3 −0
Original line number Diff line number Diff line
@@ -351,6 +351,9 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
                .getDimensionPixelSize(R.dimen.recents_empty_message_text_padding);
        setWillNotDraw(false);
        updateEmptyMessage();

        // Initialize quickstep specific cache params here, as this is constructed only once
        mActivity.getViewCache().setCacheSize(R.layout.digital_wellbeing_toast, 5);
    }

    public OverScroller getScroller() {
Loading