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

Commit 76d0f31e authored by Matías Hernández's avatar Matías Hernández Committed by Android Build Coastguard Worker
Browse files

Visit Uris added by WearableExtender

This CL also fixes the reflection-based test, which was supplying a List containing junk Objects to methods that expected generics such as List<Something>.

Bug: 283962802
Test: atest + manual (POC app now crashes on notify() as expected)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:68b20a008ebfca2aba6f0f9ec74ba35c2bbbb7ed)
Merged-In: I0da18c631eb5e4844a48760c7aaedab715a0bfed
Change-Id: I0da18c631eb5e4844a48760c7aaedab715a0bfed
parent 40a59432
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -2171,6 +2171,10 @@ public class Notification implements Parcelable
            }
        }
        private void visitUris(@NonNull Consumer<Uri> visitor) {
            visitIconUri(visitor, getIcon());
        }
        @Override
        public Action clone() {
            return new Action(
@@ -2856,7 +2860,7 @@ public class Notification implements Parcelable
        if (actions != null) {
            for (Action action : actions) {
                visitIconUri(visitor, action.getIcon());
                action.visitUris(visitor);
            }
        }
@@ -2947,6 +2951,11 @@ public class Notification implements Parcelable
        if (mBubbleMetadata != null) {
            visitIconUri(visitor, mBubbleMetadata.getIcon());
        }
        if (extras != null && extras.containsKey(WearableExtender.EXTRA_WEARABLE_EXTENSIONS)) {
            WearableExtender extender = new WearableExtender(this);
            extender.visitUris(visitor);
        }
    }
    /**
@@ -11711,6 +11720,12 @@ public class Notification implements Parcelable
                mFlags &= ~mask;
            }
        }
        private void visitUris(@NonNull Consumer<Uri> visitor) {
            for (Action action : mActions) {
                action.visitUris(visitor);
            }
        }
    }
    /**
+20 −0
Original line number Diff line number Diff line
@@ -5902,6 +5902,26 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        verify(visitor, times(1)).accept(eq(verificationIcon.getUri()));
    }
    @Test
    public void testVisitUris_wearableExtender() {
        Icon actionIcon = Icon.createWithContentUri("content://media/action");
        Icon wearActionIcon = Icon.createWithContentUri("content://media/wearAction");
        PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent(),
                PendingIntent.FLAG_IMMUTABLE);
        Notification n = new Notification.Builder(mContext, "a")
                .setSmallIcon(android.R.drawable.sym_def_app_icon)
                .addAction(new Notification.Action.Builder(actionIcon, "Hey!", intent).build())
                .extend(new Notification.WearableExtender().addAction(
                        new Notification.Action.Builder(wearActionIcon, "Wear!", intent).build()))
                .build();
        Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
        n.visitUris(visitor);
        verify(visitor).accept(eq(actionIcon.getUri()));
        verify(visitor).accept(eq(wearActionIcon.getUri()));
    }
    @Test
    public void testSetNotificationPolicy_preP_setOldFields() {
        ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
+30 −5
Original line number Diff line number Diff line
@@ -66,6 +66,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -87,7 +89,6 @@ public class NotificationVisitUrisTest extends UiServiceTestCase {
    // This list should be emptied! Items can be removed as bugs are fixed.
    private static final Multimap<Class<?>, String> KNOWN_BAD =
            ImmutableMultimap.<Class<?>, String>builder()
                    .put(Notification.WearableExtender.class, "addAction") // TODO: b/281044385
                    .put(Person.Builder.class, "setUri") // TODO: b/281044385
                    .put(RemoteViews.class, "setRemoteAdapter") // TODO: b/281044385
                    .build();
@@ -149,7 +150,7 @@ public class NotificationVisitUrisTest extends UiServiceTestCase {
        Generated<Notification> notification = buildNotification(mContext, /* styleClass= */ null,
                /* extenderClass= */ null, /* actionExtenderClass= */ null,
                /* includeRemoteViews= */ true);
        assertThat(notification.includedUris.size()).isAtLeast(20);
        assertThat(notification.includedUris.size()).isAtLeast(900);
    }

    @Test
@@ -435,19 +436,43 @@ public class NotificationVisitUrisTest extends UiServiceTestCase {
            Set<Class<?>> excludingClasses, SpecialParameterGenerator specialGenerator) {
        Log.i(TAG, "About to generate parameters for " + ReflectionUtils.methodToString(executable)
                + " in " + where);
        Class<?>[] parameterTypes = executable.getParameterTypes();
        Type[] parameterTypes = executable.getGenericParameterTypes();
        Object[] parameterValues = new Object[parameterTypes.length];
        for (int i = 0; i < parameterTypes.length; i++) {
            parameterValues[i] = generateObject(
            parameterValues[i] = generateParameter(
                    parameterTypes[i],
                    where.plus(executable,
                            String.format("[%d,%s]", i, parameterTypes[i].getName())),
                            String.format("[%d,%s]", i, parameterTypes[i].getTypeName())),
                    excludingClasses,
                    specialGenerator);
        }
        return parameterValues;
    }

    private static Object generateParameter(Type parameterType, Location where,
            Set<Class<?>> excludingClasses, SpecialParameterGenerator specialGenerator) {
        if (parameterType instanceof Class<?> parameterClass) {
            return generateObject(
                    parameterClass,
                    where,
                    excludingClasses,
                    specialGenerator);
        } else if (parameterType instanceof ParameterizedType parameterizedType) {
            if (parameterizedType.getRawType().equals(List.class)
                    && parameterizedType.getActualTypeArguments()[0] instanceof Class<?>) {
                ArrayList listValue = new ArrayList();
                for (int i = 0; i < NUM_ELEMENTS_IN_ARRAY; i++) {
                    listValue.add(
                            generateObject((Class<?>) parameterizedType.getActualTypeArguments()[0],
                                    where, excludingClasses, specialGenerator));
                }
                return listValue;
            }
        }
        throw new IllegalArgumentException(
                "I have no idea how to produce a(n) " + parameterType + ", sorry");
    }

    private static class ReflectionUtils {
        static Set<Class<?>> getConcreteSubclasses(Class<?> clazz, Class<?> containerClass) {
            return Arrays.stream(containerClass.getDeclaredClasses())