Loading core/java/android/service/notification/Condition.java +34 −4 Original line number Diff line number Diff line Loading @@ -89,6 +89,12 @@ public final class Condition implements Parcelable { public final int flags; public final int icon; /** * The maximum string length for any string contained in this condition. * @hide */ public static final int MAX_STRING_LENGTH = 1000; /** * An object representing the current state of a {@link android.app.AutomaticZenRule}. * @param id the {@link android.app.AutomaticZenRule#getConditionId()} of the zen rule Loading @@ -103,16 +109,19 @@ public final class Condition implements Parcelable { if (id == null) throw new IllegalArgumentException("id is required"); if (summary == null) throw new IllegalArgumentException("summary is required"); if (!isValidState(state)) throw new IllegalArgumentException("state is invalid: " + state); this.id = id; this.summary = summary; this.line1 = line1; this.line2 = line2; this.id = getTrimmedUri(id); this.summary = getTrimmedString(summary); this.line1 = getTrimmedString(line1); this.line2 = getTrimmedString(line2); this.icon = icon; this.state = state; this.flags = flags; } public Condition(Parcel source) { // This constructor passes all fields directly into the constructor that takes all the // fields as arguments; that constructor will trim each of the input strings to // max length if necessary. this((Uri)source.readParcelable(Condition.class.getClassLoader()), source.readString(), source.readString(), Loading Loading @@ -239,4 +248,25 @@ public final class Condition implements Parcelable { return new Condition[size]; } }; /** * Returns a truncated copy of the string if the string is longer than MAX_STRING_LENGTH. */ private static String getTrimmedString(String input) { if (input != null && input.length() > MAX_STRING_LENGTH) { return input.substring(0, MAX_STRING_LENGTH); } return input; } /** * Returns a truncated copy of the Uri by trimming the string representation to the maximum * string length. */ private static Uri getTrimmedUri(Uri input) { if (input != null && input.toString().length() > MAX_STRING_LENGTH) { return Uri.parse(getTrimmedString(input.toString())); } return input; } } core/tests/coretests/src/android/service/notification/ConditionTest.java 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.notification; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.fail; import android.net.Uri; import android.os.Parcel; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.google.common.base.Strings; import org.junit.Test; import org.junit.runner.RunWith; import java.lang.reflect.Field; @RunWith(AndroidJUnit4.class) @SmallTest public class ConditionTest { private static final String CLASS = "android.service.notification.Condition"; @Test public void testLongFields_inConstructors() { String longString = Strings.repeat("A", 65536); Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530)); // Confirm strings are truncated via short constructor Condition cond1 = new Condition(longUri, longString, Condition.STATE_TRUE); assertEquals(Condition.MAX_STRING_LENGTH, cond1.id.toString().length()); assertEquals(Condition.MAX_STRING_LENGTH, cond1.summary.length()); // Confirm strings are truncated via long constructor Condition cond2 = new Condition(longUri, longString, longString, longString, -1, Condition.STATE_TRUE, Condition.FLAG_RELEVANT_ALWAYS); assertEquals(Condition.MAX_STRING_LENGTH, cond2.id.toString().length()); assertEquals(Condition.MAX_STRING_LENGTH, cond2.summary.length()); assertEquals(Condition.MAX_STRING_LENGTH, cond2.line1.length()); assertEquals(Condition.MAX_STRING_LENGTH, cond2.line2.length()); } @Test public void testLongFields_viaParcel() { // Set fields via reflection to force them to be long, then parcel and unparcel to make sure // it gets truncated upon unparcelling. Condition cond = new Condition(Uri.parse("uri://placeholder"), "placeholder", Condition.STATE_TRUE); try { String longString = Strings.repeat("A", 65536); Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530)); Field id = Class.forName(CLASS).getDeclaredField("id"); id.setAccessible(true); id.set(cond, longUri); Field summary = Class.forName(CLASS).getDeclaredField("summary"); summary.setAccessible(true); summary.set(cond, longString); Field line1 = Class.forName(CLASS).getDeclaredField("line1"); line1.setAccessible(true); line1.set(cond, longString); Field line2 = Class.forName(CLASS).getDeclaredField("line2"); line2.setAccessible(true); line2.set(cond, longString); } catch (NoSuchFieldException e) { fail(e.toString()); } catch (ClassNotFoundException e) { fail(e.toString()); } catch (IllegalAccessException e) { fail(e.toString()); } Parcel parcel = Parcel.obtain(); cond.writeToParcel(parcel, 0); parcel.setDataPosition(0); Condition fromParcel = new Condition(parcel); assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.id.toString().length()); assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.summary.length()); assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.line1.length()); assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.line2.length()); } } Loading
core/java/android/service/notification/Condition.java +34 −4 Original line number Diff line number Diff line Loading @@ -89,6 +89,12 @@ public final class Condition implements Parcelable { public final int flags; public final int icon; /** * The maximum string length for any string contained in this condition. * @hide */ public static final int MAX_STRING_LENGTH = 1000; /** * An object representing the current state of a {@link android.app.AutomaticZenRule}. * @param id the {@link android.app.AutomaticZenRule#getConditionId()} of the zen rule Loading @@ -103,16 +109,19 @@ public final class Condition implements Parcelable { if (id == null) throw new IllegalArgumentException("id is required"); if (summary == null) throw new IllegalArgumentException("summary is required"); if (!isValidState(state)) throw new IllegalArgumentException("state is invalid: " + state); this.id = id; this.summary = summary; this.line1 = line1; this.line2 = line2; this.id = getTrimmedUri(id); this.summary = getTrimmedString(summary); this.line1 = getTrimmedString(line1); this.line2 = getTrimmedString(line2); this.icon = icon; this.state = state; this.flags = flags; } public Condition(Parcel source) { // This constructor passes all fields directly into the constructor that takes all the // fields as arguments; that constructor will trim each of the input strings to // max length if necessary. this((Uri)source.readParcelable(Condition.class.getClassLoader()), source.readString(), source.readString(), Loading Loading @@ -239,4 +248,25 @@ public final class Condition implements Parcelable { return new Condition[size]; } }; /** * Returns a truncated copy of the string if the string is longer than MAX_STRING_LENGTH. */ private static String getTrimmedString(String input) { if (input != null && input.length() > MAX_STRING_LENGTH) { return input.substring(0, MAX_STRING_LENGTH); } return input; } /** * Returns a truncated copy of the Uri by trimming the string representation to the maximum * string length. */ private static Uri getTrimmedUri(Uri input) { if (input != null && input.toString().length() > MAX_STRING_LENGTH) { return Uri.parse(getTrimmedString(input.toString())); } return input; } }
core/tests/coretests/src/android/service/notification/ConditionTest.java 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.notification; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.fail; import android.net.Uri; import android.os.Parcel; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.google.common.base.Strings; import org.junit.Test; import org.junit.runner.RunWith; import java.lang.reflect.Field; @RunWith(AndroidJUnit4.class) @SmallTest public class ConditionTest { private static final String CLASS = "android.service.notification.Condition"; @Test public void testLongFields_inConstructors() { String longString = Strings.repeat("A", 65536); Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530)); // Confirm strings are truncated via short constructor Condition cond1 = new Condition(longUri, longString, Condition.STATE_TRUE); assertEquals(Condition.MAX_STRING_LENGTH, cond1.id.toString().length()); assertEquals(Condition.MAX_STRING_LENGTH, cond1.summary.length()); // Confirm strings are truncated via long constructor Condition cond2 = new Condition(longUri, longString, longString, longString, -1, Condition.STATE_TRUE, Condition.FLAG_RELEVANT_ALWAYS); assertEquals(Condition.MAX_STRING_LENGTH, cond2.id.toString().length()); assertEquals(Condition.MAX_STRING_LENGTH, cond2.summary.length()); assertEquals(Condition.MAX_STRING_LENGTH, cond2.line1.length()); assertEquals(Condition.MAX_STRING_LENGTH, cond2.line2.length()); } @Test public void testLongFields_viaParcel() { // Set fields via reflection to force them to be long, then parcel and unparcel to make sure // it gets truncated upon unparcelling. Condition cond = new Condition(Uri.parse("uri://placeholder"), "placeholder", Condition.STATE_TRUE); try { String longString = Strings.repeat("A", 65536); Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530)); Field id = Class.forName(CLASS).getDeclaredField("id"); id.setAccessible(true); id.set(cond, longUri); Field summary = Class.forName(CLASS).getDeclaredField("summary"); summary.setAccessible(true); summary.set(cond, longString); Field line1 = Class.forName(CLASS).getDeclaredField("line1"); line1.setAccessible(true); line1.set(cond, longString); Field line2 = Class.forName(CLASS).getDeclaredField("line2"); line2.setAccessible(true); line2.set(cond, longString); } catch (NoSuchFieldException e) { fail(e.toString()); } catch (ClassNotFoundException e) { fail(e.toString()); } catch (IllegalAccessException e) { fail(e.toString()); } Parcel parcel = Parcel.obtain(); cond.writeToParcel(parcel, 0); parcel.setDataPosition(0); Condition fromParcel = new Condition(parcel); assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.id.toString().length()); assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.summary.length()); assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.line1.length()); assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.line2.length()); } }