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

Commit 4a2c7c55 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala
Browse files

Camera2: Protect MarshalRegistry against concurrent access

Multiple CameraMetadataNative objects could be reading and writing
to the metadata marshaler registry simultaneously.

This can lead to an infinite loop in the HashMap in the worst case,
so add synchronization against this.

Bug: 29043079
Change-Id: Ic5e9e58a9333b99b4bea87bf790c9fbfadfbbea9
parent 9675f16b
Loading
Loading
Loading
Loading
+43 −35
Original line number Diff line number Diff line
@@ -37,8 +37,10 @@ public class MarshalRegistry {
     * @param queryable a non-{@code null} marshal queryable that supports marshaling {@code T}
     */
    public static <T> void registerMarshalQueryable(MarshalQueryable<T> queryable) {
        synchronized(sMarshalLock) {
            sRegisteredMarshalQueryables.add(queryable);
        }
    }

    /**
     * Lookup a marshaler between {@code T} and {@code nativeType}.
@@ -54,6 +56,7 @@ public class MarshalRegistry {
     */
    @SuppressWarnings("unchecked")
    public static <T> Marshaler<T> getMarshaler(TypeReference<T> typeToken, int nativeType) {
        synchronized(sMarshalLock) {
            // TODO: can avoid making a new token each time by code-genning
            // the list of type tokens and native types from the keys (at the call sites)
            MarshalToken<T> marshalToken = new MarshalToken<T>(typeToken, nativeType);
@@ -65,11 +68,12 @@ public class MarshalRegistry {
            Marshaler<T> marshaler =
                    (Marshaler<T>) sMarshalerMap.get(marshalToken);

            if (marshaler == null) {

                if (sRegisteredMarshalQueryables.size() == 0) {
                    throw new AssertionError("No available query marshalers registered");
                }

        if (marshaler == null) {
                // Query each marshaler to see if they support the native/managed type combination
                for (MarshalQueryable<?> potentialMarshaler : sRegisteredMarshalQueryables) {

@@ -96,6 +100,7 @@ public class MarshalRegistry {

            return marshaler;
        }
    }

    private static class MarshalToken<T> {
        public MarshalToken(TypeReference<T> typeReference, int nativeType) {
@@ -125,9 +130,12 @@ public class MarshalRegistry {
        }
    }

    private static List<MarshalQueryable<?>> sRegisteredMarshalQueryables =
    // Control access to the static data structures below
    private static final Object sMarshalLock = new Object();

    private static final List<MarshalQueryable<?>> sRegisteredMarshalQueryables =
            new ArrayList<MarshalQueryable<?>>();
    private static HashMap<MarshalToken<?>, Marshaler<?>> sMarshalerMap =
    private static final HashMap<MarshalToken<?>, Marshaler<?>> sMarshalerMap =
            new HashMap<MarshalToken<?>, Marshaler<?>>();

    private MarshalRegistry() {