Skip to content

Commit

Permalink
Handle the NullPointerException when looking up resource value of a…
Browse files Browse the repository at this point in the history
… `DynamicRefTable` when the data type is invalid.

When the data type is invalid, it would make sense to return the corresponding bad code instead of throw an exception.

PiperOrigin-RevId: 631829984
  • Loading branch information
Googler authored and Copybara-Service committed May 8, 2024
1 parent 3cdc3f1 commit 7f57909
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,10 @@ public ApkAssetsCookie GetResource(int resid, boolean may_be_bag,
out_value.set(device_value.copy());

// Convert the package ID to the runtime assigned package ID.
entry.get().dynamic_ref_table.lookupResourceValue(out_value);
int err = entry.get().dynamic_ref_table.lookupResourceValue(out_value);
if (err != NO_ERROR) {
return K_INVALID_COOKIE;
}

out_selected_config.set(new ResTable_config(entry.get().config));
out_flags.set(entry.get().type_flags);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public static DataType fromCode(int code) {
}

public static DataType fromCode(byte code) {
return Preconditions.checkNotNull(FROM_BYTE.get(code), "Unknown resource type: %s", code);
DataType type = FROM_BYTE.get(code);
Preconditions.checkArgument(type != null, "Unknown resource type: %s", code);
return type;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.robolectric.res.android;

// transliterated from https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r12/include/androidfw/ResourceTypes.h
// transliterated from
// https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r12/include/androidfw/ResourceTypes.h

import static org.robolectric.res.android.Errors.BAD_TYPE;
import static org.robolectric.res.android.Errors.NO_ERROR;
import static org.robolectric.res.android.Errors.UNKNOWN_ERROR;
import static org.robolectric.res.android.ResTable.APP_PACKAGE_ID;
Expand Down Expand Up @@ -145,7 +147,15 @@ int lookupResourceId(Ref<Integer> resId) {
int lookupResourceValue(Ref<Res_value> value) {
byte resolvedType = DataType.REFERENCE.code();
Res_value inValue = value.get();
switch (DataType.fromCode(inValue.dataType)) {

DataType dataType;
try {
dataType = DataType.fromCode(inValue.dataType);
} catch (IllegalArgumentException e) {
return BAD_TYPE;
}

switch (dataType) {
case ATTRIBUTE:
resolvedType = DataType.ATTRIBUTE.code();
// fallthrough
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.robolectric.res.android;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public final class DataTypeTest {

@Test
public void fromCode_shouldThrowExceptionForInvalidCode() {
assertThrows(IllegalArgumentException.class, () -> DataType.fromCode(99));
}

@Test
public void fromCode_shouldReturnCorrectDataTypeForValidCode() {
assertThat(DataType.fromCode(0)).isEqualTo(DataType.NULL);
assertThat(DataType.fromCode(3)).isEqualTo(DataType.STRING);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.robolectric.res.android;

import static com.google.common.truth.Truth.assertThat;
import static org.robolectric.res.android.Errors.BAD_TYPE;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.robolectric.res.android.ResourceTypes.Res_value;

@RunWith(JUnit4.class)
public final class DynamicRefTableTest {

private static final Ref<Res_value> RES_VALUE_OF_BAD_TYPE =
new Ref<>(new Res_value(/* dataType= */ (byte) 99, /* data= */ 0));

@Test
public void lookupResourceValue_returnsBadTypeIfTypeOutOfEnumRange() {
DynamicRefTable pseudoRefTable =
new DynamicRefTable(/* packageId= */ (byte) 0, /* appAsLib= */ true);
assertThat(pseudoRefTable.lookupResourceValue(RES_VALUE_OF_BAD_TYPE)).isEqualTo(BAD_TYPE);
}
}

0 comments on commit 7f57909

Please sign in to comment.