Skip to content

Commit

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

Given that the function has the return type as error code, 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 fb268ae
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 fb268ae

Please sign in to comment.