Snap for 11670631 from d8be301d85bf10c177fde09644cfe1847334411a to mainline-mediaprovider-release Change-Id: If09dc391c4ccd07d7577783bed34f826c787de53
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java index 7fc1604..2f50ebc 100644 --- a/src/android/net/apf/ApfFilter.java +++ b/src/android/net/apf/ApfFilter.java
@@ -666,8 +666,8 @@ private long mMinRioRouteLifetime = Long.MAX_VALUE; // Minimum lifetime of RDNSSs in packet, Long.MAX_VALUE means not seen. private long mMinRdnssLifetime = Long.MAX_VALUE; - // Minimum lifetime in packet - private final int mMinLifetime; + // The time in seconds in which some of the information contained in this RA expires. + private final int mExpirationTime; // When the packet was last captured, in seconds since Unix Epoch private final int mLastSeen; @@ -984,7 +984,7 @@ break; } } - mMinLifetime = minLifetime(); + mExpirationTime = getExpirationTime(); } public enum MatchType { @@ -1097,14 +1097,13 @@ return MatchType.MATCH_DROP; } - // What is the minimum of all lifetimes within {@code packet} in seconds? - // Precondition: matches(packet, length) already returned true. - private int minLifetime() { + // Get the number of seconds in which some of the information contained in this RA expires. + private int getExpirationTime() { // While technically most lifetimes in the RA are u32s, as far as the RA filter is // concerned, INT_MAX is still a *much* longer lifetime than any filter would ever // reasonably be active for. - // Clamp minLifetime at INT_MAX. - int minLifetime = Integer.MAX_VALUE; + // Clamp expirationTime at INT_MAX. + int expirationTime = Integer.MAX_VALUE; for (PacketSection section : mPacketSections) { if (section.type != PacketSection.Type.LIFETIME) { continue; @@ -1114,14 +1113,14 @@ continue; } - minLifetime = (int) Math.min(minLifetime, section.lifetime); + expirationTime = (int) Math.min(expirationTime, section.lifetime); } - return minLifetime; + return expirationTime; } - // Filter for a fraction of the lifetime and adjust for the age of the RA. + // Filter for a fraction of the expiration time and adjust for the age of the RA. int getRemainingFilterLft(int currentTimeSeconds) { - int filterLifetime = ((mMinLifetime / FRACTION_OF_LIFETIME_TO_FILTER) + int filterLifetime = ((mExpirationTime / FRACTION_OF_LIFETIME_TO_FILTER) - (currentTimeSeconds - mLastSeen)); filterLifetime = Math.max(0, filterLifetime); // Clamp filterLifetime to <= 65535, so it fits in 2 bytes. @@ -2272,7 +2271,7 @@ if (context == null || config == null || ifParams == null) return null; ApfCapabilities apfCapabilities = config.apfCapabilities; if (apfCapabilities == null) return null; - if (apfCapabilities.apfVersionSupported == 0) return null; + if (apfCapabilities.apfVersionSupported < 2) return null; if (apfCapabilities.maximumApfProgramSize < 512) { Log.e(TAG, "Unacceptably small APF limit: " + apfCapabilities.maximumApfProgramSize); return null;
diff --git a/src/android/net/apf/ApfV4Generator.java b/src/android/net/apf/ApfV4Generator.java index 4c70570..96320ae 100644 --- a/src/android/net/apf/ApfV4Generator.java +++ b/src/android/net/apf/ApfV4Generator.java
@@ -129,6 +129,14 @@ return maybeAddLoadR1CounterOffset(cnt).addJumpIfR0LessThan(val, mCountAndPassLabel); } + @Override + public ApfV4Generator addCountAndDropIfBytesAtR0NotEqual(byte[] bytes, + ApfCounterTracker.Counter cnt) throws IllegalInstructionException { + checkDropCounterRange(cnt); + return maybeAddLoadR1CounterOffset(cnt).addJumpIfBytesAtR0NotEqual(bytes, + mCountAndDropLabel); + } + /** * Append the count & (pass|drop) trampoline, which increments the counter at the data address * pointed to by R1, then jumps to the (pass|drop) label. This saves a few bytes over inserting
diff --git a/src/android/net/apf/ApfV4GeneratorBase.java b/src/android/net/apf/ApfV4GeneratorBase.java index 482405a..e27a5a2 100644 --- a/src/android/net/apf/ApfV4GeneratorBase.java +++ b/src/android/net/apf/ApfV4GeneratorBase.java
@@ -402,8 +402,8 @@ /** * Add an instruction to the end of the program to jump to {@code tgt} if the bytes of the - * packet at an offset specified by {@code register} don't match {@code bytes} - * R=0 means check for not equal + * packet at an offset specified by register0 don't match {@code bytes}. + * R=0 means check for not equal. */ public final Type addJumpIfBytesAtR0NotEqual(byte[] bytes, String tgt) { return append(new Instruction(Opcodes.JNEBS).addUnsigned( @@ -411,6 +411,14 @@ } /** + * Add instructions to the end of the program to increase counter and drop packet if the + * bytes of the packet at an offset specified by register0 don't match {@code bytes}. + * WARNING: may modify R1 + */ + public abstract Type addCountAndDropIfBytesAtR0NotEqual(byte[] bytes, + ApfCounterTracker.Counter cnt) throws IllegalInstructionException; + + /** * Add an instruction to the end of the program to load memory slot {@code slot} into * {@code register}. */
diff --git a/src/android/net/apf/ApfV6Generator.java b/src/android/net/apf/ApfV6Generator.java index 36c7bc4..da624b2 100644 --- a/src/android/net/apf/ApfV6Generator.java +++ b/src/android/net/apf/ApfV6Generator.java
@@ -118,6 +118,14 @@ return addJumpIfR0GreaterThan(val - 1, tgt).addCountAndPass(cnt).defineLabel(tgt); } + @Override + public ApfV6Generator addCountAndDropIfBytesAtR0NotEqual(byte[] bytes, + ApfCounterTracker.Counter cnt) throws IllegalInstructionException { + checkDropCounterRange(cnt); + final String tgt = getUniqueLabel(); + return addJumpIfBytesAtR0Equal(bytes, tgt).addCountAndDrop(cnt).defineLabel(tgt); + } + private int mLabelCount = 0; /**
diff --git a/src/android/net/apf/ApfV6GeneratorBase.java b/src/android/net/apf/ApfV6GeneratorBase.java index 95f09f3..99f07c2 100644 --- a/src/android/net/apf/ApfV6GeneratorBase.java +++ b/src/android/net/apf/ApfV6GeneratorBase.java
@@ -182,6 +182,28 @@ } /** + * Add an instruction to the end of the program to encode int value as 4 bytes to output buffer. + */ + public final Type addWrite32(int val) { + return addWriteU32((long) val & 0xffffffffL); + } + + /** + * Add an instruction to the end of the program to write 4 bytes array to output buffer. + */ + public final Type addWrite32(@NonNull byte[] bytes) { + Objects.requireNonNull(bytes); + if (bytes.length != 4) { + throw new IllegalArgumentException( + "bytes array size must be 4, current size: " + bytes.length); + } + return addWrite32(((bytes[0] & 0xff) << 24) + | ((bytes[1] & 0xff) << 16) + | ((bytes[2] & 0xff) << 8) + | (bytes[3] & 0xff)); + } + + /** * Add an instruction to the end of the program to write 1 byte value from register to output * buffer. */ @@ -397,7 +419,7 @@ /** * Add an instruction to the end of the program to jump to {@code tgt} if the bytes of the - * packet at an offset specified by {@code register} match {@code bytes} + * packet at an offset specified by register0 match {@code bytes}. * R=1 means check for equal. */ public final Type addJumpIfBytesAtR0Equal(byte[] bytes, String tgt)
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java index 87cbdb0..aba4f4e 100644 --- a/src/android/net/ip/IpClient.java +++ b/src/android/net/ip/IpClient.java
@@ -177,6 +177,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -1482,8 +1484,8 @@ }); try { - return result.get(); - } catch (ExecutionException | InterruptedException e) { + return result.get(30, TimeUnit.SECONDS); + } catch (ExecutionException | InterruptedException | TimeoutException e) { // completeExceptionally is solely used to return error messages back to the user, so // the stack trace is not all that interesting. (A similar argument can be made for // InterruptedException). Only extract the message from the checked exception. @@ -2521,7 +2523,7 @@ apfConfig.apfCapabilities = apfCapabilities; if (apfCapabilities != null && !SdkLevel.isAtLeastV() && apfCapabilities.apfVersionSupported <= 4) { - apfConfig.installableProgramSizeClamp = 2000; + apfConfig.installableProgramSizeClamp = 1024; } apfConfig.multicastFilter = mMulticastFiltering; // Get the Configuration for ApfFilter from Context
diff --git a/tests/unit/src/android/net/apf/ApfV5Test.kt b/tests/unit/src/android/net/apf/ApfV5Test.kt index d55b7c6..416321a 100644 --- a/tests/unit/src/android/net/apf/ApfV5Test.kt +++ b/tests/unit/src/android/net/apf/ApfV5Test.kt
@@ -241,6 +241,12 @@ assertFailsWith<IllegalArgumentException> { gen.addCountAndPassIfR0LessThan(3, DROPPED_ETH_BROADCAST) } + assertFailsWith<IllegalArgumentException> { + gen.addCountAndDropIfBytesAtR0NotEqual(byteArrayOf(1), PASSED_ARP) + } + assertFailsWith<IllegalArgumentException> { + gen.addWrite32(byteArrayOf()) + } val v4gen = ApfV4Generator(APF_VERSION_4) assertFailsWith<IllegalArgumentException> { v4gen.addCountAndDrop(PASSED_ARP) } @@ -263,6 +269,9 @@ assertFailsWith<IllegalArgumentException> { v4gen.addCountAndPassIfR0LessThan(3, DROPPED_ETH_BROADCAST) } + assertFailsWith<IllegalArgumentException> { + v4gen.addCountAndDropIfBytesAtR0NotEqual(byteArrayOf(1), PASSED_ARP) + } } @Test @@ -438,6 +447,8 @@ gen.addWriteU16(0x8000) gen.addWriteU32(0x00000000) gen.addWriteU32(0x80000000) + gen.addWrite32(-2) + gen.addWrite32(byteArrayOf(0xff.toByte(), 0xfe.toByte(), 0xfd.toByte(), 0xfc.toByte())) program = gen.generate() assertContentEquals(byteArrayOf( encodeInstruction(24, 1, 0), 0x01, @@ -448,8 +459,11 @@ encodeInstruction(24, 2, 0), 0x00, 0x00, encodeInstruction(24, 2, 0), 0x80.toByte(), 0x00, encodeInstruction(24, 4, 0), 0x00, 0x00, 0x00, 0x00, - encodeInstruction(24, 4, 0), 0x80.toByte(), 0x00, 0x00, - 0x00), program) + encodeInstruction(24, 4, 0), 0x80.toByte(), 0x00, 0x00, 0x00, + encodeInstruction(24, 4, 0), 0xff.toByte(), 0xff.toByte(), + 0xff.toByte(), 0xfe.toByte(), + encodeInstruction(24, 4, 0), 0xff.toByte(), 0xfe.toByte(), + 0xfd.toByte(), 0xfc.toByte()), program) assertContentEquals(listOf( "0: write 0x01", "2: write 0x0102", @@ -459,7 +473,9 @@ "14: write 0x0000", "17: write 0x8000", "20: write 0x00000000", - "25: write 0x80000000" + "25: write 0x80000000", + "30: write 0xfffffffe", + "35: write 0xfffefdfc" ), ApfJniUtils.disassembleApf(program).map { it.trim() }) gen = ApfV6Generator() @@ -601,6 +617,8 @@ .addWriteU8(0x01) .addWriteU16(0x0203) .addWriteU32(0x04050607) + .addWrite32(-2) + .addWrite32(byteArrayOf(0xff.toByte(), 0xfe.toByte(), 0xfd.toByte(), 0xfc.toByte())) .addLoadImmediate(R0, 1) .addWriteU8(R0) .addLoadImmediate(R0, 0x0203) @@ -610,8 +628,13 @@ .addTransmitWithoutChecksum() .generate() assertPass(MIN_APF_VERSION_IN_DEV, program, ByteArray(MIN_PKT_SIZE)) - assertContentEquals(byteArrayOf(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07), ApfJniUtils.getTransmittedPacket()) + assertContentEquals( + byteArrayOf( + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff.toByte(), + 0xff.toByte(), 0xff.toByte(), 0xfe.toByte(), 0xff.toByte(), 0xfe.toByte(), + 0xfd.toByte(), 0xfc.toByte(), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07), + ApfJniUtils.getTransmittedPacket() + ) } @Test @@ -793,6 +816,20 @@ expectedMap = getInitialMap() expectedMap[Counter.PASSED_ARP] = 1 assertEquals(expectedMap, counterMap) + + program = getGenerator() + .addLoadImmediate(R0, 1) + .addCountAndDropIfBytesAtR0NotEqual( + byteArrayOf(5, 5), DROPPED_ETH_BROADCAST) + .addPass() + .addCountTrampoline() + .generate() + dataRegion = ByteArray(Counter.totalSize()) { 0 } + assertVerdict(MIN_APF_VERSION_IN_DEV, DROP, program, testPacket, dataRegion) + counterMap = decodeCountersIntoMap(dataRegion) + expectedMap = getInitialMap() + expectedMap[DROPPED_ETH_BROADCAST] = 1 + assertEquals(expectedMap, counterMap) } @Test