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

Commit 1d9f23b1 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix DWB banner not showing up for split tasks" into main

parents 9d4f5d1c e081914f
Loading
Loading
Loading
Loading
+65 −62
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ public final class DigitalWellBeingToast {
            SPLIT_GRID_BANNER_SMALL,
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface SPLIT_BANNER_CONFIG{}
    @interface SplitBannerConfig{}

    static final Intent OPEN_APP_USAGE_SETTINGS_TEMPLATE = new Intent(ACTION_APP_USAGE_SETTINGS);
    static final int MINUTE_MS = 60000;
@@ -88,7 +88,6 @@ public final class DigitalWellBeingToast {
    private Task mTask;
    private boolean mHasLimit;

    private long mAppUsageLimitTimeMs;
    private long mAppRemainingTimeMs;
    @Nullable
    private View mBanner;
@@ -96,10 +95,11 @@ public final class DigitalWellBeingToast {
    private float mBannerOffsetPercentage;
    @Nullable
    private SplitBounds mSplitBounds;
    private int mSplitBannerConfig = SPLIT_BANNER_FULLSCREEN;
    private float mSplitOffsetTranslationY;
    private float mSplitOffsetTranslationX;

    private boolean mIsDestroyed = false;

    public DigitalWellBeingToast(RecentsViewContainer container, TaskView taskView) {
        mContainer = container;
        mTaskView = taskView;
@@ -110,12 +110,10 @@ public final class DigitalWellBeingToast {
        mHasLimit = false;
        mTaskView.setContentDescription(mTask.titleDescription);
        replaceBanner(null);
        mAppUsageLimitTimeMs = -1;
        mAppRemainingTimeMs = -1;
    }

    private void setLimit(long appUsageLimitTimeMs, long appRemainingTimeMs) {
        mAppUsageLimitTimeMs = appUsageLimitTimeMs;
        mAppRemainingTimeMs = appRemainingTimeMs;
        mHasLimit = true;
        TextView toast = mContainer.getViewCache().getView(R.layout.digital_wellbeing_toast,
@@ -138,7 +136,9 @@ public final class DigitalWellBeingToast {
    }

    public void initialize(Task task) {
        mAppUsageLimitTimeMs = mAppRemainingTimeMs = -1;
        if (mIsDestroyed) {
            throw new IllegalStateException("Cannot re-initialize a destroyed toast");
        }
        mTask = task;
        ORDERED_BG_EXECUTOR.execute(() -> {
            AppUsageLimit usageLimit = null;
@@ -155,72 +155,76 @@ public final class DigitalWellBeingToast {
                    usageLimit != null ? usageLimit.getUsageRemaining() : -1;

            mTaskView.post(() -> {
                if (mIsDestroyed) {
                    return;
                }
                if (appUsageLimitTimeMs < 0 || appRemainingTimeMs < 0) {
                    setNoLimit();
                } else {
                    setLimit(appUsageLimitTimeMs, appRemainingTimeMs);
                }
            });

        });
    }
        );

    /**
     * Mark the DWB toast as destroyed and remove banner from TaskView.
     */
    public void destroy() {
        mIsDestroyed = true;
        mTaskView.post(() -> replaceBanner(null));
    }

    public void setSplitConfiguration(SplitBounds splitBounds) {
    public void setSplitBounds(@Nullable SplitBounds splitBounds) {
        mSplitBounds = splitBounds;
    }

    private @SplitBannerConfig int getSplitBannerConfig() {
        if (mSplitBounds == null
                || !mContainer.getDeviceProfile().isTablet
                || mTaskView.isFocusedTask()) {
            mSplitBannerConfig = SPLIT_BANNER_FULLSCREEN;
            return;
            return SPLIT_BANNER_FULLSCREEN;
        }

        // For portrait grid only height of task changes, not width. So we keep the text the same
        if (!mContainer.getDeviceProfile().isLeftRightSplit) {
            mSplitBannerConfig = SPLIT_GRID_BANNER_LARGE;
            return;
            return SPLIT_GRID_BANNER_LARGE;
        }

        // For landscape grid, for 30% width we only show icon, otherwise show icon and time
        if (mTask.key.id == mSplitBounds.leftTopTaskId) {
            mSplitBannerConfig = mSplitBounds.leftTaskPercent < THRESHOLD_LEFT_ICON_ONLY ?
                    SPLIT_GRID_BANNER_SMALL : SPLIT_GRID_BANNER_LARGE;
            return mSplitBounds.leftTaskPercent < THRESHOLD_LEFT_ICON_ONLY
                    ? SPLIT_GRID_BANNER_SMALL : SPLIT_GRID_BANNER_LARGE;
        } else {
            mSplitBannerConfig = mSplitBounds.leftTaskPercent > THRESHOLD_RIGHT_ICON_ONLY ?
                    SPLIT_GRID_BANNER_SMALL : SPLIT_GRID_BANNER_LARGE;
            return mSplitBounds.leftTaskPercent > THRESHOLD_RIGHT_ICON_ONLY
                    ? SPLIT_GRID_BANNER_SMALL : SPLIT_GRID_BANNER_LARGE;
        }
    }

    private String getReadableDuration(
            Duration duration,
            FormatWidth formatWidthHourAndMinute,
            @StringRes int durationLessThanOneMinuteStringId,
            boolean forceFormatWidth) {
            @StringRes int durationLessThanOneMinuteStringId) {
        int hours = Math.toIntExact(duration.toHours());
        int minutes = Math.toIntExact(duration.minusHours(hours).toMinutes());

        // Apply formatWidthHourAndMinute if both the hour part and the minute part are non-zero.
        // Apply FormatWidth.WIDE if both the hour part and the minute part are non-zero.
        if (hours > 0 && minutes > 0) {
            return MeasureFormat.getInstance(Locale.getDefault(), formatWidthHourAndMinute)
            return MeasureFormat.getInstance(Locale.getDefault(), FormatWidth.NARROW)
                    .formatMeasures(
                            new Measure(hours, MeasureUnit.HOUR),
                            new Measure(minutes, MeasureUnit.MINUTE));
        }

        // Apply formatWidthHourOrMinute if only the hour part is non-zero (unless forced).
        // Apply FormatWidth.WIDE if only the hour part is non-zero (unless forced).
        if (hours > 0) {
            return MeasureFormat.getInstance(
                    Locale.getDefault(),
                    forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
                    .formatMeasures(new Measure(hours, MeasureUnit.HOUR));
            return MeasureFormat.getInstance(Locale.getDefault(), FormatWidth.WIDE).formatMeasures(
                    new Measure(hours, MeasureUnit.HOUR));
        }

        // Apply formatWidthHourOrMinute if only the minute part is non-zero (unless forced).
        // Apply FormatWidth.WIDE if only the minute part is non-zero (unless forced).
        if (minutes > 0) {
            return MeasureFormat.getInstance(
                    Locale.getDefault()
                    , forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
                    .formatMeasures(new Measure(minutes, MeasureUnit.MINUTE));
            return MeasureFormat.getInstance(Locale.getDefault(), FormatWidth.WIDE).formatMeasures(
                    new Measure(minutes, MeasureUnit.MINUTE));
        }

        // Use a specific string for usage less than one minute but non-zero.
@@ -229,13 +233,12 @@ public final class DigitalWellBeingToast {
        }

        // Otherwise, return 0-minute string.
        return MeasureFormat.getInstance(
                Locale.getDefault(), forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
                .formatMeasures(new Measure(0, MeasureUnit.MINUTE));
        return MeasureFormat.getInstance(Locale.getDefault(), FormatWidth.WIDE).formatMeasures(
                new Measure(0, MeasureUnit.MINUTE));
    }

    /**
     * Returns text to show for the banner depending on {@link #mSplitBannerConfig}
     * Returns text to show for the banner depending on {@link #getSplitBannerConfig()}
     * If {@param forContentDesc} is {@code true}, this will always return the full
     * string corresponding to {@link #SPLIT_BANNER_FULLSCREEN}
     */
@@ -245,16 +248,16 @@ public final class DigitalWellBeingToast {
                        (remainingTime + MINUTE_MS - 1) / MINUTE_MS * MINUTE_MS :
                        remainingTime);
        String readableDuration = getReadableDuration(duration,
                FormatWidth.NARROW,
                R.string.shorter_duration_less_than_one_minute,
                false /* forceFormatWidth */);
        if (forContentDesc || mSplitBannerConfig == SPLIT_BANNER_FULLSCREEN) {
                R.string.shorter_duration_less_than_one_minute
                /* forceFormatWidth */);
        @SplitBannerConfig int splitBannerConfig = getSplitBannerConfig();
        if (forContentDesc || splitBannerConfig == SPLIT_BANNER_FULLSCREEN) {
            return mContainer.asContext().getString(
                    R.string.time_left_for_app,
                    readableDuration);
        }

        if (mSplitBannerConfig == SPLIT_GRID_BANNER_SMALL) {
        if (splitBannerConfig == SPLIT_GRID_BANNER_SMALL) {
            // show no text
            return "";
        } else { // SPLIT_GRID_BANNER_LARGE
@@ -309,7 +312,7 @@ public final class DigitalWellBeingToast {

    private void setBanner(@Nullable View view) {
        mBanner = view;
        if (view != null && mTaskView.getRecentsView() != null) {
        if (mBanner != null && mTaskView.getRecentsView() != null) {
            setupAndAddBanner();
            setBannerOutline();
        }
+5 −0
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
                        PreviewPositionHelper.STAGE_POSITION_BOTTOM_OR_RIGHT
                    )
            }
        taskContainers.forEach { it.digitalWellBeingToast?.setSplitBounds(splitBoundsConfig) }
        setOrientationState(orientedState)
    }

@@ -240,6 +241,10 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu

    fun updateSplitBoundsConfig(splitBounds: SplitConfigurationOptions.SplitBounds?) {
        splitBoundsConfig = splitBounds
        taskContainers.forEach {
            it.digitalWellBeingToast?.setSplitBounds(splitBoundsConfig)
            it.digitalWellBeingToast?.initialize(it.task)
        }
        invalidate()
    }

+10 −4
Original line number Diff line number Diff line
@@ -512,6 +512,7 @@ constructor(
        onTaskListVisibilityChanged(false)
        borderEnabled = false
        taskViewId = UNBOUND_TASK_VIEW_ID
        taskContainers.forEach { it.destroy() }
    }

    // TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
@@ -801,12 +802,12 @@ constructor(
            taskContainers.forEach {
                if (visible) {
                    recentsModel.iconCache
                        .updateIconInBackground(it.task) { thumbnailData ->
                            setIcon(it.iconView, thumbnailData.icon)
                        .updateIconInBackground(it.task) { task ->
                            setIcon(it.iconView, task.icon)
                            if (enableOverviewIconMenu()) {
                                setText(it.iconView, thumbnailData.title)
                                setText(it.iconView, task.title)
                            }
                            it.digitalWellBeingToast?.initialize(thumbnailData)
                            it.digitalWellBeingToast?.initialize(task)
                        }
                        ?.also { request -> pendingIconLoadRequests.add(request) }
                } else {
@@ -1586,6 +1587,11 @@ constructor(
        val taskView: TaskView
            get() = this@TaskView

        fun destroy() {
            digitalWellBeingToast?.destroy()
            thumbnailView?.let { taskView.removeView(it) }
        }

        // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
        //  so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
        fun bindThumbnailView() {