diff --git a/quickstep/recents_ui_overrides/res/layout/proactive_hints_container.xml b/quickstep/recents_ui_overrides/res/layout/proactive_hints_container.xml deleted file mode 100644 index be3f17acd8..0000000000 --- a/quickstep/recents_ui_overrides/res/layout/proactive_hints_container.xml +++ /dev/null @@ -1,7 +0,0 @@ - - \ No newline at end of file diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 097ff46592..769d207ab4 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -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)); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java index 69b25db8f5..6bc543f075 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java @@ -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; } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java index 5aab944a32..7fac813854 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java @@ -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(); - - mText = findViewById(R.id.digital_well_being_remaining_time); + private void setNoLimit() { + mHasLimit = false; + mTaskView.setContentDescription(mTask.titleDescription); + setTaskFooter(null); + mAppRemainingTimeMs = 0; } - public void initialize(Task task, InitializeCallback callback) { + 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 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)) : diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index f66e401f9a..9058e7eda7 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -351,6 +351,9 @@ public abstract class RecentsView 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() { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index 694d501905..e7e41893cf 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -27,6 +27,8 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.ActivityOptions; import android.content.Context; import android.content.res.Resources; @@ -39,6 +41,7 @@ import android.os.Handler; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Log; +import android.view.Gravity; import android.view.View; import android.view.ViewOutlineProvider; import android.view.accessibility.AccessibilityNodeInfo; @@ -145,14 +148,12 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { }; private final TaskOutlineProvider mOutlineProvider; - private final FooterOutlineProvider mFooterOutlineProvider; private Task mTask; private TaskThumbnailView mSnapshotView; private TaskMenuView mMenuView; private IconView mIconView; - private View mTaskFooterContainer; - private DigitalWellBeingToast mDigitalWellBeingToast; + private final DigitalWellBeingToast mDigitalWellBeingToast; private float mCurveScale; private float mFullscreenProgress; private final FullscreenDrawParams mCurrentFullscreenParams; @@ -171,6 +172,14 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private TaskThumbnailCache.ThumbnailLoadRequest mThumbnailLoadRequest; private TaskIconCache.IconLoadRequest mIconLoadRequest; + // Order in which the footers appear. Lower order appear below higher order. + public static final int INDEX_DIGITAL_WELLBEING_TOAST = 0; + public static final int INDEX_PROACTIVE_SUGGEST = 1; + private final FooterWrapper[] mFooters = new FooterWrapper[2]; + private float mFooterVerticalOffset = 0; + private float mFooterAlpha = 1; + private int mStackHeight; + public TaskView(Context context) { this(context, null); } @@ -208,8 +217,9 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mCornerRadius = TaskCornerRadius.get(context); mWindowCornerRadius = QuickStepContract.getWindowCornerRadius(context.getResources()); mCurrentFullscreenParams = new FullscreenDrawParams(mCornerRadius); + mDigitalWellBeingToast = new DigitalWellBeingToast(mActivity, this); + mOutlineProvider = new TaskOutlineProvider(getResources(), mCurrentFullscreenParams); - mFooterOutlineProvider = new FooterOutlineProvider(mCurrentFullscreenParams); setOutlineProvider(mOutlineProvider); } @@ -218,10 +228,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { super.onFinishInflate(); mSnapshotView = findViewById(R.id.snapshot); mIconView = findViewById(R.id.icon); - mDigitalWellBeingToast = findViewById(R.id.digital_well_being_toast); - mTaskFooterContainer = findViewById(R.id.task_footer_container); - mTaskFooterContainer.setOutlineProvider(mFooterOutlineProvider); - mTaskFooterContainer.setClipToOutline(true); } public TaskMenuView getMenuView() { @@ -357,15 +363,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) { getRecentsView().updateLiveTileIcon(task.icon); } - mDigitalWellBeingToast.initialize( - mTask, - contentDescription -> { - setContentDescription(contentDescription); - if (mDigitalWellBeingToast.getVisibility() == VISIBLE - && getRecentsView() != null) { - getRecentsView().onDigitalWellbeingToastShown(); - } - }); + mDigitalWellBeingToast.initialize(mTask); }); } else { mSnapshotView.setThumbnail(null, null); @@ -424,14 +422,12 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mIconView.setScaleX(scale); mIconView.setScaleY(scale); - int footerVerticalOffset = (int) (mTaskFooterContainer.getHeight() * (1.0f - scale)); - mTaskFooterContainer.setTranslationY( - mCurrentFullscreenParams.mCurrentDrawnInsets.bottom + - mCurrentFullscreenParams.mCurrentDrawnInsets.top + - footerVerticalOffset); - mFooterOutlineProvider.setFullscreenDrawParams( - mCurrentFullscreenParams, footerVerticalOffset); - mTaskFooterContainer.invalidateOutline(); + mFooterVerticalOffset = 1.0f - scale; + for (FooterWrapper footer : mFooters) { + if (footer != null) { + footer.updateFooterOffset(); + } + } } public void setIconScaleAnimStartProgress(float startProgress) { @@ -505,8 +501,13 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mSnapshotView.setDimAlpha(curveInterpolation * MAX_PAGE_SCRIM_ALPHA); setCurveScale(getCurveScaleForCurveInterpolation(curveInterpolation)); - float fade = Utilities.boundToRange(1.0f - 2 * scrollState.linearInterpolation, 0f, 1f); - mTaskFooterContainer.setAlpha(fade); + mFooterAlpha = Utilities.boundToRange(1.0f - 2 * scrollState.linearInterpolation, 0f, 1f); + for (FooterWrapper footer : mFooters) { + if (footer != null) { + footer.mView.setAlpha(mFooterAlpha); + } + } + if (mMenuView != null) { mMenuView.setPosition(getX() - getRecentsView().getScrollX(), getY()); mMenuView.setScaleX(getScaleX()); @@ -514,6 +515,56 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } } + + /** + * Sets the footer at the specific index and returns the previously set footer. + */ + public View setFooter(int index, View view) { + View oldFooter = null; + + // If the footer are is already collapsed, do not animate entry + boolean shouldAnimateEntry = mFooterVerticalOffset <= 0; + + if (mFooters[index] != null) { + oldFooter = mFooters[index].mView; + mFooters[index].release(); + removeView(oldFooter); + + // If we are replacing an existing footer, do not animate entry + shouldAnimateEntry = false; + } + if (view != null) { + int indexToAdd = getChildCount(); + for (int i = index - 1; i >= 0; i--) { + if (mFooters[i] != null) { + indexToAdd = indexOfChild(mFooters[i].mView); + break; + } + } + + addView(view, indexToAdd); + ((LayoutParams) view.getLayoutParams()).gravity = + Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; + view.setAlpha(mFooterAlpha); + mFooters[index] = new FooterWrapper(view); + if (shouldAnimateEntry) { + mFooters[index].animateEntry(); + } + } else { + mFooters[index] = null; + } + + mStackHeight = 0; + for (FooterWrapper footer : mFooters) { + if (footer != null) { + footer.setVerticalShift(mStackHeight); + mStackHeight += footer.mExpectedHeight; + } + } + + return oldFooter; + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); @@ -523,6 +574,18 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(0, 0, getWidth(), getHeight()); setSystemGestureExclusionRects(SYSTEM_GESTURE_EXCLUSION_RECT); } + + mStackHeight = 0; + for (FooterWrapper footer : mFooters) { + if (footer != null) { + mStackHeight += footer.mView.getHeight(); + } + } + for (FooterWrapper footer : mFooters) { + if (footer != null) { + footer.updateFooterOffset(); + } + } } public static float getCurveScaleForInterpolation(float linearInterpolation) { @@ -581,26 +644,74 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } } - private static final class FooterOutlineProvider extends ViewOutlineProvider { + private class FooterWrapper extends ViewOutlineProvider { - private FullscreenDrawParams mFullscreenDrawParams; - private int mVerticalOffset; - private final Rect mOutlineRect = new Rect(); + final View mView; + final ViewOutlineProvider mOldOutlineProvider; + final ViewOutlineProvider mDelegate; - FooterOutlineProvider(FullscreenDrawParams params) { - mFullscreenDrawParams = params; + final int mExpectedHeight; + final int mOldPaddingBottom; + + int mAnimationOffset = 0; + int mEntryAnimationOffset = 0; + + public FooterWrapper(View view) { + mView = view; + mOldOutlineProvider = view.getOutlineProvider(); + mDelegate = mOldOutlineProvider == null + ? ViewOutlineProvider.BACKGROUND : mOldOutlineProvider; + + int h = view.getLayoutParams().height; + if (h > 0) { + mExpectedHeight = h; + } else { + int m = MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY - 1, MeasureSpec.AT_MOST); + view.measure(m, m); + mExpectedHeight = view.getMeasuredHeight(); + } + mOldPaddingBottom = view.getPaddingBottom(); + + if (mOldOutlineProvider != null) { + view.setOutlineProvider(this); + view.setClipToOutline(true); + } } - void setFullscreenDrawParams(FullscreenDrawParams params, int verticalOffset) { - mFullscreenDrawParams = params; - mVerticalOffset = verticalOffset; + public void setVerticalShift(int shift) { + mView.setPadding(mView.getPaddingLeft(), mView.getPaddingTop(), + mView.getPaddingRight(), mOldPaddingBottom + shift); } @Override public void getOutline(View view, Outline outline) { - mOutlineRect.set(0, 0, view.getWidth(), view.getHeight()); - mOutlineRect.offset(0, -mVerticalOffset); - outline.setRoundRect(mOutlineRect, mFullscreenDrawParams.mCurrentDrawnCornerRadius); + mDelegate.getOutline(view, outline); + outline.offset(0, -mAnimationOffset - mEntryAnimationOffset); + } + + void updateFooterOffset() { + mAnimationOffset = Math.round(mStackHeight * mFooterVerticalOffset); + mView.setTranslationY(mAnimationOffset + mEntryAnimationOffset + + mCurrentFullscreenParams.mCurrentDrawnInsets.bottom + + mCurrentFullscreenParams.mCurrentDrawnInsets.top); + mView.invalidateOutline(); + } + + void release() { + mView.setOutlineProvider(mOldOutlineProvider); + setVerticalShift(0); + } + + void animateEntry() { + ValueAnimator animator = ValueAnimator.ofFloat(0, 1); + animator.addUpdateListener(anim -> { + float factor = 1 - anim.getAnimatedFraction(); + int totalShift = mExpectedHeight + mView.getPaddingBottom() - mOldPaddingBottom; + mEntryAnimationOffset = Math.round(factor * totalShift); + updateFooterOffset(); + }); + animator.setDuration(100); + animator.start(); } } @@ -624,7 +735,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } } - if (mDigitalWellBeingToast.getVisibility() == VISIBLE) { + if (mDigitalWellBeingToast.hasLimit()) { info.addAction( new AccessibilityNodeInfo.AccessibilityAction( R.string.accessibility_app_usage_settings, @@ -648,7 +759,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } if (action == R.string.accessibility_app_usage_settings) { - mDigitalWellBeingToast.openAppUsageSettings(); + mDigitalWellBeingToast.openAppUsageSettings(this); return true; } diff --git a/quickstep/res/layout/digital_wellbeing_toast.xml b/quickstep/res/layout/digital_wellbeing_toast.xml new file mode 100644 index 0000000000..83594e4ff3 --- /dev/null +++ b/quickstep/res/layout/digital_wellbeing_toast.xml @@ -0,0 +1,27 @@ + + + \ No newline at end of file diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml index 6a595a16e5..60cfa0cbaa 100644 --- a/quickstep/res/layout/task.xml +++ b/quickstep/res/layout/task.xml @@ -25,7 +25,7 @@ android:id="@+id/snapshot" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_marginTop="@dimen/task_thumbnail_top_margin" /> + android:layout_marginTop="@dimen/task_thumbnail_top_margin"/> - - - - - - - - + android:importantForAccessibility="no"/> \ No newline at end of file diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml index 73c7c5c033..b036bc1ebd 100644 --- a/quickstep/res/values-ar/strings.xml +++ b/quickstep/res/values-ar/strings.xml @@ -27,7 +27,7 @@ "إغلاق" "إعدادات استخدام التطبيق" "محو الكل" - "التطبيقات التي تمّ استخدامها مؤخرًا" + "التطبيقات المستخدمة مؤخرًا" "%1$s، %2$s" "أقل من دقيقة" "يتبقى اليوم %1$s." diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml index a33973b218..c188493e59 100644 --- a/quickstep/res/values-as/strings.xml +++ b/quickstep/res/values-as/strings.xml @@ -31,4 +31,7 @@ "%1$s, %2$s" "< ১ মিনিট" "আজি %1$s বাকী আছ" + "এপৰ পৰামৰ্শসমূহ" + "সকলো এপ্" + "আপোনাৰ অনুমানিক এপ্" diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml index 7f4e56d260..449cc8c11d 100644 --- a/quickstep/res/values-de/strings.xml +++ b/quickstep/res/values-de/strings.xml @@ -20,7 +20,7 @@ "Splitscreen" - "Fixieren" + "Anpinnen" "Freeform-Modus" "Übersicht" "Keine kürzlich verwendeten Elemente" diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml index c6698bb480..356d10d5da 100644 --- a/quickstep/res/values-gl/strings.xml +++ b/quickstep/res/values-gl/strings.xml @@ -27,7 +27,7 @@ "Pecha a aplicación" "Configuración do uso de aplicacións" "Borrar todo" - "Aplicacións recentes" + "Apps recentes" "%1$s (%2$s)" "<1 min" "Tempo restante hoxe %1$s" diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml index bd88671938..2ebec4e7c7 100644 --- a/quickstep/res/values-or/strings.xml +++ b/quickstep/res/values-or/strings.xml @@ -27,8 +27,11 @@ "ବନ୍ଦ କରନ୍ତୁ" "ଆପ୍‍ ବ୍ୟବହାର ସେଟିଂସ୍‍" "ସବୁ ଖାଲି କରନ୍ତୁ" - "ସାମ୍ପ୍ରତିକ ଆପ୍‌" + "ବର୍ତ୍ତମାନର ଆପ୍‌" "%1$s %2$s" "< 1 ମିନିଟ୍" "ଆଜି %1$s ବାକି ଅଛି" + "ଆପ୍ ପରାମର୍ଶଗୁଡ଼ିକ" + "ସମସ୍ତ ଆପ୍ସ" + "ଆପଣ ପୂର୍ବାନୁମାନ କରିଥିବା ଆପ୍ସ" diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java index 46161cbc8a..8643160950 100644 --- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java @@ -59,6 +59,7 @@ import android.view.View; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.shortcuts.DeepShortcutView; import com.android.launcher3.util.MultiValueAlpha; @@ -182,6 +183,12 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans mDeviceProfile = dp; } + @Override + public boolean supportsAdaptiveIconAnimation() { + return hasControlRemoteAppTransitionPermission() + && FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM.get(); + } + /** * @return ActivityOptions with remote animations that controls how the window of the opening * targets are displayed. diff --git a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java index 70f9c90dad..0c5a6f5b6e 100644 --- a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java +++ b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java @@ -51,15 +51,15 @@ public class DigitalWellBeingToastTest extends AbstractQuickStepTest { mLauncher.pressHome(); final DigitalWellBeingToast toast = getToast(); - assertTrue("Toast is not visible", toast.isShown()); - assertEquals("Toast text: ", "5 minutes left today", toast.getTextView().getText()); + assertTrue("Toast is not visible", toast.hasLimit()); + assertEquals("Toast text: ", "5 minutes left today", toast.getText()); // Unset time limit for app. runWithShellPermission( () -> usageStatsManager.unregisterAppUsageLimitObserver(observerId)); mLauncher.pressHome(); - assertFalse("Toast is visible", getToast().isShown()); + assertFalse("Toast is visible", getToast().hasLimit()); } finally { runWithShellPermission( () -> usageStatsManager.unregisterAppUsageLimitObserver(observerId)); diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java index c3e46ea110..90763b871b 100644 --- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java +++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java @@ -33,6 +33,7 @@ import androidx.test.uiautomator.UiDevice; import com.android.launcher3.tapl.LauncherInstrumentation; import com.android.launcher3.tapl.TestHelpers; +import com.android.systemui.shared.system.QuickStepContract; import org.junit.Assert; import org.junit.rules.TestRule; @@ -43,6 +44,8 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** * Test rule that allows executing a test with Quickstep on and then Quickstep off. @@ -78,11 +81,14 @@ public class NavigationModeSwitchRule implements TestRule { @Override public void evaluate() throws Throwable { final Context context = getInstrumentation().getContext(); - final String prevOverlayPkg = LauncherInstrumentation.isGesturalMode(context) - ? NAV_BAR_MODE_GESTURAL_OVERLAY - : LauncherInstrumentation.isSwipeUpMode(context) - ? NAV_BAR_MODE_2BUTTON_OVERLAY - : NAV_BAR_MODE_3BUTTON_OVERLAY; + final int currentInteractionMode = + LauncherInstrumentation.getCurrentInteractionMode(context); + final String prevOverlayPkg = + QuickStepContract.isGesturalMode(currentInteractionMode) + ? NAV_BAR_MODE_GESTURAL_OVERLAY + : QuickStepContract.isSwipeUpMode(currentInteractionMode) + ? NAV_BAR_MODE_2BUTTON_OVERLAY + : NAV_BAR_MODE_3BUTTON_OVERLAY; final LauncherInstrumentation.NavigationModel originalMode = mLauncher.getNavigationModel(); try { @@ -131,6 +137,27 @@ public class NavigationModeSwitchRule implements TestRule { setOverlayPackageEnabled(NAV_BAR_MODE_GESTURAL_OVERLAY, overlayPackage == NAV_BAR_MODE_GESTURAL_OVERLAY); + if (currentSysUiNavigationMode() != expectedMode) { + final CountDownLatch latch = new CountDownLatch(1); + final Context targetContext = getInstrumentation().getTargetContext(); + final SysUINavigationMode.NavigationModeChangeListener listener = + newMode -> { + if (LauncherInstrumentation.getNavigationModel(newMode.resValue) + == expectedMode) { + latch.countDown(); + } + }; + final SysUINavigationMode sysUINavigationMode = + SysUINavigationMode.INSTANCE.get(targetContext); + targetContext.getMainExecutor().execute(() -> + sysUINavigationMode.addModeChangeListener(listener)); + latch.await(10, TimeUnit.SECONDS); + targetContext.getMainExecutor().execute(() -> + sysUINavigationMode.removeModeChangeListener(listener)); + Assert.assertTrue("Navigation mode didn't change to " + expectedMode, + currentSysUiNavigationMode() == expectedMode); + } + for (int i = 0; i != 100; ++i) { if (mLauncher.getNavigationModel() == expectedMode) { Thread.sleep(5000); @@ -153,4 +180,12 @@ public class NavigationModeSwitchRule implements TestRule { return base; } } + + private static LauncherInstrumentation.NavigationModel currentSysUiNavigationMode() { + return LauncherInstrumentation.getNavigationModel( + SysUINavigationMode.getMode( + getInstrumentation(). + getTargetContext()). + resValue); + } } diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index bf00e9541d..a80ecb0b14 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -85,7 +85,7 @@ "الأدوات" "الخلفيات" "الأنماط والخلفيات" - "إعدادات الصفحة الرئيسية" + "إعدادات الشاشة الرئيسية" "أوقف المشرف هذه الميزة" "السماح بتدوير الشاشة الرئيسية" "عند تدوير الهاتف" @@ -108,7 +108,7 @@ "أدوات %1$s" "قائمة الأدوات" "تم إغلاق قائمة الأدوات." - "إضافة إلى الشاشة الرئيسية" + "الإضافة إلى الشاشة الرئيسية" "نقل العنصر إلى هنا" "تمت إضافة العنصر إلى الشاشة الرئيسية" "تم حذف العنصر" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 5158a78164..883003c5c0 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -105,7 +105,7 @@ "Vidžeti za %1$s" "Lista vidžeta" "Lista vidžeta je zatvorena" - "Dodaj na početni ekran" + "Dodajte na početni ekran" "Premesti stavku ovde" "Stavka je dodata na početni ekran" "Stavka je uklonjena" diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index 6d80329988..775885caac 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -83,7 +83,7 @@ "স্টাইল এবং ওয়ালপেপার" "হোম সেটিংস" "আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে" - "হোমস্ক্রীন ঘোরানোর অনুমতি দিন" + "হোম স্ক্রিন ঘোরানোর অনুমতি দিন" "যখন ফোনটি ঘোরানো হয়" "বিজ্ঞপ্তি ডট" "চালু" @@ -104,7 +104,7 @@ "%1$s উইজেট" "উইজেটের তালিকা" "উইজেটের তালিকা বন্ধ করা হয়েছে" - "হোম স্ক্রীনে যোগ করুন" + "হোম স্ক্রিনে যোগ করুন" "এখানে আইটেম সরান" "হোম স্ক্রীনে আইটেম যোগ করা হয়েছে" "আইটেম সরানো হয়েছে" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 53bdeb2d7b..5650457071 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -79,7 +79,7 @@ "Folder je zatvoren" "Ime foldera je promijenjeno u %1$s" "Folder: %1$s" - "Dodaci" + "Vidžeti" "Pozadinske slike" "Stilovi i pozadinske slike" "Postavke početnog ekrana" @@ -90,7 +90,7 @@ "Uključeno" "Isključeno" "Potreban je pristup obavještenjima" - "Za prikaz tačaka obavještenja, uključite obavještenja za aplikacije za aplikaciju %1$s" + "Za prikaz tačaka za obavještenja, uključite obavještenja za aplikacije za aplikaciju %1$s" "Promijeni postavke" "Prikaži tačke za obavještenja" "Dodaj ikonu na početni ekran" diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 19f537ffbd..c0859d3b4d 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -81,7 +81,7 @@ "Widgets" "Fons de pantalla" "Estils i fons de pantalla" - "Configuració de pantalla d\'inici" + "Config. pantalla d\'inici" "Desactivada per l\'administrador" "Permet la rotació de la pantalla d\'inici" "En girar el telèfon" @@ -92,7 +92,7 @@ "Per veure els punts de notificació, activa les notificacions de l\'aplicació %1$s" "Canvia la configuració" "Mostra els punts de notificació" - "Afegeix la icona a la pantalla d\'inici" + "Afegeix icona a la pantalla d\'inici" "Per a les aplicacions noves" "Desconegut" "Suprimeix" diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 008910dc93..dc17516bce 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -33,7 +33,7 @@ "Tryk to gange, og hold fingeren nede for at vælge en widget eller bruge tilpassede handlinger." "%1$d × %2$d" "%1$d i bredden og %2$d i højden" - "Tryk og hold nede for at placere manuelt" + "Tryk og hold for at placere manuelt" "Tilføj automatisk" "Søg efter apps" "Indlæser apps…" @@ -48,7 +48,7 @@ "Liste med apps" "Liste over personlige apps" "Liste over apps til arbejdet" - "Startskærm" + "Hjem" "Fjern" "Afinstaller" "Appinfo" @@ -80,8 +80,8 @@ "Mappe: %1$s" "Widgets" "Baggrunde" - "Stilarter og baggrunde" - "Indstillinger for startskærmen" + "Stil og baggrunde" + "Startskærmindstillinger" "Deaktiveret af din administrator" "Tillad rotation af startskærmen" "Når telefonen roteres" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 1b7cd22c31..a345babd5c 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -80,11 +80,11 @@ "Ordner: %1$s" "Widgets" "Hintergründe" - "Stile und Hintergründe" - "Einstellungen für den Startbildschirm" + "Designs und Hintergründe" + "Startbildschirm-Einstellungen" "Von deinem Administrator deaktiviert" "Drehung des Startbildschirms zulassen" - "Bei Drehung des Smartphones" + "Beim Drehen des Smartphones" "App-Benachrichtigungspunkte" "An" "Aus" @@ -93,7 +93,7 @@ "Einstellungen ändern" "App-Benachrichtigungspunkte anzeigen" "Symbol zum Startbildschirm hinzufügen" - "Für neue Apps" + "Bei neuen Apps" "Unbekannt" "Entfernen" "Suchen" diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index 6692370896..0c48b5d2cb 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -83,7 +83,7 @@ "Styles & wallpapers" "Home settings" "Disabled by your admin" - "Allow Homescreen rotation" + "Allow Home screen rotation" "When phone is rotated" "Notification dots" "On" diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 6692370896..0c48b5d2cb 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -83,7 +83,7 @@ "Styles & wallpapers" "Home settings" "Disabled by your admin" - "Allow Homescreen rotation" + "Allow Home screen rotation" "When phone is rotated" "Notification dots" "On" diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index 6692370896..0c48b5d2cb 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -83,7 +83,7 @@ "Styles & wallpapers" "Home settings" "Disabled by your admin" - "Allow Homescreen rotation" + "Allow Home screen rotation" "When phone is rotated" "Notification dots" "On" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index ac6ffaa35f..09b1239972 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -85,13 +85,13 @@ "Inhabilitado por el administrador" "Permitir rotación de la pantalla de inicio" "Al girar el teléfono" - "Burbujas de notificación" - "Activadas" + "Puntos de notificación" + "Activados" "Desactivadas" "Se necesita acceso a las notificaciones" - "Para mostrar burbujas de notificación, activa las notificaciones de %1$s" + "Para mostrar puntos de notificación, activa las notificaciones de %1$s" "Cambiar ajustes" - "Mostrar burbujas de notificación" + "Mostrar puntos de notificación" "Añadir icono a la pantalla de inicio" "Para aplicaciones nuevas" "Desconocido" diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index cea321da27..1e470e15a7 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -27,7 +27,7 @@ "Allalaetud rakendus on turvarežiimis keelatud" "Turvarežiimis on vidinad keelatud" "Otsetee pole saadaval" - "Avaekraan" + "Avakuva" "Kohandatud toimingud" "Vidina valimiseks vajutage ja hoidke seda all." "Topeltpuudutage ja hoidke vidina valimiseks või kohandatud toimingute kasutamiseks." @@ -48,16 +48,16 @@ "Rakenduste loend" "Isiklike rakenduste loend" "Töörakenduste loend" - "Avaekraan" + "Avakuva" "Eemalda" "Desinstalli" "Rakenduse teave" "Installimine" "installi otseteed" "Võimaldab rakendusel lisada otseteid kasutaja sekkumiseta." - "loe avaekraani seadeid ja otseteid" + "avakuva seadete ja otseteede lugemine" "Võimaldab rakendusel lugeda avaekraanil seadeid ja otseteid." - "kirjuta avaekraani seaded ja otseteed" + "avakuva seadete ja otseteede kirjutamine" "Võimaldab rakendusel muuta avaekraanil seadeid ja otseteid." "Rakendusel %1$s pole lubatud helistada" "Probleem vidina laadimisel" @@ -70,8 +70,8 @@ %1$s, %2$d märguanne "Leht %1$d/%2$d" - "Avaekraan %1$d/%2$d" - "Uus avaekraan" + "Avakuva %1$d/%2$d" + "Uus avakuva leht" "Kaust on avatud, %1$d x %2$d" "Puudutage kausta sulgemiseks" "Puudutage ümbernimetamise salvestamiseks" @@ -81,9 +81,9 @@ "Vidinad" "Taustapildid" "Stiilid ja taustapildid" - "Avaekraani seaded" + "Avakuva seaded" "Keelas administraator" - "Luba avaekraani pööramine" + "Luba avakuva pööramine" "Kui telefoni pööratakse" "Märguandetäpid" "Sees" @@ -92,7 +92,7 @@ "Märguandetäppide kuvamiseks lülitage sisse rakenduse %1$s märguanded" "Seadete muutmine" "Kuva märguandetäpid" - "Lisa ikoon avaekraanile" + "Lisa ikoon avakuvasse" "Uute rakenduste puhul" "Teadmata" "Eemalda" @@ -104,7 +104,7 @@ "Teenuse %1$s vidinad" "Vidinate loend" "Vidinate loend on suletud" - "Lisa avaekraanile" + "Lisa avakuvasse" "Teisalda üksus siia" "Üksus lisati avaekraanile" "Üksus eemaldati" diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 18af2fb0fc..9ba46c171d 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -54,11 +54,11 @@ "Aplikazioaren datuak" "Instalatu" "Instalatu lasterbideak" - "Erabiltzaileak ezer egin gabe lasterbideak gehitzea baimentzen die aplikazioei." + "Erabiltzaileak ezer egin gabe lasterbideak gehitzeko baimena ematen die aplikazioei." "Irakurri hasierako ezarpenak eta lasterbideak" - "Hasierako pantailako ezarpenak eta lasterbideak irakurtzea baimentzen die aplikazioei." + "Hasierako pantailako ezarpenak eta lasterbideak irakurtzeko baimena ematen die aplikazioei." "Idatzi hasierako ezarpenak eta lasterbideak" - "Hasierako pantailako ezarpenak eta lasterbideak aldatzea baimentzen die aplikazioei." + "Hasierako pantailako ezarpenak eta lasterbideak aldatzeko baimena ematen die aplikazioei." "%1$s aplikazioak ez du telefono-deiak egiteko baimenik" "Arazo bat izan da widgeta kargatzean" "Konfigurazioa" @@ -83,7 +83,7 @@ "Estiloak eta horma-paperak" "Hasierako pantailaren ezarpenak" "Administratzaileak desgaitu du" - "Baimendu hasierako pantaila biratzea" + "Eman hasierako pantaila biratzeko baimena" "Telefonoa biratzen denean" "Jakinarazpen-biribiltxoak" "Aktibatuta" @@ -93,7 +93,7 @@ "Aldatu ezarpenak" "Erakutsi jakinarazpen-biribiltxoak" "Gehitu ikonoa hasierako pantailan" - "Aplikazio berrietan" + "Aplikazio berrien kasuan" "Ezezaguna" "Kendu" "Bilatu" diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 7e3cbdc810..926cdb9b1c 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -33,7 +33,7 @@ "برای انتخاب یک ابزارک، دو ضربه سریع بزنید و نگه‌دارید یا از کنش‌های سفارشی استفاده کنید." "%1$d × %2$d" "‏%1$d عرض در %2$d طول" - "برای قرار دادن به‌صورت دستی لمس کنید و بکشید" + "آن را لمس کنید و بکشید تا به‌صورت دستی اضافه شود" "افزودن خودکار" "جستجوی برنامه‌ها" "درحال بارگیری برنامه‌‌ها…" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 9d0e3a0b0c..5ac514d448 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -51,7 +51,7 @@ "Accueil" "Supprimer" "Désinstaller" - "Détails de l\'appli" + "Détails de l\'application" "Installer" "installer des raccourcis" "Permet à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur." diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 585139c758..7b4bcb1d82 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -81,7 +81,7 @@ "Widgets" "Fonds d\'écran" "Styles et fonds d\'écran" - "Paramètres accueil" + "Paramètres d\'écran d\'accueil" "Désactivé par votre administrateur" "Autoriser la rotation de l\'écran d\'accueil" "Lorsque vous faites pivoter le téléphone" diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index 769586e78a..e115a72624 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -80,14 +80,14 @@ "Cartafol: %1$s" "Widgets" "Fondos de pantalla" - "Estilos e fondos de pantalla" - "Configuración da pantalla de Inicio" + "Estilos/fondos de pantalla" + "Axustes de Inicio" "Función desactivada polo administrador" "Permitir xirar a pantalla de inicio" "Ao xirar o teléfono" "Puntos de notificacións" - "Opción activada" - "Opción desactivada" + "Activados" + "Desactivados" "Necesítase acceso ás notificacións" "Para que se mostren os puntos de notificacións, activa as notificacións da aplicación %1$s" "Cambiar configuración" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index 5f24b05210..b796140e5e 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -22,9 +22,9 @@ "Launcher3" "कार्यस्‍थल" - "एप्‍लिकेशन इंस्‍टॉल नहीं है." - "ऐप्स उपलब्ध नहीं है" - "डाउनलोड किए गए ऐप्स सुरक्षित मोड में अक्षम है" + "ऐप्‍लिकेशन इंस्‍टॉल नहीं है." + "ऐप्लिकेशन उपलब्ध नहीं है" + "डाउनलोड किए गए ऐप्लिकेशन सुरक्षित मोड में अक्षम है" "विजेट सुरक्षित मोड में अक्षम हैं" "शॉर्टकट उपलब्ध नहीं है" "होम स्क्रीन" @@ -78,7 +78,7 @@ "फ़ोल्डर बंद किया गया" "फ़ोल्डर का नाम बदलकर %1$s किया गया" "फ़ोल्डर: %1$s" - "शॉर्टकट" + "विजेट" "वॉलपेपर" "स्टाइल और वॉलपेपर" "होम पेज की सेटिंग" @@ -97,9 +97,9 @@ "अज्ञात" "निकालें" "सर्च करें" - "यह ऐप्स इंस्टॉल नहीं है" + "यह ऐप्लिकेशन इंस्टॉल नहीं है" "इस आइकॉन का ऐप इंस्टॉल नहीं है. आप उसे निकाल सकते हैं या ऐप को खोज कर उसे मैन्युअल रूप से इंस्टॉल कर सकते हैं." - "%1$s डाउनलोड हो रहा है, %2$s पूर्ण" + "%1$s डाउनलोड हो रहा है, %2$s पूरी हुई" "%1$s के इंस्टॉल होने की प्रतीक्षा की जा रही है" "%1$s विजेट" "विजेट की सूची" @@ -132,7 +132,7 @@ "सूचना को खारिज किया गया" "निजी ऐप" "काम से जुड़े ऐप" - "कार्य प्रोफ़ाइल" + "वर्क प्रोफ़ाइल" "काम से जुड़े सभी ऐप्लिकेशन यहां पाएं" "काम से जुड़े हर ऐप्लिकेशन पर एक बैज (निशान) होता है और इन ऐप्लिकेशन की सुरक्षा आपका संगठन करता है. आसानी से इस्तेमाल करने के लिए ऐप्लिकेशन को अपनी होम स्क्रीन पर ले जाएं." "आपका संगठन प्रबंधित कर रहा है" diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index 0841be0fd1..3054214b5e 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -33,7 +33,7 @@ "Tap dua kalip & tahan untuk mengambil widget atau menggunakan tindakan khusus." "%1$d × %2$d" "lebar %1$d x tinggi %2$d" - "Sentuh & tahan untuk menempatkan secara manual" + "Tap lama untuk menempatkan secara manual" "Tambahkan otomatis" "Telusuri aplikasi" "Memuat aplikasi…" @@ -81,9 +81,9 @@ "Widget" "Wallpaper" "Gaya & wallpaper" - "Setelan layar Utama" + "Setelan layar utama" "Dinonaktifkan oleh admin" - "Izinkan layar Utama diputar" + "Izinkan Layar utama diputar" "Saat ponsel diputar" "Titik notifikasi" "Aktif" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 6f5a4009ee..c25e8795f7 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -50,7 +50,7 @@ "רשימת אפליקציות עבודה" "דף הבית" "הסר" - "הסר התקנה" + "להסרת התקנה" "פרטי אפליקציה" "התקנה" "התקן קיצורי דרך" @@ -61,7 +61,7 @@ "מאפשר לאפליקציה לשנות את ההגדרות וקיצורי הדרך בדף הבית." "%1$s אינו רשאי להתקשר" "בעיה בטעינת ווידג\'ט" - "הגדר" + "הגדרה" "זוהי אפליקציית מערכת ולא ניתן להסיר את התקנתה." "תיקיה ללא שם" "%1$s מושבתת" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index 2e953a6cdd..1cd9045b76 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -34,7 +34,7 @@ "%1$d × %2$d" "Ені: %1$d, биіктігі: %2$d" "Қолмен қою үшін басып тұрыңыз" - "Автоматты енгізу" + "Автоматты қосу" "Қолданбаларды іздеу" "Қолданбалар жүктелуде…" "\"%1$s\" сұрауына сәйкес келетін қолданбалар жоқ" diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index b953ea337b..f4a328df14 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -84,7 +84,7 @@ "ការកំណត់​ទំព័រដើម" "បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក" "អនុញ្ញាតការបងិ្វលអេក្រង់ដើម" - "នៅពេលដែលបង្វិលទូរស័ព្ទរបស់អ្នក" + "នៅពេលដែលបង្វិលទូរសព្ទ" "ស្លាកជូនដំណឹង" "បើក" "បិទ" @@ -104,7 +104,7 @@ "ធាតុ​ក្រាហ្វិក %1$s" "បញ្ជីធាតុ​ក្រាហ្វិក" "បាន​បិទ​បញ្ជីធាតុ​ក្រាហ្វិក" - "បន្ថែមទៅអេក្រង់ដើម" + "បញ្ចូលទៅអេក្រង់ដើម" "ផ្លាស់ធាតុមកទីនេះ" "ធាតុដែលត្រូវបានបន្ថែមទៅអេក្រង់ដើម" "ធាតុដែលបានដកចេញ" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 2e96a7ce19..14c830064b 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -104,7 +104,7 @@ "%1$s ವಿಜೆಟ್‌ಗಳು" "ವಿಜೆಟ್ ಪಟ್ಟಿ" "ವಿಜೆಟ್ ಪಟ್ಟಿಯನ್ನು ಮುಚ್ಚಲಾಗಿದೆ" - "ಮುಖಪುಟಕ್ಕೆ ಸೇರಿಸು" + "ಮುಖಪುಟಕ್ಕೆ ಸೇರಿಸಿ" "ಐಟಂ ಇಲ್ಲಿಗೆ ಸರಿಸಿ" "ಮುಖಪುಟ ಪರದೆಗೆ ಐಟಂ ಸೇರಿಸಲಾಗಿದೆ" "ಐಟಂ ತೆಗೆದುಹಾಕಲಾಗಿದೆ" diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index 36b63851c5..046a66253e 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -33,7 +33,7 @@ "Виджет тандоо үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз." "%1$d × %2$d" "Туурасы: %1$d, бийиктиги: %2$d" - "Кол менен жайгаштыруу үчүн басып туруп, таштаңыз" + "Кол менен кошуу үчүн кое бербей басып туруңуз" "Автоматтык түрдө кошуу" "Колдонмолорду издөө" "Колдонмолор жүктөлүүдө…" @@ -81,7 +81,7 @@ "Виджеттер" "Тушкагаздар" "Стилдер жана тушкагаздар" - "Башкы беттин жөндөөлөрү" + "Башкы бет жөндөөлөрү" "Администраторуңуз өчүрүп койгон" "Башкы экранды айлантууга уруксат берүү" "Телефон айланганда" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index e03340bdb1..4362e7cca5 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -78,7 +78,7 @@ "ഫോൾഡർ അടച്ചു" "ഫോൾഡറിന്റെ പേര് %1$s എന്നായി മാറ്റി" "ഫോൾഡർ: %1$s" - "വിജറ്റുകൾ" + "വിഡ്ജെറ്റുകൾ" "വാൾപേപ്പർ" "സ്‌റ്റൈലുകളും വാൾപേപ്പറുകളും" "ഹോം ക്രമീകരണം" diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index f52f46171c..ab02ac655c 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -104,7 +104,7 @@ "%1$s жижиг хэрэгсэл" "Жижиг хэрэгслийн жагсаалт" "Жижиг хэрэгслийн жагсаалтыг хаасан" - "Нүүр дэлгэц нэмэх" + "Нүүр дэлгэцэд нэмэх" "Энд байршуулах" "Нүүр дэлгэцэнд нэмсэн зүйл" "Арилгасан зүйл" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index f6eac53997..19c06976b0 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -66,8 +66,8 @@ "अनामित फोल्डर" "%1$s अक्षम केला आहे" - %1$sसाठी%2$dसूचना आहेत %1$sसाठी %2$d सूचना आहेत + %1$sसाठी%2$dसूचना आहे "%2$d पैकी %1$d पृष्ठ" "%2$d पैकी %1$d मुख्य स्क्रीन" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 7ae4446d5f..fd1f7d9535 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -50,7 +50,7 @@ "အလုပ်သုံး အက်ပ်စာရင်း" "ပင်မစာမျက်နှာ" "ဖယ်ရှားမည်" - "ဖယ်ထုတ်မည်" + "ဖြုတ်ရန်" "အက်ပ်အချက်အလက်များ" "ထည့်သွင်းရန်" "အတိုကောက်မှတ်သားမှုများအား ထည့်သွင်းခြင်း" @@ -94,7 +94,7 @@ "သတိပေးချက် အစက်များ ပြရန်" "ပင်မစာမျက်နှာသို့ သင်္ကေတပုံ ထည့်ရန်" "အက်ပ်အသစ်များအတွက်" - "မသိရ" + "မသိ" "ဖယ်ရှားရန်" "ရှာဖွေရန်" "အက်ပ်မတပ်ဆင်ရသေးပါ" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index bc1b45036c..ec30d8c6b2 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -33,7 +33,7 @@ "Dubbeltik en blijf aanraken om een widget toe te voegen of aangepaste acties te gebruiken." "%1$d × %2$d" "%1$d breed en %2$d hoog" - "Tik op een item en houd dit vast om het handmatig te plaatsen" + "Tik en houd vast om handmatig te plaatsen" "Automatisch toevoegen" "Apps zoeken" "Apps laden…" @@ -80,7 +80,7 @@ "Map: %1$s" "Widgets" "Achtergrond" - "Stijlen en achtergronden" + "Stijl en achtergrond" "Instellingen startscherm" "Uitgeschakeld door je beheerder" "Draaien van startscherm toestaan" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index e33ef7da70..68859605fb 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -106,7 +106,7 @@ "%1$s – widżety" "Lista widgetów" "Lista widgetów zamknięta" - "Dodaj do strony głównej" + "Dodaj do ekranu głównego" "Przenieś element tutaj" "Element został dodany do ekranu głównego" "Element został usunięty" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 68a08a9eb5..071b71e38f 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -81,7 +81,7 @@ "Widgets" "Imagens de fundo" "Estilos e imagens de fundo" - "Definições da página inicial" + "Definições de início" "Desativada pelo gestor" "Permitir rotação do ecrã principal" "Quando o telemóvel é rodado" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 1744fa16cc..e88ff18b42 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -33,7 +33,7 @@ "Toque duas vezes e segure para selecionar um widget ou usar ações personalizadas." "%1$d × %2$d" "%1$d de largura por %2$d de altura" - "Toque e mantenha pressionado para posicionar manualmente" + "Toque e mantenha pressionado para mover manualmente" "Adicionar automaticamente" "Apps de pesquisa" "Carregando apps…" @@ -81,7 +81,7 @@ "Widgets" "Planos de fundo" "Estilos e planos de fundo" - "Configurações da tela inicial" + "Config. tela inicial" "Desativado pelo administrador" "Permitir rotação da tela inicial" "Quando o smartphone for girado" diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index a7e8f05844..1251d7e3f8 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -51,7 +51,7 @@ "Ecran de pornire" "Eliminați" "Dezinstalați" - "Informații aplicație" + "Informații despre aplicații" "Instalați" "instalează comenzi rapide" "Permite unei aplicații să adauge comenzi rapide fără intervenția utilizatorului." @@ -82,9 +82,9 @@ "Widgeturi" "Imagini de fundal" "Stiluri și imagini de fundal" - "Setări pentru ecranul de pornire" + "Setări ecran de pornire" "Dezactivată de administrator" - "Permiteți rotirea ecranului de pornire" + "Permite rotirea ecranului de pornire" "Când telefonul este rotit" "Puncte de notificare" "Activate" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 9030a75eed..34e267da9b 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -82,8 +82,8 @@ "Папка: %1$s" "Виджеты" "Обои" - "Темы и обои" - "Настройки главного экрана" + "Стили и обои" + "Главный экран" "Функция отключена администратором" "Разрешить поворачивать главный экран" "Когда телефон повернут" diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index 574d3ede01..ef99a59e4e 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -80,8 +80,8 @@ "ෆෝල්ඩරය: %1$s" "විජට්" "වෝල්පේපර" - "විලාස සහ බිතුපත්" - "Home සැකසීම්" + "විලාස සහ වෝල්පේපර" + "නිවසේ සැකසීම්" "ඔබගේ පරිපාලක විසින් අබල කරන ලදී" "මුල් පිටු තිරය කරකැවීමට ඉඩ දෙන්න" "දුරකථනය කරකවන විට" diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 77eeab25ec..340a128d2b 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -83,7 +83,7 @@ "Miniaplikácie" "Tapety" "Štýly a tapety" - "Nastavenia Home" + "Nastavenia plochy" "Zakázané vaším správcom" "Povoliť otáčanie plochy" "Pri otočení telefónu" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index f74fde2eb8..4e52592687 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -105,7 +105,7 @@ "Виџети за %1$s" "Листа виџета" "Листа виџета је затворена" - "Додај на почетни екран" + "Додајте на почетни екран" "Премести ставку овде" "Ставка је додата на почетни екран" "Ставка је уклоњена" diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index 7b84ed3c1d..6f33c4f046 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -106,7 +106,7 @@ "Wijeti za %1$s" "Orodha ya wijeti" "Orodha ya wijeti imefungwa" - "Ongeza kwenye skrini ya Kwanza" + "Ongeza kwenye Skrini ya Kwanza" "Hamishia kipengee hapa" "Kipengee kimeongezwa kwenye skrini ya kwanza" "Kipengee kimeondolewa" diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index 47b25816fb..672665e430 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -22,9 +22,9 @@ "Launcher3" "பணியிடம்" - "பயன்பாடு நிறுவப்படவில்லை." - "பயன்பாடு இல்லை" - "இறக்கிய பயன்பாடு பாதுகாப்பு முறையில் முடக்கப்பட்டது" + "ஆப்ஸ் நிறுவப்படவில்லை." + "ஆப்ஸ் இல்லை" + "இறக்கிய ஆப்ஸ் பாதுகாப்பு முறையில் முடக்கப்பட்டது" "பாதுகாப்புப் பயன்முறையில் விட்ஜெட்கள் முடக்கப்பட்டுள்ளன" "ஷார்ட்கட் இல்லை" "முகப்புத் திரை" @@ -51,18 +51,18 @@ "முகப்பு" "அகற்று" "நிறுவல் நீக்கு" - "பயன்பாட்டுத் தகவல்" + "ஆப்ஸ் தகவல்" "நிறுவு" "குறுக்குவழிகளை நிறுவுதல்" - "பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளைச் சேர்க்கப் பயன்பாட்டை அனுமதிக்கிறது." + "பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளைச் சேர்க்கப் ஆப்ஸை அனுமதிக்கிறது." "முகப்பின் அமைப்பு மற்றும் குறுக்குவழிகளைப் படித்தல்" - "முகப்பில் உள்ள அமைப்பு மற்றும் குறுக்குவழிகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது." + "முகப்பில் உள்ள அமைப்பு மற்றும் குறுக்குவழிகளைப் படிக்க ஆப்ஸை அனுமதிக்கிறது." "முகப்பின் அமைப்பு மற்றும் குறுக்குவழிகளை எழுதுதல்" - "முகப்பில் உள்ள அமைப்பு மற்றும் குறுக்குவழிகளை மாற்ற பயன்பாட்டை அனுமதிக்கிறது." + "முகப்பில் உள்ள அமைப்பு மற்றும் குறுக்குவழிகளை மாற்ற ஆப்ஸை அனுமதிக்கிறது." "ஃபோன் அழைப்புகள் செய்ய, %1$s அனுமதிக்கப்படவில்லை" "விட்ஜெட்டை ஏற்றுவதில் சிக்கல்" "அமைவு" - "இது அமைப்பு பயன்பாடு என்பதால் நிறுவல் நீக்கம் செய்ய முடியாது." + "இது அமைப்பு ஆப்ஸ் என்பதால் நிறுவல் நீக்கம் செய்ய முடியாது." "பெயரிடப்படாத கோப்புறை" "%1$s முடக்கப்பட்டது" @@ -78,7 +78,7 @@ "கோப்புறை மூடப்பட்டது" "கோப்புறை %1$s என மறுபெயரிடப்பட்டது" "கோப்புறை: %1$s" - "ஷார்ட்கட்ஸ்" + "விட்ஜெட்கள்" "வால்பேப்பர்கள்" "ஸ்டைல்கள் & வால்பேப்பர்கள்" "முகப்பு அமைப்புகள்" @@ -93,12 +93,12 @@ "அமைப்புகளை மாற்று" "அறிவிப்புப் புள்ளிகளைக் காட்டு" "முகப்புத் திரையில் ஐகானைச் சேர்" - "புதிய பயன்பாடுகளுக்கு" + "புதிய ஆப்ஸை நிறுவும்போது" "தெரியாதது" "அகற்று" "தேடு" - "பயன்பாடு நிறுவப்படவில்லை" - "ஐகானுக்கான பயன்பாடு நிறுவப்படவில்லை. இதை அகற்றலாம் அல்லது பயன்பாட்டைத் தேடி கைமுறையாக நிறுவலாம்." + "ஆப்ஸ் நிறுவப்படவில்லை" + "ஐகானுக்கான ஆப்ஸ் நிறுவப்படவில்லை. இதை அகற்றலாம் அல்லது பயன்பாட்டைத் தேடி கைமுறையாக நிறுவலாம்." "%1$sஐப் பதிவிறக்குகிறது, %2$s முடிந்தது" "%1$sஐ நிறுவுவதற்காகக் காத்திருக்கிறது" "%1$s விட்ஜெட்டுகள்" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 528ce481bd..c8f70fe058 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -80,7 +80,7 @@ "ఫోల్డర్: %1$s" "విడ్జెట్‌లు" "వాల్‌పేపర్‌లు" - "శైలులు & వాల్‌పేపర్‌లు" + "స్ట‌యిల్స్‌ & వాల్‌పేపర్‌లు" "హోమ్ సెట్టింగ్‌లు" "మీ నిర్వాహకులు నిలిపివేసారు" "హోమ్ స్క్రీన్ భ్రమణాన్ని అనుమతించండి" diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index f0c241e9e8..0df94c7104 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -98,7 +98,7 @@ "Alisin" "Maghanap" "Hindi naka-install ang app na ito" - "Hindi naka-install ang app para sa icon na ito. Maaari mo itong alisin, o maaari mong hanapin ang app at i-install ito nang manu-mano." + "Hindi naka-install ang app para sa icon na ito. Puwede mo itong alisin, o maaari mong hanapin ang app at i-install ito nang manual." "Dina-download na ang %1$s, tapos na ang %2$s" "Hinihintay nang mag-install ang %1$s" "Mga widget ng %1$s" diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index ad51464a32..13ba701815 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -82,8 +82,8 @@ "Папка %1$s" "Віджети" "Фонові малюнки" - "Стилі й фонові малюнки" - "Налаштування Home" + "Стиль і фон" + "Налаштування головного екрана" "Вимкнув адміністратор" "Дозволити обертання головного екрана" "Коли телефон обертається" @@ -94,7 +94,7 @@ "Щоб показувати значки сповіщень, увімкніть сповіщення в додатку %1$s" "Змінити налаштування" "Показувати значки сповіщень" - "Додати значок на головний екран" + "Додавати значок на головний екран" "Для нових додатків" "Невідомо" "Прибрати" diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index 5d7218d37e..4f776701e5 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -33,7 +33,7 @@ "کوئی ویجٹ منتخب کرنے یا حسب ضرورت کاروائیاں استعمال کرنے کیلئے دو بار تھپتھپائیں اور پکڑے رکھیں۔" "%1$d × %2$d" "‏%1$d چوڑا اور ‎%2$d اونچا" - "‏دستی طور پر رکھنے کیلئے ‎& ٹچ کرکے ہولڈ کریں" + "‏دستی طور پر رکھنے کیلئے ‎ٹچ کر کے دبائے رکھیں" "خود کار طور پر شامل کریں" "ایپس تلاش کریں" "ایپس لوڈ کی جا رہی ہیں…" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index d34a64f93a..69084d7041 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -33,7 +33,7 @@ "Ikki marta bosib va bosib turgan holatda vidjetni tanlang yoki maxsus amaldan foydalaning." "%1$d × %2$d" "Eni %1$d, bo‘yi %2$d" - "Qo‘lda joylashtirish uchun bosib turing" + "Joylash uchun bosib turing" "Avtomatik chiqarish" "Ilovalarni qidirish" "Ilovalar yuklanmoqda…" @@ -83,7 +83,7 @@ "Mavzu va fon rasmlari" "Bosh ekran sozlamalari" "Administrator tomonidan o‘chirilgan" - "Asosiy ekranni aylantirishga ruxsat berish" + "Bosh ekranni burishga ruxsat" "Telefon burilganda" "Bildirishnoma belgilari" "Yoniq" @@ -95,7 +95,7 @@ "Bosh ekranga ikonka chiqarish" "Yangi o‘rnatilgan ilovalar ikonkasini bosh ekranga chiqarish" "Noma’lum" - "O‘chirish" + "Olib tashlash" "Qidirish" "Ushbu ilova o‘rnatilmagan" "Ilova o‘rnatilmagan. Belgini o‘chirib tashlashingiz yoki ilovani topib, uni qo‘lda o‘rnatishingiz mumkin." @@ -104,15 +104,15 @@ "%1$s vidjetlari" "Vidjetlar ro‘yxati" "Vidjetlar ro‘yxati yopildi" - "Bosh ekranga qo‘shish" + "Bosh ekranga chiqarish" "Obyektni bu yerga ko‘chirish" "Obyekt bosh ekranga qo‘shildi" "Obyekt o‘chirib tashlandi" "Qaytarish" "Obyektni ko‘chirib o‘tkazish" - "%1$s %2$s katakka ko‘chirib o‘tkazish" - "%1$s-joyga ko‘chirib o‘tkazish" - "Sevimlilarga (%1$s) ko‘chirib o‘tkazish" + "%1$s %2$s katakka olish" + "%1$s-joyga olish" + "Sevimlilarga olish (%1$s)" "Element ko‘chirib o‘tkazildi" "%1$s jildiga qo‘shish" "%1$s ilovasi bor jildga qo‘shish" diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 174ec7fe95..71decfca68 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -33,7 +33,7 @@ "Nhấn đúp và giữ để chọn tiện ích hoặc sử dụng tác vụ tùy chỉnh." "%1$d × %2$d" "Rộng %1$d x cao %2$d" - "Chạm và giữ để đặt theo cách thủ công" + "Chạm và giữ để thêm theo cách thủ công" "Tự động thêm" "Tìm kiếm ứng dụng" "Đang tải ứng dụng…" @@ -78,7 +78,7 @@ "Đã đóng thư mục" "Đã đổi tên thư mục thành %1$s" "Thư mục: %1$s" - "Tiện ích con" + "Tiện ích" "Hình nền" "Kiểu và hình nền" "Cài đặt màn hình chính" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index fd31875a98..9804af1e89 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -33,7 +33,7 @@ "点按两次并按住微件即可选择微件,您也可以使用自定义操作。" "%1$d × %2$d" "宽 %1$d,高 %2$d" - "触摸并按住即可手动放置" + "轻触并按住即可手动放置" "自动添加" "搜索应用" "正在加载应用…" diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index de0fa89a0c..e7377440c1 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -81,7 +81,7 @@ "小工具" "桌布" "樣式和桌布" - "主螢幕設定" + "主畫面設定" "已由您的管理員停用" "允許主畫面旋轉" "當手機旋轉時" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 4d37d721f7..e971b69f1f 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -33,7 +33,7 @@ "輕觸兩下並按住小工具即可選取,你也可以使用自訂動作。" "%1$d × %2$d" "寬度為 %1$d,高度為 %2$d" - "按住即可手動放置" + "按住圖示即可手動新增" "自動新增" "搜尋應用程式" "正在載入應用程式…" @@ -81,7 +81,7 @@ "小工具" "桌布" "樣式和桌布" - "Home 設定" + "主螢幕設定" "已由你的管理員停用" "允許旋轉主螢幕" "當手機旋轉時" diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 2f801e04b9..7085c60521 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -32,6 +32,7 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.text.TextUtils.TruncateAt; import android.util.AttributeSet; +import android.util.Log; import android.util.Property; import android.util.TypedValue; import android.view.KeyEvent; @@ -52,6 +53,7 @@ import com.android.launcher3.icons.DotRenderer; import com.android.launcher3.icons.IconCache.IconLoadRequest; import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver; import com.android.launcher3.model.PackageItemInfo; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.views.ActivityContext; import java.text.NumberFormat; @@ -304,6 +306,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, @Override public boolean onTouchEvent(MotionEvent event) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_START_TAG, "BubbleTextView.onTouchEvent " + event); + } // Call the superclass onTouchEvent first, because sometimes it changes the state to // isPressed() on an ACTION_UP boolean result = super.onTouchEvent(event); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 4e905c7265..80ea78f194 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1353,19 +1353,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, if (isActionMain) { if (!internalStateHandled) { - // Note: There should be at most one log per method call. This is enforced - // implicitly by using if-else statements. - UserEventDispatcher ued = getUserEventDispatcher(); - AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(this); - if (topOpenView != null) { - topOpenView.logActionCommand(Action.Command.HOME_INTENT); - } else if (alreadyOnHome) { - Target target = newContainerTarget(mStateManager.getState().containerType); - target.pageIndex = mWorkspace.getCurrentPage(); - ued.logActionCommand(Action.Command.HOME_INTENT, target, - newContainerTarget(ContainerType.WORKSPACE)); - } - // In all these cases, only animate if we're already on home AbstractFloatingView.closeAllOpenViews(this, isStarted()); @@ -1385,6 +1372,13 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, } } + // Handle HOME_INTENT + UserEventDispatcher ued = getUserEventDispatcher(); + Target target = newContainerTarget(mStateManager.getState().containerType); + target.pageIndex = mWorkspace.getCurrentPage(); + ued.logActionCommand(Action.Command.HOME_INTENT, target, + newContainerTarget(ContainerType.WORKSPACE)); + final View v = getWindow().peekDecorView(); if (v != null && v.getWindowToken() != null) { UiThreadHelper.hideKeyboardAsync(this, v.getWindowToken()); diff --git a/src/com/android/launcher3/LauncherAppTransitionManager.java b/src/com/android/launcher3/LauncherAppTransitionManager.java index fb50dfbbb5..4bddc6a4ea 100644 --- a/src/com/android/launcher3/LauncherAppTransitionManager.java +++ b/src/com/android/launcher3/LauncherAppTransitionManager.java @@ -51,4 +51,8 @@ public class LauncherAppTransitionManager implements ResourceBasedOverride { } return ActivityOptions.makeClipRevealAnimation(v, left, top, width, height); } + + public boolean supportsAdaptiveIconAnimation() { + return false; + } } diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index c63f976a87..1480648895 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -268,8 +268,6 @@ public class LauncherState { if (this != NORMAL) { LauncherStateManager lsm = launcher.getStateManager(); LauncherState lastState = lsm.getLastState(); - launcher.getUserEventDispatcher().logActionCommand(Action.Command.BACK, - containerType, lastState.containerType); lsm.goToState(lastState); } } diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index cc9bda7106..7bdbb95f79 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -69,6 +69,7 @@ import com.android.launcher3.compat.ShortcutConfigActivityInfo; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.FolderAdaptiveIcon; import com.android.launcher3.graphics.RotationMode; +import com.android.launcher3.graphics.TintedDrawableSpan; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.shortcuts.ShortcutKey; @@ -562,6 +563,20 @@ public final class Utilities { return spanned; } + /** + * Prefixes a text with the provided icon + */ + public static CharSequence prefixTextWithIcon(Context context, int iconRes, CharSequence msg) { + // Update the hint to contain the icon. + // Prefix the original hint with two spaces. The first space gets replaced by the icon + // using span. The second space is used for a singe space character between the hint + // and the icon. + SpannableString spanned = new SpannableString(" " + msg); + spanned.setSpan(new TintedDrawableSpan(context, iconRes), + 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + return spanned; + } + public static SharedPreferences getPrefs(Context context) { return context.getSharedPreferences( LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE); diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index d68ff4451d..ea9b077c62 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -26,6 +26,7 @@ import android.os.Process; import android.text.Selection; import android.text.SpannableStringBuilder; import android.util.AttributeSet; +import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -625,6 +626,9 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo @Override public boolean dispatchTouchEvent(MotionEvent ev) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_START_TAG, "AllAppsContainerView.dispatchTouchEvent " + ev); + } final boolean result = super.dispatchTouchEvent(ev); switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java index 1ff484b495..31fcc8c642 100644 --- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java +++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java @@ -20,6 +20,7 @@ import static android.view.View.MeasureSpec.getSize; import static android.view.View.MeasureSpec.makeMeasureSpec; import static com.android.launcher3.LauncherState.ALL_APPS_HEADER; +import static com.android.launcher3.Utilities.prefixTextWithIcon; import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR; import android.content.Context; @@ -40,6 +41,7 @@ import com.android.launcher3.ExtendedEditText; import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.R; +import com.android.launcher3.Utilities; import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.allapps.AlphabeticalAppsList; @@ -89,14 +91,7 @@ public class AppsSearchContainerLayout extends ExtendedEditText mFixedTranslationY = getTranslationY(); mMarginTopAdjusting = mFixedTranslationY - getPaddingTop(); - // Update the hint to contain the icon. - // Prefix the original hint with two spaces. The first space gets replaced by the icon - // using span. The second space is used for a singe space character between the hint - // and the icon. - SpannableString spanned = new SpannableString(" " + getHint()); - spanned.setSpan(new TintedDrawableSpan(getContext(), R.drawable.ic_allapps_search), - 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); - setHint(spanned); + setHint(prefixTextWithIcon(getContext(), R.drawable.ic_allapps_search, getHint())); } @Override diff --git a/src/com/android/launcher3/graphics/TintedDrawableSpan.java b/src/com/android/launcher3/graphics/TintedDrawableSpan.java index d7195750d6..0bfc435ccc 100644 --- a/src/com/android/launcher3/graphics/TintedDrawableSpan.java +++ b/src/com/android/launcher3/graphics/TintedDrawableSpan.java @@ -32,7 +32,7 @@ public class TintedDrawableSpan extends DynamicDrawableSpan { public TintedDrawableSpan(Context context, int resourceId) { super(ALIGN_BOTTOM); - mDrawable = context.getDrawable(resourceId); + mDrawable = context.getDrawable(resourceId).mutate(); mOldTint = 0; mDrawable.setTint(0); } diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java index 3b74307dbb..763240885e 100644 --- a/src/com/android/launcher3/icons/LauncherIcons.java +++ b/src/com/android/launcher3/icons/LauncherIcons.java @@ -189,6 +189,7 @@ public class LauncherIcons extends BaseIconFactory implements AutoCloseable { private String getBadgePackage(ShortcutInfo si) { String whitelistedPkg = mContext.getString(R.string.shortcutinfo_badgepkg_whitelist); if (whitelistedPkg.equals(si.getPackage()) + && si.getExtras() != null && si.getExtras().containsKey(EXTRA_BADGEPKG)) { return si.getExtras().getString(EXTRA_BADGEPKG); } diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java index f858dc4c69..85f763d095 100644 --- a/src/com/android/launcher3/touch/ItemClickHandler.java +++ b/src/com/android/launcher3/touch/ItemClickHandler.java @@ -49,6 +49,7 @@ import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.PackageManagerHelper; +import com.android.launcher3.views.FloatingIconView; import com.android.launcher3.widget.PendingAppWidgetHostView; import com.android.launcher3.widget.WidgetAddFlowHandler; @@ -259,6 +260,10 @@ public class ItemClickHandler { intent.setPackage(null); } } + if (v != null && launcher.getAppTransitionManager().supportsAdaptiveIconAnimation()) { + // Preload the icon to reduce latency b/w swapping the floating view with the original. + FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */); + } launcher.startActivitySafely(v, intent, item, sourceContainer); } } diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java index 939b0f2b9f..ac152dbffa 100644 --- a/src/com/android/launcher3/views/BaseDragLayer.java +++ b/src/com/android/launcher3/views/BaseDragLayer.java @@ -29,6 +29,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.os.Build; import android.util.AttributeSet; +import android.util.Log; import android.util.Property; import android.view.MotionEvent; import android.view.View; @@ -240,6 +241,9 @@ public abstract class BaseDragLayer @Override public boolean dispatchTouchEvent(MotionEvent ev) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_START_TAG, "BaseDragLayer.dispatchTouchEvent " + ev); + } switch (ev.getAction()) { case ACTION_DOWN: { float x = ev.getX(); diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index 339681cd69..b6c4fedac9 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -17,6 +17,7 @@ package com.android.launcher3.views; import static com.android.launcher3.LauncherAnimUtils.DRAWABLE_ALPHA; import static com.android.launcher3.Utilities.getBadge; +import static com.android.launcher3.Utilities.getFullDrawable; import static com.android.launcher3.Utilities.mapToRange; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM; @@ -42,6 +43,7 @@ import android.os.Build; import android.os.CancellationSignal; import android.os.Handler; import android.util.AttributeSet; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; @@ -65,6 +67,7 @@ import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.shortcuts.DeepShortcutView; import androidx.annotation.Nullable; +import androidx.annotation.UiThread; import androidx.annotation.WorkerThread; import androidx.dynamicanimation.animation.FloatPropertyCompat; import androidx.dynamicanimation.animation.SpringAnimation; @@ -77,6 +80,11 @@ import androidx.dynamicanimation.animation.SpringForce; public class FloatingIconView extends View implements Animator.AnimatorListener, ClipPathView, OnGlobalLayoutListener { + private static final String TAG = FloatingIconView.class.getSimpleName(); + + // Manages loading the icon on a worker thread + private static @Nullable IconLoadResult sIconLoadResult; + public static final float SHAPE_PROGRESS_DURATION = 0.10f; private static final int FADE_DURATION_MS = 200; private static final Rect sTmpRect = new Rect(); @@ -126,6 +134,8 @@ public class FloatingIconView extends View implements private boolean mIsAdaptiveIcon = false; private boolean mIsOpening; + private IconLoadResult mIconLoadResult; + private @Nullable Drawable mBadge; private @Nullable Drawable mForeground; private @Nullable Drawable mBackground; @@ -299,8 +309,8 @@ public class FloatingIconView extends View implements * @param v The view to copy * @param positionOut Rect that will hold the size and position of v. */ - private void matchPositionOf(View v, RectF positionOut) { - float rotation = getLocationBoundsForView(v, positionOut); + private void matchPositionOf(Launcher launcher, View v, boolean isOpening, RectF positionOut) { + float rotation = getLocationBoundsForView(launcher, v, isOpening, positionOut); final LayoutParams lp = new LayoutParams( Math.round(positionOut.width()), Math.round(positionOut.height())); @@ -328,8 +338,9 @@ public class FloatingIconView extends View implements * - For DeepShortcutView, we return the bounds of the icon view. * - For BubbleTextView, we return the icon bounds. */ - private float getLocationBoundsForView(View v, RectF outRect) { - boolean ignoreTransform = !mIsOpening; + private static float getLocationBoundsForView(Launcher launcher, View v, boolean isOpening, + RectF outRect) { + boolean ignoreTransform = !isOpening; if (v instanceof DeepShortcutView) { v = ((DeepShortcutView) v).getBubbleText(); ignoreTransform = false; @@ -353,7 +364,7 @@ public class FloatingIconView extends View implements float[] points = new float[] {iconBounds.left, iconBounds.top, iconBounds.right, iconBounds.bottom}; float[] rotation = new float[] {0}; - Utilities.getDescendantCoordRelativeToAncestor(v, mLauncher.getDragLayer(), points, + Utilities.getDescendantCoordRelativeToAncestor(v, launcher.getDragLayer(), points, false, ignoreTransform, rotation); outRect.set( Math.min(points[0], points[2]), @@ -363,148 +374,217 @@ public class FloatingIconView extends View implements return rotation[0]; } + /** + * Loads the icon and saves the results to {@link #sIconLoadResult}. + * Runs onIconLoaded callback (if any), which signifies that the FloatingIconView is + * ready to display the icon. Otherwise, the FloatingIconView will grab the results when its + * initialized. + * + * @param originalView The View that the FloatingIconView will replace. + * @param info ItemInfo of the originalView + * @param pos The position of the view. + */ @WorkerThread @SuppressWarnings("WrongThread") - private void getIcon(View v, ItemInfo info, boolean isOpening, - Runnable onIconLoadedRunnable, CancellationSignal loadIconSignal) { - final LayoutParams lp = (LayoutParams) getLayoutParams(); + private static void getIconResult(Launcher l, View originalView, ItemInfo info, RectF pos, + IconLoadResult iconLoadResult) { Drawable drawable = null; + Drawable badge = null; boolean supportsAdaptiveIcons = ADAPTIVE_ICON_WINDOW_ANIM.get() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; - Drawable btvIcon = v instanceof BubbleTextView ? ((BubbleTextView) v).getIcon() : null; + Drawable btvIcon = originalView instanceof BubbleTextView + ? ((BubbleTextView) originalView).getIcon() : null; if (info instanceof SystemShortcut) { - if (v instanceof ImageView) { - drawable = ((ImageView) v).getDrawable(); - } else if (v instanceof DeepShortcutView) { - drawable = ((DeepShortcutView) v).getIconView().getBackground(); + if (originalView instanceof ImageView) { + drawable = ((ImageView) originalView).getDrawable(); + } else if (originalView instanceof DeepShortcutView) { + drawable = ((DeepShortcutView) originalView).getIconView().getBackground(); } else { - drawable = v.getBackground(); + drawable = originalView.getBackground(); } } else { - boolean isFolderIcon = v instanceof FolderIcon; - int width = isFolderIcon ? v.getWidth() : lp.width; - int height = isFolderIcon ? v.getHeight() : lp.height; + boolean isFolderIcon = originalView instanceof FolderIcon; + int width = isFolderIcon ? originalView.getWidth() : (int) pos.width(); + int height = isFolderIcon ? originalView.getHeight() : (int) pos.height(); if (supportsAdaptiveIcons) { - drawable = Utilities.getFullDrawable(mLauncher, info, width, height, false, - sTmpObjArray); + drawable = getFullDrawable(l, info, width, height, false, sTmpObjArray); if (drawable instanceof AdaptiveIconDrawable) { - mBadge = getBadge(mLauncher, info, sTmpObjArray[0]); + badge = getBadge(l, info, sTmpObjArray[0]); } else { // The drawable we get back is not an adaptive icon, so we need to use the // BubbleTextView icon that is already legacy treated. drawable = btvIcon; } } else { - if (v instanceof BubbleTextView) { + if (originalView instanceof BubbleTextView) { // Similar to DragView, we simply use the BubbleTextView icon here. drawable = btvIcon; } else { - drawable = Utilities.getFullDrawable(mLauncher, info, width, height, false, - sTmpObjArray); + drawable = getFullDrawable(l, info, width, height, false, sTmpObjArray); } } } - Drawable finalDrawable = drawable == null ? null - : drawable.getConstantState().newDrawable(); - boolean isAdaptiveIcon = supportsAdaptiveIcons - && finalDrawable instanceof AdaptiveIconDrawable; - int iconOffset = getOffsetForIconBounds(finalDrawable); + drawable = drawable == null ? null : drawable.getConstantState().newDrawable(); + int iconOffset = getOffsetForIconBounds(l, drawable, pos); + synchronized (iconLoadResult) { + iconLoadResult.drawable = drawable; + iconLoadResult.badge = badge; + iconLoadResult.iconOffset = iconOffset; + if (iconLoadResult.onIconLoaded != null) { + l.getMainExecutor().execute(iconLoadResult.onIconLoaded); + iconLoadResult.onIconLoaded = null; + } + iconLoadResult.isIconLoaded = true; + } + } - mLauncher.getMainExecutor().execute(() -> { - if (isAdaptiveIcon) { - mIsAdaptiveIcon = true; - boolean isFolderIcon = finalDrawable instanceof FolderAdaptiveIcon; + /** + * Sets the drawables of the {@param originalView} onto this view. + * + * @param originalView The View that the FloatingIconView will replace. + * @param drawable The drawable of the original view. + * @param badge The badge of the original view. + * @param iconOffset The amount of offset needed to match this view with the original view. + */ + @UiThread + private void setIcon(View originalView, @Nullable Drawable drawable, @Nullable Drawable badge, + int iconOffset) { + mBadge = badge; - AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) finalDrawable; - Drawable background = adaptiveIcon.getBackground(); - if (background == null) { - background = new ColorDrawable(Color.TRANSPARENT); + mIsAdaptiveIcon = drawable instanceof AdaptiveIconDrawable; + if (mIsAdaptiveIcon) { + boolean isFolderIcon = drawable instanceof FolderAdaptiveIcon; + + AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) drawable; + Drawable background = adaptiveIcon.getBackground(); + if (background == null) { + background = new ColorDrawable(Color.TRANSPARENT); + } + mBackground = background; + Drawable foreground = adaptiveIcon.getForeground(); + if (foreground == null) { + foreground = new ColorDrawable(Color.TRANSPARENT); + } + mForeground = foreground; + + final LayoutParams lp = (LayoutParams) getLayoutParams(); + final int originalHeight = lp.height; + final int originalWidth = lp.width; + + int blurMargin = mBlurSizeOutline / 2; + mFinalDrawableBounds.set(0, 0, originalWidth, originalHeight); + + if (!isFolderIcon) { + mFinalDrawableBounds.inset(iconOffset - blurMargin, iconOffset - blurMargin); + } + mForeground.setBounds(mFinalDrawableBounds); + mBackground.setBounds(mFinalDrawableBounds); + + mStartRevealRect.set(0, 0, originalWidth, originalHeight); + + if (mBadge != null) { + mBadge.setBounds(mStartRevealRect); + if (!mIsOpening && !isFolderIcon) { + DRAWABLE_ALPHA.set(mBadge, 0); } - mBackground = background; - Drawable foreground = adaptiveIcon.getForeground(); - if (foreground == null) { - foreground = new ColorDrawable(Color.TRANSPARENT); + } + + if (isFolderIcon) { + ((FolderIcon) originalView).getPreviewBounds(sTmpRect); + float bgStroke = ((FolderIcon) originalView).getBackgroundStrokeWidth(); + if (mForeground instanceof ShiftedBitmapDrawable) { + ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mForeground; + sbd.setShiftX(sbd.getShiftX() - sTmpRect.left - bgStroke); + sbd.setShiftY(sbd.getShiftY() - sTmpRect.top - bgStroke); } - mForeground = foreground; - - final int originalHeight = lp.height; - final int originalWidth = lp.width; - - int blurMargin = mBlurSizeOutline / 2; - mFinalDrawableBounds.set(0, 0, originalWidth, originalHeight); - if (!isFolderIcon) { - mFinalDrawableBounds.inset(iconOffset - blurMargin, iconOffset - blurMargin); + if (mBadge instanceof ShiftedBitmapDrawable) { + ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mBadge; + sbd.setShiftX(sbd.getShiftX() - sTmpRect.left - bgStroke); + sbd.setShiftY(sbd.getShiftY() - sTmpRect.top - bgStroke); } - mForeground.setBounds(mFinalDrawableBounds); - mBackground.setBounds(mFinalDrawableBounds); - - mStartRevealRect.set(0, 0, originalWidth, originalHeight); - - if (mBadge != null) { - mBadge.setBounds(mStartRevealRect); - if (!isOpening && !isFolderIcon) { - DRAWABLE_ALPHA.set(mBadge, 0); - } - } - - if (isFolderIcon) { - ((FolderIcon) v).getPreviewBounds(sTmpRect); - float bgStroke = ((FolderIcon) v).getBackgroundStrokeWidth(); - if (mForeground instanceof ShiftedBitmapDrawable) { - ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mForeground; - sbd.setShiftX(sbd.getShiftX() - sTmpRect.left - bgStroke); - sbd.setShiftY(sbd.getShiftY() - sTmpRect.top - bgStroke); - } - if (mBadge instanceof ShiftedBitmapDrawable) { - ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mBadge; - sbd.setShiftX(sbd.getShiftX() - sTmpRect.left - bgStroke); - sbd.setShiftY(sbd.getShiftY() - sTmpRect.top - bgStroke); - } - } else { - Utilities.scaleRectAboutCenter(mStartRevealRect, - IconShape.getNormalizationScale()); - } - - float aspectRatio = mLauncher.getDeviceProfile().aspectRatio; - if (mIsVerticalBarLayout) { - lp.width = (int) Math.max(lp.width, lp.height * aspectRatio); - } else { - lp.height = (int) Math.max(lp.height, lp.width * aspectRatio); - } - layout(lp.leftMargin, lp.topMargin, lp.leftMargin + lp.width, lp.topMargin - + lp.height); - - float scale = Math.max((float) lp.height / originalHeight, - (float) lp.width / originalWidth); - float bgDrawableStartScale; - if (isOpening) { - bgDrawableStartScale = 1f; - mOutline.set(0, 0, originalWidth, originalHeight); - } else { - bgDrawableStartScale = scale; - mOutline.set(0, 0, lp.width, lp.height); - } - setBackgroundDrawableBounds(bgDrawableStartScale); - mEndRevealRect.set(0, 0, lp.width, lp.height); - setOutlineProvider(new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - outline.setRoundRect(mOutline, mTaskCornerRadius); - } - }); - setClipToOutline(true); } else { - setBackground(finalDrawable); - setClipToOutline(false); + Utilities.scaleRectAboutCenter(mStartRevealRect, + IconShape.getNormalizationScale()); } - if (!loadIconSignal.isCanceled()) { - onIconLoadedRunnable.run(); + float aspectRatio = mLauncher.getDeviceProfile().aspectRatio; + if (mIsVerticalBarLayout) { + lp.width = (int) Math.max(lp.width, lp.height * aspectRatio); + } else { + lp.height = (int) Math.max(lp.height, lp.width * aspectRatio); } - invalidate(); - invalidateOutline(); - }); + layout(lp.leftMargin, lp.topMargin, lp.leftMargin + lp.width, lp.topMargin + + lp.height); + + float scale = Math.max((float) lp.height / originalHeight, + (float) lp.width / originalWidth); + float bgDrawableStartScale; + if (mIsOpening) { + bgDrawableStartScale = 1f; + mOutline.set(0, 0, originalWidth, originalHeight); + } else { + bgDrawableStartScale = scale; + mOutline.set(0, 0, lp.width, lp.height); + } + setBackgroundDrawableBounds(bgDrawableStartScale); + mEndRevealRect.set(0, 0, lp.width, lp.height); + setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setRoundRect(mOutline, mTaskCornerRadius); + } + }); + setClipToOutline(true); + } else { + setBackground(drawable); + setClipToOutline(false); + } + + invalidate(); + invalidateOutline(); + } + + /** + * Checks if the icon result is loaded. If true, we set the icon immediately. Else, we add a + * callback to set the icon once the icon result is loaded. + */ + private void checkIconResult(View originalView, boolean isOpening) { + CancellationSignal cancellationSignal = new CancellationSignal(); + if (!isOpening) { + // Hide immediately since the floating view starts at a different location. + originalView.setVisibility(INVISIBLE); + cancellationSignal.setOnCancelListener(() -> originalView.setVisibility(VISIBLE)); + } + + if (mIconLoadResult == null) { + Log.w(TAG, "No icon load result found in checkIconResult"); + return; + } + + synchronized (mIconLoadResult) { + if (mIconLoadResult.isIconLoaded) { + setIcon(originalView, mIconLoadResult.drawable, mIconLoadResult.badge, + mIconLoadResult.iconOffset); + if (isOpening) { + originalView.setVisibility(INVISIBLE); + } + } else { + mIconLoadResult.onIconLoaded = () -> { + if (cancellationSignal.isCanceled()) { + return; + } + if (mIconLoadResult.isIconLoaded) { + setIcon(originalView, mIconLoadResult.drawable, mIconLoadResult.badge, + mIconLoadResult.iconOffset); + } + // Delay swapping views until the icon is loaded to prevent a flash. + setVisibility(VISIBLE); + originalView.setVisibility(INVISIBLE); + }; + } + } + mLoadIconSignal = cancellationSignal; } private void setBackgroundDrawableBounds(float scale) { @@ -521,17 +601,19 @@ public class FloatingIconView extends View implements @WorkerThread @SuppressWarnings("WrongThread") - private int getOffsetForIconBounds(Drawable drawable) { + private static int getOffsetForIconBounds(Launcher l, Drawable drawable, RectF position) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || !(drawable instanceof AdaptiveIconDrawable)) { return 0; } + int blurSizeOutline = + l.getResources().getDimensionPixelSize(R.dimen.blur_size_medium_outline); - final LayoutParams lp = (LayoutParams) getLayoutParams(); - Rect bounds = new Rect(0, 0, lp.width + mBlurSizeOutline, lp.height + mBlurSizeOutline); - bounds.inset(mBlurSizeOutline / 2, mBlurSizeOutline / 2); + Rect bounds = new Rect(0, 0, (int) position.width() + blurSizeOutline, + (int) position.height() + blurSizeOutline); + bounds.inset(blurSizeOutline / 2, blurSizeOutline / 2); - try (LauncherIcons li = LauncherIcons.obtain(mLauncher)) { + try (LauncherIcons li = LauncherIcons.obtain(l)) { Utilities.scaleRectAboutCenter(bounds, li.getNormalizer().getScale(drawable, null, null, null)); } @@ -587,7 +669,11 @@ public class FloatingIconView extends View implements } @Override - public void onAnimationStart(Animator animator) {} + public void onAnimationStart(Animator animator) { + if (mIconLoadResult != null && mIconLoadResult.isIconLoaded) { + setVisibility(View.VISIBLE); + } + } @Override public void onAnimationCancel(Animator animator) {} @@ -598,7 +684,8 @@ public class FloatingIconView extends View implements @Override public void onGlobalLayout() { if (mOriginalIcon.isAttachedToWindow() && mPositionOut != null) { - float rotation = getLocationBoundsForView(mOriginalIcon, sTmpRectF); + float rotation = getLocationBoundsForView(mLauncher, mOriginalIcon, mIsOpening, + sTmpRectF); if (rotation != mRotation || !sTmpRectF.equals(mPositionOut)) { updatePosition(rotation, sTmpRectF, (LayoutParams) getLayoutParams()); if (mOnTargetChangeRunnable != null) { @@ -612,6 +699,22 @@ public class FloatingIconView extends View implements mOnTargetChangeRunnable = onTargetChangeListener; } + /** + * Loads the icon drawable on a worker thread to reduce latency between swapping views. + */ + @UiThread + public static IconLoadResult fetchIcon(Launcher l, View v, ItemInfo info, boolean isOpening) { + IconLoadResult result = new IconLoadResult(); + new Handler(LauncherModel.getWorkerLooper()).postAtFrontOfQueue(() -> { + RectF position = new RectF(); + getLocationBoundsForView(l, v, isOpening, position); + getIconResult(l, v, info, position, result); + }); + + sIconLoadResult = result; + return result; + } + /** * Creates a floating icon view for {@param originalView}. * @param originalView The view to copy @@ -624,38 +727,30 @@ public class FloatingIconView extends View implements boolean hideOriginal, RectF positionOut, boolean isOpening) { final DragLayer dragLayer = launcher.getDragLayer(); ViewGroup parent = (ViewGroup) dragLayer.getParent(); - FloatingIconView view = launcher.getViewCache().getView(R.layout.floating_icon_view, launcher, parent); view.recycle(); + // Get the drawable on the background thread + boolean shouldLoadIcon = originalView.getTag() instanceof ItemInfo && hideOriginal; + view.mIconLoadResult = sIconLoadResult; + if (shouldLoadIcon && view.mIconLoadResult == null) { + view.mIconLoadResult = fetchIcon(launcher, originalView, + (ItemInfo) originalView.getTag(), isOpening); + } + sIconLoadResult = null; + view.mIsVerticalBarLayout = launcher.getDeviceProfile().isVerticalBarLayout(); view.mIsOpening = isOpening; - view.mOriginalIcon = originalView; view.mPositionOut = positionOut; - // Match the position of the original view. - view.matchPositionOf(originalView, positionOut); - // Get the drawable on the background thread + // Match the position of the original view. + view.matchPositionOf(launcher, originalView, isOpening, positionOut); + // Must be called after matchPositionOf so that we know what size to load. - if (originalView.getTag() instanceof ItemInfo && hideOriginal) { - view.mLoadIconSignal = new CancellationSignal(); - Runnable onIconLoaded = () -> { - // Delay swapping views until the icon is loaded to prevent a flash. - view.setVisibility(VISIBLE); - originalView.setVisibility(INVISIBLE); - }; - if (!isOpening) { - // Hide immediately since the floating view starts at a different location. - originalView.setVisibility(INVISIBLE); - view.mLoadIconSignal.setOnCancelListener(() -> originalView.setVisibility(VISIBLE)); - } - CancellationSignal loadIconSignal = view.mLoadIconSignal; - new Handler(LauncherModel.getWorkerLooper()).postAtFrontOfQueue(() -> { - view.getIcon(originalView, (ItemInfo) originalView.getTag(), isOpening, - onIconLoaded, loadIconSignal); - }); + if (shouldLoadIcon) { + view.checkIconResult(originalView, isOpening); } // We need to add it to the overlay, but keep it invisible until animation starts.. @@ -779,5 +874,14 @@ public class FloatingIconView extends View implements mFgSpringY.cancel(); mBadge = null; sTmpObjArray[0] = null; + mIconLoadResult = null; + } + + private static class IconLoadResult { + Drawable drawable; + Drawable badge; + int iconOffset; + Runnable onIconLoaded; + boolean isIconLoaded; } } diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java index 35e44bb95c..dce839f397 100644 --- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java +++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java @@ -44,6 +44,7 @@ import com.android.launcher3.SimpleOnStylusPressListener; import com.android.launcher3.StylusEventHelper; import com.android.launcher3.Utilities; import com.android.launcher3.dragndrop.DragLayer; +import com.android.launcher3.util.Themes; import com.android.launcher3.views.BaseDragLayer.TouchCompleteListener; /** @@ -97,6 +98,9 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView if (Utilities.ATLEAST_OREO) { setExecutor(Utilities.THREAD_POOL_EXECUTOR); } + if (Utilities.ATLEAST_Q && Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) { + setOnLightBackground(true); + } } @Override diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index 21d763e30e..9ff354a7eb 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -16,8 +16,6 @@ package com.android.launcher3.tapl; -import static com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel.ZERO_BUTTON; - import android.graphics.Point; import android.graphics.Rect; import android.widget.TextView; @@ -36,7 +34,6 @@ import com.android.launcher3.testing.TestProtocol; */ public class AllApps extends LauncherInstrumentation.VisibleContainer { private static final int MAX_SCROLL_ATTEMPTS = 40; - private static final int MIN_INTERACT_SIZE = 100; private final int mHeight; @@ -65,13 +62,6 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { } final Rect iconBounds = icon.getVisibleBounds(); LauncherInstrumentation.log("hasClickableIcon: icon bounds: " + iconBounds); - if (mLauncher.getNavigationModel() != ZERO_BUTTON) { - final UiObject2 navBar = mLauncher.waitForSystemUiObject("navigation_bar_frame"); - if (iconBounds.bottom >= navBar.getVisibleBounds().top) { - LauncherInstrumentation.log("hasClickableIcon: icon intersects with nav bar"); - return false; - } - } if (iconCenterInSearchBox(allAppsContainer, icon)) { LauncherInstrumentation.log("hasClickableIcon: icon center is under search box"); return false; @@ -96,7 +86,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { @NonNull public AppIcon getAppIcon(String appName) { try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( - "want to get app icon " + appName + " on all apps")) { + "getting app icon " + appName + " on all apps")) { final UiObject2 allAppsContainer = verifyActiveContainer(); final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer, "apps_list_view"); @@ -110,21 +100,28 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { if (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector)) { scrollBackToBeginning(); int attempts = 0; + int scroll = getScroll(allAppsContainer); try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled")) { - while (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector) && - allAppsContainer.scroll(Direction.DOWN, 0.8f)) { + while (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector)) { + mLauncher.scroll(allAppsContainer, Direction.DOWN, 0.8f, null, 50); + final int newScroll = getScroll(allAppsContainer); + if (newScroll == scroll) break; + mLauncher.assertTrue( "Exceeded max scroll attempts: " + MAX_SCROLL_ATTEMPTS, ++attempts <= MAX_SCROLL_ATTEMPTS); verifyActiveContainer(); + scroll = newScroll; } } verifyActiveContainer(); } + mLauncher.assertTrue("Unable to scroll to a clickable icon: " + appName, + hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector)); + final UiObject2 appIcon = mLauncher.getObjectInContainer(appListRecycler, appIconSelector); - ensureIconVisible(appIcon, allAppsContainer, appListRecycler); return new AppIcon(mLauncher, appIcon); } } @@ -162,24 +159,6 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { getInt(TestProtocol.SCROLL_Y_FIELD, -1); } - private void ensureIconVisible( - UiObject2 appIcon, UiObject2 allAppsContainer, UiObject2 appListRecycler) { - final int appHeight = appIcon.getVisibleBounds().height(); - if (appHeight < MIN_INTERACT_SIZE) { - // Try to figure out how much percentage of the container needs to be scrolled in order - // to reveal the app icon to have the MIN_INTERACT_SIZE - final float pct = Math.max(((float) (MIN_INTERACT_SIZE - appHeight)) / mHeight, 0.2f); - mLauncher.scroll(appListRecycler, Direction.DOWN, pct, null, 10); - try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( - "scrolled an icon in all apps to make it visible - and then")) { - mLauncher.waitForIdle(); - verifyActiveContainer(); - } - } - mLauncher.assertTrue("Couldn't scroll app icon to not intersect with the search box", - !iconCenterInSearchBox(allAppsContainer, appIcon)); - } - private UiObject2 getSearchBox(UiObject2 allAppsContainer) { return mLauncher.waitForObjectInContainer(allAppsContainer, "search_container_all_apps"); } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 8ebe525657..2db9d08269 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -208,14 +208,10 @@ public final class LauncherInstrumentation { // app context are not constructed with resources that take overlays into account final Context ctx = baseContext.createPackageContext("android", 0); for (int i = 0; i < 100; ++i) { - log("Interaction mode = " + getCurrentInteractionMode(ctx)); - if (isGesturalMode(ctx)) { - return NavigationModel.ZERO_BUTTON; - } else if (isSwipeUpMode(ctx)) { - return NavigationModel.TWO_BUTTON; - } else if (isLegacyMode(ctx)) { - return NavigationModel.THREE_BUTTON; - } + final int currentInteractionMode = getCurrentInteractionMode(ctx); + final NavigationModel model = getNavigationModel(currentInteractionMode); + log("Interaction mode = " + currentInteractionMode + " (" + model + ")"); + if (model != null) return model; Thread.sleep(100); } fail("Can't detect navigation mode"); @@ -225,6 +221,17 @@ public final class LauncherInstrumentation { return NavigationModel.THREE_BUTTON; } + public static NavigationModel getNavigationModel(int currentInteractionMode) { + if (QuickStepContract.isGesturalMode(currentInteractionMode)) { + return NavigationModel.ZERO_BUTTON; + } else if (QuickStepContract.isSwipeUpMode(currentInteractionMode)) { + return NavigationModel.TWO_BUTTON; + } else if (QuickStepContract.isLegacyMode(currentInteractionMode)) { + return NavigationModel.THREE_BUTTON; + } + return null; + } + public static boolean isAvd() { return Build.MODEL.contains("Cuttlefish"); } @@ -748,19 +755,7 @@ public final class LauncherInstrumentation { return currentTime; } - public static boolean isGesturalMode(Context context) { - return QuickStepContract.isGesturalMode(getCurrentInteractionMode(context)); - } - - public static boolean isSwipeUpMode(Context context) { - return QuickStepContract.isSwipeUpMode(getCurrentInteractionMode(context)); - } - - public static boolean isLegacyMode(Context context) { - return QuickStepContract.isLegacyMode(getCurrentInteractionMode(context)); - } - - private static int getCurrentInteractionMode(Context context) { + public static int getCurrentInteractionMode(Context context) { return getSystemIntegerRes(context, "config_navBarInteractionMode"); }