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

Commit bfbe4619 authored by Stevie Kideckel's avatar Stevie Kideckel
Browse files

Fix handling for onItemClick of fixed collection items

The onItemClick handling code assumed that the item would be nested at
least one layer deep due to the RemoteViewsAdapter adding a wrapper view
group.

Rather than add another case to that logic, I've refactored this to
traverse the view's children looking for a view with the tag. As the
tag is internal, there should only ever be one child with it and we'll
always want that one to handle the click.

Fix: 190353630
Test: locally
Test: atest RemoteViewsFixedCollectionAdapterTest
Change-Id: I22057f148d33482ad84fff592b9f7f554fa2bfad
parent ebcaa39d
Loading
Loading
Loading
Loading
+25 −23
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -812,29 +813,8 @@ public class RemoteViews implements Parcelable, Filter {
                AdapterView<?> av = (AdapterView<?>) target;
                // The PendingIntent template is stored in the view's tag.
                OnItemClickListener listener = (parent, view, position, id) -> {
                    // The view should be a frame layout
                    if (view instanceof ViewGroup) {
                        ViewGroup vg = (ViewGroup) view;

                        // AdapterViews contain their children in a frame
                        // so we need to go one layer deeper here.
                        if (parent instanceof AdapterViewAnimator) {
                            vg = (ViewGroup) vg.getChildAt(0);
                        }
                        if (vg == null) return;

                        RemoteResponse response = null;
                        int childCount = vg.getChildCount();
                        for (int i = 0; i < childCount; i++) {
                            Object tag = vg.getChildAt(i).getTag(R.id.fillInIntent);
                            if (tag instanceof RemoteResponse) {
                                response = (RemoteResponse) tag;
                                break;
                            }
                        }
                        if (response == null) return;
                    RemoteResponse response = findRemoteResponseTag(view);
                    response.handleViewInteraction(view, handler);
                    }
                };
                av.setOnItemClickListener(listener);
                av.setTag(pendingIntentTemplate);
@@ -845,6 +825,28 @@ public class RemoteViews implements Parcelable, Filter {
            }
        }

        @Nullable
        private RemoteResponse findRemoteResponseTag(@Nullable View rootView) {
            if (rootView == null) return null;

            ArrayDeque<View> viewsToCheck = new ArrayDeque<>();
            viewsToCheck.addLast(rootView);

            while (!viewsToCheck.isEmpty()) {
                View view = viewsToCheck.removeFirst();
                Object tag = view.getTag(R.id.fillInIntent);
                if (tag instanceof RemoteResponse) return (RemoteResponse) tag;
                if (!(view instanceof ViewGroup)) continue;

                ViewGroup viewGroup = (ViewGroup) view;
                for (int i = 0; i < viewGroup.getChildCount(); i++) {
                    viewsToCheck.addLast(viewGroup.getChildAt(i));
                }
            }

            return null;
        }

        @Override
        public int getActionTag() {
            return SET_PENDING_INTENT_TEMPLATE_TAG;