summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuri Lin <yurilin@google.com>2022-09-22 15:21:17 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2022-09-22 15:21:17 +0000
commitda63d3e028df7732efbd85ee34b243da96613a29 (patch)
tree9fd22fe8e97c8fad26cd131f6361c256b7996063
parentb625b562c41cd3f68aebdd33f96f766209ecfa15 (diff)
parent5cb217fff3bc7184bd776a9dc2991e7fce5e25bd (diff)
downloadbase-da63d3e028df7732efbd85ee34b243da96613a29.tar.gz
Merge "Limit lengths of fields in Condition to a max length." into qt-dev
-rw-r--r--core/java/android/service/notification/Condition.java38
-rw-r--r--core/tests/coretests/src/android/service/notification/ConditionTest.java101
2 files changed, 135 insertions, 4 deletions
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index e506509bb1be..50597ec3972e 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -90,6 +90,12 @@ public final class Condition implements Parcelable {
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
* @param summary a user visible description of the rule state.
@@ -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(),
@@ -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;
+ }
}
diff --git a/core/tests/coretests/src/android/service/notification/ConditionTest.java b/core/tests/coretests/src/android/service/notification/ConditionTest.java
new file mode 100644
index 000000000000..42629ba41287
--- /dev/null
+++ b/core/tests/coretests/src/android/service/notification/ConditionTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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());
+ }
+}