Vectors are now exposed as ArrayList<T> in the Java backend even for arguments
and return values to/from methods, they already were inside structures.
In addition vectors of arrays are now properly marshalled when used as arguments
or results to/from methods.
Bug: 32237331, 32180328
Test: hidl_test_java
Change-Id: Ie24f11668f22fc2c31fb7d8e8da534f1c970f58f
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 71d17bf..f8ddc06 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -451,9 +451,9 @@
////////////////////////////////////////////////////////////////////////////
- out << "public static final "
+ out << "public static final ArrayList<"
<< localName()
- << "[] readVectorFromParcel(HwParcel parcel) {\n";
+ << "> readVectorFromParcel(HwParcel parcel) {\n";
out.indent();
out << "ArrayList<"
@@ -472,9 +472,7 @@
"0",
true /* isReader */);
- out << "\nreturn _hidl_vec.toArray(new "
- << localName()
- << "[_hidl_vec.size()]);\n";
+ out << "\nreturn _hidl_vec;\n";
out.unindent();
out << "}\n\n";
@@ -535,15 +533,11 @@
out << "public static final void writeVectorToParcel(\n";
out.indent();
out.indent();
- out << "HwParcel parcel, "
+ out << "HwParcel parcel, ArrayList<"
<< localName()
- << "[] _hidl_array) {\n";
+ << "> _hidl_vec) {\n";
out.unindent();
- out << "ArrayList<"
- << localName()
- << "> _hidl_vec = new ArrayList(Arrays.asList(_hidl_array));\n";
-
out << "HwBlob _hidl_blob = new HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
VectorType::EmitJavaFieldReaderWriterForElementType(
diff --git a/VectorType.cpp b/VectorType.cpp
index f656281..d7eb581 100644
--- a/VectorType.cpp
+++ b/VectorType.cpp
@@ -59,10 +59,18 @@
std::string VectorType::getJavaType(
std::string *extra, bool /* forInitializer */) const {
- *extra = "[]";
+ extra->clear();
std::string elementExtra;
- return mElementType->getJavaType(&elementExtra) + elementExtra;
+ std::string elementJavaType = mElementType->getJavaType(&elementExtra);
+
+ CHECK(mElementType->isArray() || elementExtra.empty());
+
+ return "ArrayList<"
+ + (mElementType->isArray()
+ ? elementJavaType : mElementType->getJavaWrapperType())
+ + elementExtra
+ + ">";
}
std::string VectorType::getVtsType() const {
@@ -341,6 +349,50 @@
return;
}
+ if (mElementType->isArray()) {
+ if (isReader) {
+ std::string extra;
+ out << " new "
+ << getJavaType(&extra, false /* forInitializer */)
+ << "();\n";
+ }
+
+ out << "{\n";
+ out.indent();
+
+ out << "HwBlob _hidl_blob = ";
+
+ if (isReader) {
+ out << parcelObj
+ << ".readBuffer();\n";
+ } else {
+ size_t align, size;
+ getAlignmentAndSize(&align, &size);
+
+ out << "new HwBlob("
+ << size
+ << " /* size */);\n";
+ }
+
+ emitJavaFieldReaderWriter(
+ out,
+ 0 /* depth */,
+ parcelObj,
+ "_hidl_blob",
+ argName,
+ "0 /* offset */",
+ isReader);
+
+ if (!isReader) {
+ out << parcelObj << ".writeBuffer(_hidl_blob);\n";
+ };
+
+ out.unindent();
+ out << "}\n";
+
+ return;
+ }
+
emitJavaReaderWriterWithSuffix(
out,
parcelObj,
@@ -353,19 +405,15 @@
void VectorType::emitJavaFieldInitializer(
Formatter &out, const std::string &fieldName) const {
std::string extra;
- mElementType->getJavaType(&extra);
+ std::string javaType = getJavaType(&extra, false /* forInitializer */);
- const std::string wrapperType = mElementType->getJavaWrapperType();
-
- out << "final ArrayList<"
- << wrapperType
- << extra
- << "> "
+ out << "final "
+ << javaType
+ << " "
<< fieldName
- << " = new ArrayList<"
- << wrapperType
- << extra
- << ">();\n";
+ << " = new "
+ << javaType
+ << "();\n";
}
void VectorType::emitJavaFieldReaderWriter(
@@ -450,16 +498,8 @@
iteratorName + " * " + std::to_string(elementSize),
true /* isReader */);
- out << fieldName;
-
- if (elementType->isArray()
- && static_cast<const ArrayType *>(
- elementType)->getElementType()->resolveToScalarType()
- != nullptr) {
- out << ".add(HwBlob.wrapArray(_hidl_vec_element));\n";
- } else {
- out << ".add(_hidl_vec_element);\n";
- }
+ out << fieldName
+ << ".add(_hidl_vec_element);\n";
out.unindent();
@@ -577,6 +617,10 @@
return static_cast<ArrayType *>(mElementType)->countDimensions() == 1;
}
+ if (mElementType->isVector()) {
+ return false;
+ }
+
return true;
}
diff --git a/generateJava.cpp b/generateJava.cpp
index 1e0c478..2b14cf0 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -108,7 +108,8 @@
"ERROR: This interface is not Java compatible. The Java backend"
" does NOT support union types nor native handles. "
"In addition, vectors of arrays are limited to at most "
- "one-dimensional arrays.\n");
+ "one-dimensional arrays and vectors of vectors are not "
+ "supported.\n");
return UNKNOWN_ERROR;
}
diff --git a/test/java_test/hidl_test_java_native.cpp b/test/java_test/hidl_test_java_native.cpp
index 5c95948..56410b4 100644
--- a/test/java_test/hidl_test_java_native.cpp
+++ b/test/java_test/hidl_test_java_native.cpp
@@ -52,6 +52,10 @@
const IBase::VectorOfArray &in,
someMethodWithVectorOfArray_cb _hidl_cb) override;
+ Return<void> someMethodTakingAVectorOfArray(
+ const hidl_vec<hidl_array<uint8_t, 6> > &in,
+ someMethodTakingAVectorOfArray_cb _hidl_cb) override;
+
Return<void> transpose(
const IBase::StringMatrix5x3 &in,
transpose_cb _hidl_cb) override;
@@ -118,6 +122,12 @@
static std::string to_string(const IBase::StringMatrix5x3 &M);
static std::string to_string(const IBase::StringMatrix3x5 &M);
+template<typename T, size_t SIZE>
+static std::string to_string(const hidl_array<T, SIZE> &array);
+
+template<size_t SIZE>
+static std::string to_string(const hidl_array<uint8_t, SIZE> &array);
+
template<typename T>
static std::string to_string(const hidl_vec<T> &vec) {
std::string out;
@@ -148,6 +158,23 @@
return out;
}
+template<size_t SIZE>
+static std::string to_string(const hidl_array<uint8_t, SIZE> &array) {
+ std::string out;
+ for (size_t i = 0; i < SIZE; ++i) {
+ if (i > 0) {
+ out += ":";
+ }
+
+ char tmp[3];
+ sprintf(tmp, "%02x", array[i]);
+
+ out += tmp;
+ }
+
+ return out;
+}
+
template<typename T, size_t SIZE1, size_t SIZE2>
static std::string to_string(const hidl_array<T, SIZE1, SIZE2> &array) {
std::string out;
@@ -296,6 +323,26 @@
return Void();
}
+Return<void> Baz::someMethodTakingAVectorOfArray(
+ const hidl_vec<hidl_array<uint8_t, 6> > &in,
+ someMethodTakingAVectorOfArray_cb _hidl_cb) {
+ LOG(INFO) << "Baz::someMethodTakingAVectorOfArray "
+ << to_string(in);
+
+ const size_t n = in.size();
+
+ hidl_vec<hidl_array<uint8_t, 6> > out;
+ out.resize(n);
+
+ for (size_t i = 0; i < n; ++i) {
+ out[i] = in[n - 1 - i];
+ }
+
+ _hidl_cb(out);
+
+ return Void();
+}
+
Return<void> Baz::transpose(
const IBase::StringMatrix5x3 &in, transpose_cb _hidl_cb) {
LOG(INFO) << "Baz::transpose " << to_string(in);
@@ -678,6 +725,27 @@
}));
}
+TEST_F(HidlTest, BazSomeMethodTakingAVectorOfArray) {
+ hidl_vec<hidl_array<uint8_t, 6> > in;
+ in.resize(3);
+
+ size_t k = 0;
+ for (size_t i = 0; i < in.size(); ++i) {
+ for (size_t j = 0; j < 6; ++j, ++k) {
+ in[i][j] = k;
+ }
+ }
+
+ EXPECT_OK(
+ baz->someMethodTakingAVectorOfArray(
+ in,
+ [&](const auto &out) {
+ EXPECT_EQ(
+ to_string(out),
+ "[0c:0d:0e:0f:10:11, 06:07:08:09:0a:0b, 00:01:02:03:04:05]");
+ }));
+}
+
static std::string numberToEnglish(int x) {
static const char *const kDigits[] = {
"zero",
diff --git a/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java b/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java
index 17bef99..efb055c 100644
--- a/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java
+++ b/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java
@@ -93,6 +93,76 @@
return builder.toString();
}
+ public static String fooVecToString(ArrayList<IBase.Foo> vec) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ for (int i = 0; i < vec.size(); ++i) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ builder.append(toString(vec.get(i)));
+ }
+ builder.append("]");
+
+ return builder.toString();
+ }
+
+ public static String macAddressVecToString(ArrayList<byte[]> vec) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ for (int i = 0; i < vec.size(); ++i) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ builder.append(toString(vec.get(i)));
+ }
+ builder.append("]");
+
+ return builder.toString();
+ }
+
+ public static String booleanVecToString(ArrayList<Boolean> vec) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ for (int i = 0; i < vec.size(); ++i) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ builder.append(toString(vec.get(i)));
+ }
+ builder.append("]");
+
+ return builder.toString();
+ }
+
+ public static String integerVecToString(ArrayList<Integer> vec) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ for (int i = 0; i < vec.size(); ++i) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ builder.append(toString(vec.get(i)));
+ }
+ builder.append("]");
+
+ return builder.toString();
+ }
+
+ public static String stringVecToString(ArrayList<String> vec) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ for (int i = 0; i < vec.size(); ++i) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ builder.append(toString(vec.get(i)));
+ }
+ builder.append("]");
+
+ return builder.toString();
+ }
+
public static String toString(IBase.Foo[] array) {
StringBuilder builder = new StringBuilder();
builder.append("[");
@@ -163,6 +233,23 @@
return builder.toString();
}
+ public static String toString(byte[] val) {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < val.length; ++i) {
+ if (i > 0) {
+ builder.append(":");
+ }
+
+ byte b = val[i];
+ if (b < 16) {
+ builder.append("0");
+ }
+ builder.append(Integer.toHexString(b));
+ }
+
+ return builder.toString();
+ }
+
public static String toString(boolean x) {
return x ? "true" : "false";
}
@@ -211,7 +298,7 @@
out.append(", ");
}
- Byte[] address = vec.addresses.get(i);
+ byte[] address = vec.addresses.get(i);
for (int j = 0; j < 6; ++j) {
if (j > 0) {
@@ -399,7 +486,7 @@
}
{
- IBase.Foo[] inputArray = new IBase.Foo[2];
+ ArrayList<IBase.Foo> inputVec = new ArrayList<IBase.Foo>();
IBase.Foo foo = new IBase.Foo();
foo.x = 1;
@@ -414,7 +501,7 @@
foo.y.z = 3.14f;
foo.y.s = "Lorem ipsum...";
- inputArray[0] = foo;
+ inputVec.add(foo);
foo = new IBase.Foo();
foo.x = 2;
@@ -429,11 +516,12 @@
foo.y.z = 1.1414f;
foo.y.s = "Et tu brute?";
- inputArray[1] = foo;
+ inputVec.add(foo);
- IBase.Foo[] outputArray = proxy.someMethodWithFooVectors(inputArray);
+ ArrayList<IBase.Foo> outputVec =
+ proxy.someMethodWithFooVectors(inputVec);
- Expect(toString(outputArray),
+ Expect(fooVecToString(outputVec),
"[Foo(x = 2, " +
"y = Bar(z = 1.1414, s = 'Et tu brute?'), " +
"aaa = [Bar(z = 2.0, s = 'Lorem ipsum 0'), " +
@@ -453,7 +541,7 @@
int k = 0;
for (int i = 0; i < 3; ++i) {
- Byte[] mac = new Byte[6];
+ byte[] mac = new byte[6];
for (int j = 0; j < 6; ++j, ++k) {
mac[j] = (byte)k;
}
@@ -471,6 +559,25 @@
}
{
+ ArrayList<byte[]> in = new ArrayList<byte[]>();
+
+ int k = 0;
+ for (int i = 0; i < 3; ++i) {
+ byte[] mac = new byte[6];
+ for (int j = 0; j < 6; ++j, ++k) {
+ mac[j] = (byte)k;
+ }
+
+ in.add(mac);
+ }
+
+ ArrayList<byte[]> out = proxy.someMethodTakingAVectorOfArray(in);
+
+ Expect(macAddressVecToString(out),
+ "[0c:0d:0e:0f:10:11, 06:07:08:09:0a:0b, 00:01:02:03:04:05]");
+ }
+
+ {
IBase.StringMatrix5x3 in = new IBase.StringMatrix5x3();
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 3; ++j) {
@@ -517,7 +624,12 @@
Expect(toString(proxy.someBoolArrayMethod(someBoolArray)),
"[false, true, false, true]");
- Expect(toString(proxy.someBoolVectorMethod(someBoolArray)),
+ ArrayList<Boolean> someBoolVec = new ArrayList<Boolean>();
+ someBoolVec.add(true);
+ someBoolVec.add(false);
+ someBoolVec.add(true);
+
+ Expect(booleanVecToString(proxy.someBoolVectorMethod(someBoolVec)),
"[false, true, false]");
}
@@ -527,16 +639,18 @@
Expect(toString(proxy.doQuiteABit(1, 2L, 3.0f, 4.0)), "666.5");
{
- int[] param = new int[15];
- for (int i = 0; i < param.length; ++i) {
- param[i] = i;
+ int[] paramArray = new int[15];
+ ArrayList<Integer> paramVec = new ArrayList<Integer>();
+ for (int i = 0; i < paramArray.length; ++i) {
+ paramArray[i] = i;
+ paramVec.add(i);
}
- Expect(toString(proxy.doSomethingElse(param)),
+ Expect(toString(proxy.doSomethingElse(paramArray)),
"[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, " +
"0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2]");
- Expect(toString(proxy.mapThisVector(param)),
+ Expect(integerVecToString(proxy.mapThisVector(paramVec)),
"[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28]");
}
@@ -550,15 +664,20 @@
Expect(toString(proxy.useAnEnum(IBaz.SomeEnum.goober)), "-64");
{
- String[] strings = new String[3];
- strings[0] = "one";
- strings[1] = "two";
- strings[2] = "three";
+ String[] stringArray = new String[3];
+ stringArray[0] = "one";
+ stringArray[1] = "two";
+ stringArray[2] = "three";
- Expect(toString(proxy.haveSomeStrings(strings)),
+ Expect(toString(proxy.haveSomeStrings(stringArray)),
"['Hello', 'World']");
- Expect(toString(proxy.haveAStringVec(strings)),
+ ArrayList<String> stringVec = new ArrayList<String>();
+ stringVec.add("one");
+ stringVec.add("two");
+ stringVec.add("three");
+
+ Expect(stringVecToString(proxy.haveAStringVec(stringVec)),
"['Hello', 'World']");
}
@@ -594,12 +713,13 @@
return fooOutput;
}
- public IBase.Foo[] someMethodWithFooVectors(IBase.Foo[] fooInput) {
- Log.d(TAG, "Baz someMethodWithFooVectors " + HidlTestJava.toString(fooInput));
+ public ArrayList<IBase.Foo> someMethodWithFooVectors(
+ ArrayList<IBase.Foo> fooInput) {
+ Log.d(TAG, "Baz someMethodWithFooVectors " + HidlTestJava.fooVecToString(fooInput));
- IBase.Foo[] fooOutput = new IBase.Foo[2];
- fooOutput[0] = fooInput[1];
- fooOutput[1] = fooInput[0];
+ ArrayList<IBase.Foo> fooOutput = new ArrayList<IBase.Foo>();
+ fooOutput.add(fooInput.get(1));
+ fooOutput.add(fooInput.get(0));
return fooOutput;
}
@@ -617,6 +737,19 @@
return out;
}
+ public ArrayList<byte[/* 6 */]> someMethodTakingAVectorOfArray(
+ ArrayList<byte[/* 6 */]> in) {
+ Log.d(TAG, "Baz someMethodTakingAVectorOfArray");
+
+ int n = in.size();
+ ArrayList<byte[]> out = new ArrayList<byte[]>();
+ for (int i = 0; i < n; ++i) {
+ out.add(in.get(n - i - 1));
+ }
+
+ return out;
+ }
+
public IBase.StringMatrix3x5 transpose(IBase.StringMatrix5x3 in) {
Log.d(TAG, "Baz transpose " + HidlTestJava.toString(in));
@@ -662,12 +795,12 @@
return out;
}
- public boolean[] someBoolVectorMethod(boolean[] x) {
- Log.d(TAG, "Baz someBoolVectorMethod(" + HidlTestJava.toString(x) + ")");
+ public ArrayList<Boolean> someBoolVectorMethod(ArrayList<Boolean> x) {
+ Log.d(TAG, "Baz someBoolVectorMethod(" + HidlTestJava.booleanVecToString(x) + ")");
- boolean[] out = new boolean[x.length];
- for (int i = 0; i < x.length; ++i) {
- out[i] = !x[i];
+ ArrayList<Boolean> out = new ArrayList<Boolean>();
+ for (int i = 0; i < x.size(); ++i) {
+ out.add(!x.get(i));
}
return out;
@@ -706,14 +839,16 @@
return "Hello, world!";
}
- public int[] mapThisVector(int[] param) {
- Log.d(TAG, "mapThisVector " + HidlTestJava.toString(param));
+ public ArrayList<Integer> mapThisVector(ArrayList<Integer> param) {
+ Log.d(TAG, "mapThisVector " + HidlTestJava.integerVecToString(param));
- for (int i = 0; i < param.length; ++i) {
- param[i] *= 2;
+ ArrayList<Integer> out = new ArrayList<Integer>();
+
+ for (int i = 0; i < param.size(); ++i) {
+ out.add(2 * param.get(i));
}
- return param;
+ return out;
}
class BazCallback extends IBazCallback.Stub {
@@ -745,15 +880,15 @@
return result;
}
- public String[] haveAStringVec(String[] vector) {
+ public ArrayList<String> haveAStringVec(ArrayList<String> vector) {
Log.d(TAG, "haveAStringVec ["
- + "\"" + vector[0] + "\", "
- + "\"" + vector[1] + "\", "
- + "\"" + vector[2] + "\"]");
+ + "\"" + vector.get(0) + "\", "
+ + "\"" + vector.get(1) + "\", "
+ + "\"" + vector.get(2) + "\"]");
- String[] result = new String[2];
- result[0] = "Hello";
- result[1] = "World";
+ ArrayList<String> result = new ArrayList<String>();
+ result.add("Hello");
+ result.add("World");
return result;
}