Loading core/java/android/content/om/FabricatedOverlay.java +32 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.text.TextUtils; import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.Objects; /** * Fabricated Runtime Resource Overlays (FRROs) are overlays generated ar runtime. Loading Loading @@ -88,6 +89,27 @@ public class FabricatedOverlay { return this; } /** * Ensure the resource name is in the form [package]:type/entry. * * @param name name of the target resource to overlay (in the form [package]:type/entry) * @return the valid name */ private static String ensureValidResourceName(@NonNull String name) { Objects.requireNonNull(name); final int slashIndex = name.indexOf('/'); /* must contain '/' */ final int colonIndex = name.indexOf(':'); /* ':' should before '/' if ':' exist */ // The minimum length of resource type is "id". Preconditions.checkArgument( slashIndex >= 0 /* It must contain the type name */ && colonIndex != 0 /* 0 means the package name is empty */ && (slashIndex - colonIndex) > 2 /* The shortest length of type is "id" */, "\"%s\" is invalid resource name", name); return name; } /** * Sets the value of the fabricated overlay * Loading @@ -99,6 +121,8 @@ public class FabricatedOverlay { * @see android.util.TypedValue#type */ public Builder setResourceValue(@NonNull String resourceName, int dataType, int value) { ensureValidResourceName(resourceName); final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); entry.resourceName = resourceName; entry.dataType = dataType; Loading @@ -120,6 +144,8 @@ public class FabricatedOverlay { */ public Builder setResourceValue(@NonNull String resourceName, int dataType, int value, String configuration) { ensureValidResourceName(resourceName); final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); entry.resourceName = resourceName; entry.dataType = dataType; Loading @@ -140,6 +166,8 @@ public class FabricatedOverlay { * @see android.util.TypedValue#type */ public Builder setResourceValue(@NonNull String resourceName, int dataType, String value) { ensureValidResourceName(resourceName); final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); entry.resourceName = resourceName; entry.dataType = dataType; Loading @@ -161,6 +189,8 @@ public class FabricatedOverlay { */ public Builder setResourceValue(@NonNull String resourceName, int dataType, String value, String configuration) { ensureValidResourceName(resourceName); final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); entry.resourceName = resourceName; entry.dataType = dataType; Loading @@ -180,6 +210,8 @@ public class FabricatedOverlay { */ public Builder setResourceValue(@NonNull String resourceName, ParcelFileDescriptor value, String configuration) { ensureValidResourceName(resourceName); final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); entry.resourceName = resourceName; entry.binaryData = value; Loading core/tests/overlaytests/device/src/com/android/overlaytest/FabricatedOverlaysTest.java +46 −3 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.overlaytest; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertThrows; Loading @@ -45,7 +44,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeoutException; @RunWith(JUnit4.class) Loading Loading @@ -220,12 +218,57 @@ public class FabricatedOverlaysTest { } } @Test public void setResourceValue_withNullResourceName() throws Exception { final FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()); assertThrows(NullPointerException.class, () -> builder.setResourceValue(null, TypedValue.TYPE_INT_DEC, 1)); } @Test public void setResourceValue_withEmptyResourceName() throws Exception { final FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()); assertThrows(IllegalArgumentException.class, () -> builder.setResourceValue("", TypedValue.TYPE_INT_DEC, 1)); } @Test public void setResourceValue_withEmptyPackageName() throws Exception { final FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()); assertThrows(IllegalArgumentException.class, () -> builder.setResourceValue(":color/mycolor", TypedValue.TYPE_INT_DEC, 1)); } @Test public void setResourceValue_withInvalidTypeName() throws Exception { final FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()); assertThrows(IllegalArgumentException.class, () -> builder.setResourceValue("c/mycolor", TypedValue.TYPE_INT_DEC, 1)); } @Test public void setResourceValue_withEmptyTypeName() throws Exception { final FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()); assertThrows(IllegalArgumentException.class, () -> builder.setResourceValue("/mycolor", TypedValue.TYPE_INT_DEC, 1)); } @Test public void testInvalidResourceValues() throws Exception { final FabricatedOverlay overlay = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()) .setResourceValue(TEST_RESOURCE, TypedValue.TYPE_INT_DEC, 1) .setResourceValue("something", TypedValue.TYPE_INT_DEC, 1) .setResourceValue("color/something", TypedValue.TYPE_INT_DEC, 1) .build(); waitForResourceValue(0); Loading Loading
core/java/android/content/om/FabricatedOverlay.java +32 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.text.TextUtils; import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.Objects; /** * Fabricated Runtime Resource Overlays (FRROs) are overlays generated ar runtime. Loading Loading @@ -88,6 +89,27 @@ public class FabricatedOverlay { return this; } /** * Ensure the resource name is in the form [package]:type/entry. * * @param name name of the target resource to overlay (in the form [package]:type/entry) * @return the valid name */ private static String ensureValidResourceName(@NonNull String name) { Objects.requireNonNull(name); final int slashIndex = name.indexOf('/'); /* must contain '/' */ final int colonIndex = name.indexOf(':'); /* ':' should before '/' if ':' exist */ // The minimum length of resource type is "id". Preconditions.checkArgument( slashIndex >= 0 /* It must contain the type name */ && colonIndex != 0 /* 0 means the package name is empty */ && (slashIndex - colonIndex) > 2 /* The shortest length of type is "id" */, "\"%s\" is invalid resource name", name); return name; } /** * Sets the value of the fabricated overlay * Loading @@ -99,6 +121,8 @@ public class FabricatedOverlay { * @see android.util.TypedValue#type */ public Builder setResourceValue(@NonNull String resourceName, int dataType, int value) { ensureValidResourceName(resourceName); final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); entry.resourceName = resourceName; entry.dataType = dataType; Loading @@ -120,6 +144,8 @@ public class FabricatedOverlay { */ public Builder setResourceValue(@NonNull String resourceName, int dataType, int value, String configuration) { ensureValidResourceName(resourceName); final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); entry.resourceName = resourceName; entry.dataType = dataType; Loading @@ -140,6 +166,8 @@ public class FabricatedOverlay { * @see android.util.TypedValue#type */ public Builder setResourceValue(@NonNull String resourceName, int dataType, String value) { ensureValidResourceName(resourceName); final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); entry.resourceName = resourceName; entry.dataType = dataType; Loading @@ -161,6 +189,8 @@ public class FabricatedOverlay { */ public Builder setResourceValue(@NonNull String resourceName, int dataType, String value, String configuration) { ensureValidResourceName(resourceName); final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); entry.resourceName = resourceName; entry.dataType = dataType; Loading @@ -180,6 +210,8 @@ public class FabricatedOverlay { */ public Builder setResourceValue(@NonNull String resourceName, ParcelFileDescriptor value, String configuration) { ensureValidResourceName(resourceName); final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); entry.resourceName = resourceName; entry.binaryData = value; Loading
core/tests/overlaytests/device/src/com/android/overlaytest/FabricatedOverlaysTest.java +46 −3 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.overlaytest; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertThrows; Loading @@ -45,7 +44,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeoutException; @RunWith(JUnit4.class) Loading Loading @@ -220,12 +218,57 @@ public class FabricatedOverlaysTest { } } @Test public void setResourceValue_withNullResourceName() throws Exception { final FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()); assertThrows(NullPointerException.class, () -> builder.setResourceValue(null, TypedValue.TYPE_INT_DEC, 1)); } @Test public void setResourceValue_withEmptyResourceName() throws Exception { final FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()); assertThrows(IllegalArgumentException.class, () -> builder.setResourceValue("", TypedValue.TYPE_INT_DEC, 1)); } @Test public void setResourceValue_withEmptyPackageName() throws Exception { final FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()); assertThrows(IllegalArgumentException.class, () -> builder.setResourceValue(":color/mycolor", TypedValue.TYPE_INT_DEC, 1)); } @Test public void setResourceValue_withInvalidTypeName() throws Exception { final FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()); assertThrows(IllegalArgumentException.class, () -> builder.setResourceValue("c/mycolor", TypedValue.TYPE_INT_DEC, 1)); } @Test public void setResourceValue_withEmptyTypeName() throws Exception { final FabricatedOverlay.Builder builder = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()); assertThrows(IllegalArgumentException.class, () -> builder.setResourceValue("/mycolor", TypedValue.TYPE_INT_DEC, 1)); } @Test public void testInvalidResourceValues() throws Exception { final FabricatedOverlay overlay = new FabricatedOverlay.Builder( "android", TEST_OVERLAY_NAME, mContext.getPackageName()) .setResourceValue(TEST_RESOURCE, TypedValue.TYPE_INT_DEC, 1) .setResourceValue("something", TypedValue.TYPE_INT_DEC, 1) .setResourceValue("color/something", TypedValue.TYPE_INT_DEC, 1) .build(); waitForResourceValue(0); Loading