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

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

Merge "Fix a11y focus issue with partial scrolls and notifyDataSetChanged." into main

parents 52ff826a f4aa685b
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -43,6 +43,16 @@ flag {
  bug: "263474465"
}

flag {
  name: "notify_single_item_change_on_icon_load"
  namespace: "intentresolver"
  description: "ChooserGridAdapter to notify specific items change when the target icon is loaded (instead of all-item change)."
  bug: "298193161"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
  name: "fix_resolver_memory_leak"
  is_exported: true
+76 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
import static android.content.ContentProvider.getUriWithoutUserId;
import static android.content.ContentProvider.getUserIdFromUri;
import static android.service.chooser.Flags.notifySingleItemChangeOnIconLoad;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;

@@ -163,9 +164,11 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@@ -3212,6 +3215,8 @@ public class ChooserActivity extends ResolverActivity implements

        private static final int NUM_EXPANSIONS_TO_HIDE_AZ_LABEL = 20;

        private final Set<ViewHolderBase> mBoundViewHolders = new HashSet<>();

        ChooserGridAdapter(ChooserListAdapter wrappedAdapter) {
            super();
            mChooserListAdapter = wrappedAdapter;
@@ -3232,6 +3237,31 @@ public class ChooserActivity extends ResolverActivity implements
                    notifyDataSetChanged();
                }
            });
            if (notifySingleItemChangeOnIconLoad()) {
                wrappedAdapter.setOnIconLoadedListener(this::onTargetIconLoaded);
            }
        }

        private void onTargetIconLoaded(DisplayResolveInfo info) {
            for (ViewHolderBase holder : mBoundViewHolders) {
                switch (holder.getViewType()) {
                    case VIEW_TYPE_NORMAL:
                        TargetInfo itemInfo =
                                mChooserListAdapter.getItem(
                                        ((ItemViewHolder) holder).mListPosition);
                        if (info == itemInfo) {
                            notifyItemChanged(holder.getAdapterPosition());
                        }
                        break;
                    case VIEW_TYPE_CALLER_AND_RANK:
                        ItemGroupViewHolder groupHolder = (ItemGroupViewHolder) holder;
                        if (suggestedAppsGroupContainsTarget(groupHolder, info)) {
                            notifyItemChanged(holder.getAdapterPosition());
                        }
                        break;
                }

            }
        }

        public void setFooterHeight(int height) {
@@ -3382,6 +3412,9 @@ public class ChooserActivity extends ResolverActivity implements

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if (notifySingleItemChangeOnIconLoad()) {
                mBoundViewHolders.add((ViewHolderBase) holder);
            }
            int viewType = ((ViewHolderBase) holder).getViewType();
            switch (viewType) {
                case VIEW_TYPE_DIRECT_SHARE:
@@ -3395,6 +3428,22 @@ public class ChooserActivity extends ResolverActivity implements
            }
        }

        @Override
        public void onViewRecycled(RecyclerView.ViewHolder holder) {
            if (notifySingleItemChangeOnIconLoad()) {
                mBoundViewHolders.remove((ViewHolderBase) holder);
            }
            super.onViewRecycled(holder);
        }

        @Override
        public boolean onFailedToRecycleView(RecyclerView.ViewHolder holder) {
            if (notifySingleItemChangeOnIconLoad()) {
                mBoundViewHolders.remove((ViewHolderBase) holder);
            }
            return super.onFailedToRecycleView(holder);
        }

        @Override
        public int getItemViewType(int position) {
            int count;
@@ -3604,6 +3653,33 @@ public class ChooserActivity extends ResolverActivity implements
            }
        }

        /**
         * Checks whether the suggested apps group, {@code holder}, contains the target,
         * {@code info}.
         */
        private boolean suggestedAppsGroupContainsTarget(
                ItemGroupViewHolder holder, DisplayResolveInfo info) {

            int position = holder.getAdapterPosition();
            int start = getListPosition(position);
            int startType = getRowType(start);

            int columnCount = holder.getColumnCount();
            int end = start + columnCount - 1;
            while (getRowType(end) != startType && end >= start) {
                end--;
            }

            for (int i = 0; i < columnCount; i++) {
                if (start + i <= end) {
                    if (mChooserListAdapter.getItem(holder.getItemIndex(i)) == info) {
                        return true;
                    }
                }
            }
            return false;
        }

        int getListPosition(int position) {
            position -= getSystemRowCount() + getProfileRowCount();

+20 −0
Original line number Diff line number Diff line
@@ -16,9 +16,12 @@

package com.android.internal.app;

import static android.service.chooser.Flags.notifySingleItemChangeOnIconLoad;

import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE;
import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER;

import android.annotation.Nullable;
import android.app.prediction.AppPredictor;
import android.content.ComponentName;
import android.content.Context;
@@ -56,6 +59,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

public class ChooserListAdapter extends ResolverListAdapter {
    private static final String TAG = "ChooserListAdapter";
@@ -108,6 +112,9 @@ public class ChooserListAdapter extends ResolverListAdapter {
    // Represents the UserSpace in which the Initial Intents should be resolved.
    private final UserHandle mInitialIntentsUserSpace;

    @Nullable
    private Consumer<DisplayResolveInfo> mOnIconLoadedListener;

    // For pinned direct share labels, if the text spans multiple lines, the TextView will consume
    // the full width, even if the characters actually take up less than that. Measure the actual
    // line widths and constrain the View's width based upon that so that the pin doesn't end up
@@ -218,6 +225,10 @@ public class ChooserListAdapter extends ResolverListAdapter {
                true);
    }

    public void setOnIconLoadedListener(Consumer<DisplayResolveInfo> onIconLoadedListener) {
        mOnIconLoadedListener = onIconLoadedListener;
    }

    AppPredictor getAppPredictor() {
        return mAppPredictor;
    }
@@ -329,6 +340,15 @@ public class ChooserListAdapter extends ResolverListAdapter {
        }
    }

    @Override
    protected void onIconLoaded(DisplayResolveInfo info) {
        if (notifySingleItemChangeOnIconLoad() && mOnIconLoadedListener != null) {
            mOnIconLoadedListener.accept(info);
        } else {
            notifyDataSetChanged();
        }
    }

    private void loadDirectShareIcon(SelectableTargetInfo info) {
        LoadDirectShareIconTask task = (LoadDirectShareIconTask) mIconLoaders.get(info);
        if (task == null) {
+5 −1
Original line number Diff line number Diff line
@@ -680,6 +680,10 @@ public class ResolverListAdapter extends BaseAdapter {
        }
    }

    protected void onIconLoaded(DisplayResolveInfo info) {
        notifyDataSetChanged();
    }

    private void loadLabel(DisplayResolveInfo info) {
        LoadLabelTask task = mLabelLoaders.get(info);
        if (task == null) {
@@ -1004,7 +1008,7 @@ public class ResolverListAdapter extends BaseAdapter {
                mResolverListCommunicator.updateProfileViewButton();
            } else if (!mDisplayResolveInfo.hasDisplayIcon()) {
                mDisplayResolveInfo.setDisplayIcon(d);
                notifyDataSetChanged();
                onIconLoaded(mDisplayResolveInfo);
            }
        }
    }