| /* |
| * Copyright (C) 2016 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 com.android.commands.hidl_test_java; |
| |
| import android.hidl.manager.V1_0.IServiceManager; |
| import android.hardware.tests.baz.V1_0.IBase; |
| import android.hardware.tests.baz.V1_0.IBaz; |
| import android.hardware.tests.baz.V1_0.IQuux; |
| import android.hardware.tests.baz.V1_0.IBaz.NestedStruct; |
| import android.hardware.tests.baz.V1_0.IBazCallback; |
| import android.os.HwBinder; |
| import android.os.RemoteException; |
| import android.os.HidlSupport; |
| import android.util.Log; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.NoSuchElementException; |
| import java.util.Objects; |
| |
| public final class HidlTestJava { |
| private static final String TAG = "HidlTestJava"; |
| |
| public static void main(String[] args) { |
| int exitCode = 1; |
| try { |
| exitCode = new HidlTestJava().run(args); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| Log.e(TAG, "Error ", e); |
| } |
| System.exit(exitCode); |
| } |
| |
| public int run(String[] args) throws RemoteException { |
| if (args[0].equals("-c")) { |
| client(); |
| } else if (args[0].equals("-s")) { |
| server(); |
| } else { |
| Log.e(TAG, "Usage: HidlTestJava -c(lient) | -s(erver)"); |
| System.err.printf("Usage: HidlTestJava -c(lient) | -s(erver)\n"); |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| final class HidlDeathRecipient implements HwBinder.DeathRecipient { |
| final Object mLock = new Object(); |
| boolean mCalled = false; |
| long mCookie = 0; |
| |
| @Override |
| public void serviceDied(long cookie) { |
| synchronized (mLock) { |
| mCalled = true; |
| mCookie = cookie; |
| mLock.notify(); |
| } |
| } |
| |
| public boolean cookieMatches(long cookie) { |
| synchronized (mLock) { |
| return mCookie == cookie; |
| } |
| } |
| |
| public boolean waitUntilServiceDied(long timeoutMillis) { |
| synchronized(mLock) { |
| while (!mCalled) { |
| try { |
| mLock.wait(timeoutMillis); |
| } catch (InterruptedException e) { |
| continue; // Spin for another loop |
| } |
| break; // got notified or timeout hit |
| } |
| return mCalled; |
| } |
| } |
| }; |
| |
| private void ExpectTrue(boolean x) { |
| if (x) { |
| return; |
| } |
| |
| throw new RuntimeException(); |
| } |
| |
| private void ExpectFalse(boolean x) { |
| ExpectTrue(!x); |
| } |
| |
| private void Expect(String result, String s) { |
| if (result.equals(s)) { |
| return; |
| } |
| |
| System.err.printf("Expected '%s', got '%s'\n", s, result); |
| Log.e(TAG, "Expected '" + s + "', got '" + result + "'"); |
| throw new RuntimeException(); |
| } |
| |
| // .equals and HidlSupport.interfacesEqual should have the same behavior. |
| private void ExpectEqual(android.hidl.base.V1_0.IBase l, android.hidl.base.V1_0.IBase r) { |
| ExpectTrue(Objects.equals(l, r)); |
| ExpectTrue(Objects.equals(r, l)); |
| ExpectTrue(HidlSupport.interfacesEqual(l, r)); |
| ExpectTrue(HidlSupport.interfacesEqual(r, l)); |
| } |
| private void ExpectNotEqual(android.hidl.base.V1_0.IBase l, android.hidl.base.V1_0.IBase r) { |
| ExpectFalse(Objects.equals(l, r)); |
| ExpectFalse(Objects.equals(r, l)); |
| ExpectFalse(HidlSupport.interfacesEqual(l, r)); |
| ExpectFalse(HidlSupport.interfacesEqual(r, l)); |
| } |
| |
| class BazCallback extends IBazCallback.Stub { |
| private boolean mCalled; |
| |
| public BazCallback() { |
| mCalled = false; |
| } |
| |
| boolean wasCalled() { |
| return mCalled; |
| } |
| |
| public void heyItsMe(IBazCallback cb) throws RemoteException { |
| mCalled = true; |
| |
| cb.heyItsMe(null); |
| } |
| |
| public void hey() { |
| mCalled = true; |
| } |
| |
| @Override public boolean equals(Object other) { |
| return other != null && other.getClass() == BazCallback.class && |
| ((BazCallback) other).mCalled == mCalled; |
| } |
| @Override public int hashCode() { return mCalled ? 1 : 0; } |
| } |
| |
| private String numberToEnglish(int x) { |
| final String[] kDigits = { |
| "zero", |
| "one", |
| "two", |
| "three", |
| "four", |
| "five", |
| "six", |
| "seven", |
| "eight", |
| "nine", |
| }; |
| |
| if (x < 0) { |
| return "negative " + numberToEnglish(-x); |
| } |
| |
| if (x < 10) { |
| return kDigits[x]; |
| } |
| |
| if (x <= 15) { |
| final String[] kSpecialTens = { |
| "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", |
| }; |
| |
| return kSpecialTens[x - 10]; |
| } |
| |
| if (x < 20) { |
| return kDigits[x % 10] + "teen"; |
| } |
| |
| if (x < 100) { |
| final String[] kDecades = { |
| "twenty", "thirty", "forty", "fifty", "sixty", "seventy", |
| "eighty", "ninety", |
| }; |
| |
| return kDecades[x / 10 - 2] + kDigits[x % 10]; |
| } |
| |
| return "positively huge!"; |
| } |
| |
| private void ExpectDeepEq(Object l, Object r) { |
| ExpectTrue(HidlSupport.deepEquals(l, r)); |
| ExpectTrue(HidlSupport.deepHashCode(l) == HidlSupport.deepHashCode(r)); |
| } |
| |
| private void ExpectDeepNe(Object l, Object r) { |
| ExpectTrue(!HidlSupport.deepEquals(l, r)); |
| } |
| |
| private void client() throws RemoteException { |
| |
| ExpectDeepEq(null, null); |
| ExpectDeepNe(null, new String()); |
| ExpectDeepNe(new String(), null); |
| ExpectDeepEq(new String(), new String()); |
| ExpectDeepEq("hey", "hey"); |
| |
| ExpectDeepEq(new int[]{1,2}, new int[]{1,2}); |
| ExpectDeepNe(new int[]{1,2}, new int[]{1,3}); |
| ExpectDeepNe(new int[]{1,2}, new int[]{1,2,3}); |
| ExpectDeepEq(new int[][]{{1,2},{3,4}}, new int[][]{{1,2},{3,4}}); |
| ExpectDeepNe(new int[][]{{1,2},{3,4}}, new int[][]{{1,2},{3,5}}); |
| ExpectDeepNe(new int[][]{{1,2},{3,4}}, new int[][]{{1,2,3},{4,5,6}}); |
| ExpectDeepNe(new int[][]{{1,2},{3,4}}, new int[][]{{1,2},{3,4,5}}); |
| |
| ExpectDeepEq(new Integer[]{1,2}, new Integer[]{1,2}); |
| ExpectDeepNe(new Integer[]{1,2}, new Integer[]{1,3}); |
| ExpectDeepNe(new Integer[]{1,2}, new Integer[]{1,2,3}); |
| ExpectDeepEq(new Integer[][]{{1,2},{3,4}}, new Integer[][]{{1,2},{3,4}}); |
| ExpectDeepNe(new Integer[][]{{1,2},{3,4}}, new Integer[][]{{1,2},{3,5}}); |
| ExpectDeepNe(new Integer[][]{{1,2},{3,4}}, new Integer[][]{{1,2,3},{4,5,6}}); |
| ExpectDeepNe(new Integer[][]{{1,2},{3,4}}, new Integer[][]{{1,2},{3,4,5}}); |
| |
| ExpectDeepEq(new ArrayList(Arrays.asList(1, 2)), |
| new ArrayList(Arrays.asList(1, 2))); |
| ExpectDeepNe(new ArrayList(Arrays.asList(1, 2)), |
| new ArrayList(Arrays.asList(1, 2, 3))); |
| |
| ExpectDeepEq(new ArrayList(Arrays.asList(new int[]{1,2}, new int[]{3,4})), |
| new ArrayList(Arrays.asList(new int[]{1,2}, new int[]{3,4}))); |
| ExpectDeepNe(new ArrayList(Arrays.asList(new int[]{1,2}, new int[]{3,4})), |
| new ArrayList(Arrays.asList(new int[]{1,2}, new int[]{3,5}))); |
| |
| ExpectDeepEq(new ArrayList(Arrays.asList(new Integer[]{1,2}, new Integer[]{3,4})), |
| new ArrayList(Arrays.asList(new Integer[]{1,2}, new Integer[]{3,4}))); |
| ExpectDeepNe(new ArrayList(Arrays.asList(new Integer[]{1,2}, new Integer[]{3,4})), |
| new ArrayList(Arrays.asList(new Integer[]{1,2}, new Integer[]{3,5}))); |
| |
| ExpectDeepEq(new ArrayList[]{new ArrayList(Arrays.asList(1,2)), |
| new ArrayList(Arrays.asList(3,4))}, |
| new ArrayList[]{new ArrayList(Arrays.asList(1,2)), |
| new ArrayList(Arrays.asList(3,4))}); |
| |
| { |
| // Test proper exceptions are thrown |
| try { |
| IBase proxy = IBase.getService("this-doesn't-exist"); |
| // this should never run |
| ExpectTrue(false); |
| } catch (Exception e) { |
| ExpectTrue(e instanceof NoSuchElementException); |
| } |
| } |
| |
| { |
| // Test access through base interface binder. |
| IBase baseProxy = IBase.getService("baz"); |
| baseProxy.someBaseMethod(); |
| |
| IBaz bazProxy = IBaz.castFrom(baseProxy); |
| ExpectTrue(bazProxy != null); |
| |
| // IQuux is completely unrelated to IBase/IBaz, so the following |
| // should fail, i.e. return null. |
| IQuux quuxProxy = IQuux.castFrom(baseProxy); |
| ExpectTrue(quuxProxy == null); |
| } |
| |
| { |
| // Test waiting API |
| IBase baseProxyA = IBaz.getService("baz", true /* retry */); |
| ExpectTrue(baseProxyA != null); |
| IBase baseProxyB = IBaz.getService("baz", false /* retry */); |
| ExpectTrue(baseProxyB != null); |
| } |
| |
| IBaz proxy = IBaz.getService("baz"); |
| proxy.someBaseMethod(); |
| |
| { |
| Expect(proxy.interfaceDescriptor(), IBaz.kInterfaceName); |
| } |
| |
| { |
| IBase.Foo foo = new IBase.Foo(); |
| foo.x = 1; |
| |
| for (int i = 0; i < 5; ++i) { |
| IBase.Foo.Bar bar = new IBase.Foo.Bar(); |
| bar.z = 1.0f + (float)i * 0.01f; |
| bar.s = "Hello, world " + i; |
| foo.aaa.add(bar); |
| } |
| |
| foo.y.z = 3.14f; |
| foo.y.s = "Lorem ipsum..."; |
| |
| IBase.Foo result = proxy.someOtherBaseMethod(foo); |
| ExpectTrue(result.equals(foo)); |
| } |
| |
| { |
| IBase.Foo[] inputArray = new IBase.Foo[2]; |
| |
| IBase.Foo foo = new IBase.Foo(); |
| foo.x = 1; |
| |
| for (int i = 0; i < 5; ++i) { |
| IBase.Foo.Bar bar = new IBase.Foo.Bar(); |
| bar.z = 1.0f + (float)i * 0.01f; |
| bar.s = "Hello, world " + i; |
| foo.aaa.add(bar); |
| } |
| |
| foo.y.z = 3.14f; |
| foo.y.s = "Lorem ipsum..."; |
| |
| inputArray[0] = foo; |
| |
| foo = new IBase.Foo(); |
| foo.x = 2; |
| |
| for (int i = 0; i < 3; ++i) { |
| IBase.Foo.Bar bar = new IBase.Foo.Bar(); |
| bar.z = 2.0f - (float)i * 0.01f; |
| bar.s = "Lorem ipsum " + i; |
| foo.aaa.add(bar); |
| } |
| |
| foo.y.z = 1.1414f; |
| foo.y.s = "Et tu brute?"; |
| |
| inputArray[1] = foo; |
| |
| IBase.Foo[] expectedOutputArray = new IBase.Foo[2]; |
| expectedOutputArray[0] = inputArray[1]; |
| expectedOutputArray[1] = inputArray[0]; |
| |
| IBase.Foo[] outputArray = proxy.someMethodWithFooArrays(inputArray); |
| |
| ExpectTrue(java.util.Objects.deepEquals(outputArray, expectedOutputArray)); |
| } |
| |
| { |
| ArrayList<IBase.Foo> inputVec = new ArrayList<IBase.Foo>(); |
| |
| IBase.Foo foo = new IBase.Foo(); |
| foo.x = 1; |
| |
| for (int i = 0; i < 5; ++i) { |
| IBase.Foo.Bar bar = new IBase.Foo.Bar(); |
| bar.z = 1.0f + (float)i * 0.01f; |
| bar.s = "Hello, world " + i; |
| foo.aaa.add(bar); |
| } |
| |
| foo.y.z = 3.14f; |
| foo.y.s = "Lorem ipsum..."; |
| |
| inputVec.add(foo); |
| |
| foo = new IBase.Foo(); |
| foo.x = 2; |
| |
| for (int i = 0; i < 3; ++i) { |
| IBase.Foo.Bar bar = new IBase.Foo.Bar(); |
| bar.z = 2.0f - (float)i * 0.01f; |
| bar.s = "Lorem ipsum " + i; |
| foo.aaa.add(bar); |
| } |
| |
| foo.y.z = 1.1414f; |
| foo.y.s = "Et tu brute?"; |
| |
| inputVec.add(foo); |
| |
| ArrayList<IBase.Foo> expectedOutputVec = new ArrayList<IBase.Foo>(); |
| expectedOutputVec.add(inputVec.get(1)); |
| expectedOutputVec.add(inputVec.get(0)); |
| |
| ArrayList<IBase.Foo> outputVec = |
| proxy.someMethodWithFooVectors(inputVec); |
| |
| ExpectTrue(java.util.Objects.deepEquals(outputVec, expectedOutputVec)); |
| } |
| |
| { |
| IBase.VectorOfArray in = new IBase.VectorOfArray(); |
| |
| 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.addresses.add(mac); |
| } |
| |
| IBase.VectorOfArray expectedOut = new IBase.VectorOfArray(); |
| int n = in.addresses.size(); |
| |
| for (int i = 0; i < n; ++i) { |
| expectedOut.addresses.add(in.addresses.get(n - 1 - i)); |
| } |
| |
| IBase.VectorOfArray out = proxy.someMethodWithVectorOfArray(in); |
| ExpectTrue(out.equals(expectedOut)); |
| } |
| |
| { |
| 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[]> expectedOut = new ArrayList<byte[]>(); |
| |
| int n = in.size(); |
| for (int i = 0; i < n; ++i) { |
| expectedOut.add(in.get(n - 1 - i)); |
| } |
| |
| ArrayList<byte[]> out = proxy.someMethodTakingAVectorOfArray(in); |
| |
| ExpectTrue(out.size() == expectedOut.size()); |
| for (int i = 0; i < n; ++i) { |
| ExpectTrue(java.util.Objects.deepEquals(out.get(i), expectedOut.get(i))); |
| } |
| } |
| |
| { |
| IBase.StringMatrix5x3 in = new IBase.StringMatrix5x3(); |
| IBase.StringMatrix3x5 expectedOut = new IBase.StringMatrix3x5(); |
| |
| for (int i = 0; i < 5; ++i) { |
| for (int j = 0; j < 3; ++j) { |
| in.s[i][j] = numberToEnglish(3 * i + j + 1); |
| expectedOut.s[j][i] = in.s[i][j]; |
| } |
| } |
| |
| IBase.StringMatrix3x5 out = proxy.transpose(in); |
| |
| // [[1 2 3] [4 5 6] [7 8 9] [10 11 12] [13 14 15]]^T |
| // = [[1 4 7 10 13] [2 5 8 11 14] [3 6 9 12 15]] |
| ExpectTrue(out.equals(expectedOut)); |
| } |
| |
| { |
| String[][] in = new String[5][3]; |
| String[][] expectedOut = new String[3][5]; |
| for (int i = 0; i < 5; ++i) { |
| for (int j = 0; j < 3; ++j) { |
| in[i][j] = numberToEnglish(3 * i + j + 1); |
| expectedOut[j][i] = in[i][j]; |
| } |
| } |
| |
| String[][] out = proxy.transpose2(in); |
| |
| // [[1 2 3] [4 5 6] [7 8 9] [10 11 12] [13 14 15]]^T |
| // = [[1 4 7 10 13] [2 5 8 11 14] [3 6 9 12 15]] |
| ExpectTrue(java.util.Arrays.deepEquals(out, expectedOut)); |
| } |
| |
| ExpectTrue(proxy.someBoolMethod(true) == false); |
| |
| { |
| boolean[] someBoolArray = new boolean[3]; |
| someBoolArray[0] = true; |
| someBoolArray[1] = false; |
| someBoolArray[2] = true; |
| |
| boolean[] resultArray = proxy.someBoolArrayMethod(someBoolArray); |
| ExpectTrue(resultArray[0] == false); |
| ExpectTrue(resultArray[1] == true); |
| ExpectTrue(resultArray[2] == false); |
| |
| ArrayList<Boolean> someBoolVec = new ArrayList<Boolean>(); |
| someBoolVec.add(true); |
| someBoolVec.add(false); |
| someBoolVec.add(true); |
| |
| ArrayList<Boolean> resultVec = proxy.someBoolVectorMethod(someBoolVec); |
| ExpectTrue(resultVec.get(0) == false); |
| ExpectTrue(resultVec.get(1) == true); |
| ExpectTrue(resultVec.get(2) == false); |
| } |
| |
| proxy.doThis(1.0f); |
| |
| ExpectTrue(proxy.doThatAndReturnSomething(1) == 666); |
| ExpectTrue(proxy.doQuiteABit(1, 2L, 3.0f, 4.0) == 666.5); |
| |
| { |
| int[] paramArray = new int[15]; |
| int[] expectedOutArray = new int[32]; |
| ArrayList<Integer> paramVec = new ArrayList<Integer>(); |
| ArrayList<Integer> expectedOutVec = new ArrayList<Integer>(); |
| |
| for (int i = 0; i < paramArray.length; ++i) { |
| paramArray[i] = i; |
| paramVec.add(i); |
| |
| expectedOutArray[i] = 2 * i; |
| expectedOutArray[15 + i] = i; |
| |
| expectedOutVec.add(2 * i); |
| } |
| |
| expectedOutArray[30] = 1; |
| expectedOutArray[31] = 2; |
| |
| |
| int[] outArray = proxy.doSomethingElse(paramArray); |
| ExpectTrue(java.util.Objects.deepEquals(outArray, expectedOutArray)); |
| |
| ArrayList<Integer> outVec = proxy.mapThisVector(paramVec); |
| java.util.Objects.equals(outVec, expectedOutVec); |
| |
| } |
| |
| Expect(proxy.doStuffAndReturnAString(), "Hello, world!"); |
| |
| BazCallback cb = new BazCallback(); |
| ExpectTrue(!cb.wasCalled()); |
| proxy.callMe(cb); |
| ExpectTrue(cb.wasCalled()); |
| |
| ExpectTrue(proxy.useAnEnum(IBaz.SomeEnum.goober) == -64); |
| |
| { |
| String[] stringArray = new String[3]; |
| stringArray[0] = "one"; |
| stringArray[1] = "two"; |
| stringArray[2] = "three"; |
| |
| String[] expectedOutArray = new String[2]; |
| expectedOutArray[0] = "Hello"; |
| expectedOutArray[1] = "World"; |
| |
| String[] outArray = proxy.haveSomeStrings(stringArray); |
| ExpectTrue(java.util.Arrays.deepEquals(outArray, expectedOutArray)); |
| |
| ArrayList<String> stringVec = new ArrayList<String>(); |
| stringVec.add("one"); |
| stringVec.add("two"); |
| stringVec.add("three"); |
| |
| ArrayList<String> expectedOutVec = new ArrayList<String>(); |
| expectedOutVec.add("Hello"); |
| expectedOutVec.add("World"); |
| |
| ExpectTrue(expectedOutVec.equals(proxy.haveAStringVec(stringVec))); |
| } |
| |
| proxy.returnABunchOfStrings( |
| new IBaz.returnABunchOfStringsCallback() { |
| @Override |
| public void onValues(String a, String b, String c) { |
| Expect(a, "Eins"); |
| Expect(b, "Zwei"); |
| Expect(c, "Drei"); |
| } |
| }); |
| |
| proxy.returnABunchOfStrings((a,b,c) -> Expect(a + b + c, "EinsZweiDrei")); |
| |
| proxy.callMeLater(new BazCallback()); |
| System.gc(); |
| proxy.iAmFreeNow(); |
| |
| { |
| IBaz.T t1 = new IBaz.T(); |
| IBaz.T t2 = new IBaz.T(); |
| for (int i = 0; i < 5; i++) { |
| for (int j = 0; j < 3; j++) { |
| t1.matrix5x3[i][j] = t2.matrix5x3[i][j] = (i + 1) * (j + 1); |
| } |
| } |
| ExpectTrue(t1.equals(t2)); |
| ExpectTrue(t1.hashCode() == t2.hashCode()); |
| t2.matrix5x3[4][2] = -60; |
| ExpectTrue(!t1.equals(t2)); |
| } |
| |
| ArrayList<NestedStruct> structs = proxy.getNestedStructs(); |
| ExpectTrue(structs.size() == 5); |
| ExpectTrue(structs.get(1).matrices.size() == 6); |
| |
| { |
| IBaz.Everything e = new IBaz.Everything(); |
| Expect(e.toString(), |
| "{.number = 0, .anotherNumber = 0, .s = , " + |
| ".vs = [], .multidimArray = [[null, null], [null, null]], " + |
| ".sArray = [null, null, null], .anotherStruct = {.first = , .last = }, .bf = }"); |
| e.s = "string!"; |
| e.number = 127; |
| e.anotherNumber = 100; |
| e.vs.addAll(Arrays.asList("One", "Two", "Three")); |
| for (int i = 0; i < e.multidimArray.length; i++) |
| for (int j = 0; j < e.multidimArray[i].length; j++) |
| e.multidimArray[i][j] = Integer.toString(i) + Integer.toString(j); |
| e.bf = IBaz.BitField.VALL; |
| e.anotherStruct.first = "James"; |
| e.anotherStruct.last = "Bond"; |
| Expect(e.toString(), |
| "{.number = 127, .anotherNumber = 100, .s = string!, " + |
| ".vs = [One, Two, Three], .multidimArray = [[00, 01], [10, 11]], " + |
| ".sArray = [null, null, null], .anotherStruct = {.first = James, .last = Bond}, " + |
| ".bf = V0 | V1 | V2 | V3 | VALL}"); |
| Expect(IBaz.BitField.toString(IBaz.BitField.VALL), "VALL"); |
| Expect(IBaz.BitField.toString((byte)(IBaz.BitField.V0 | IBaz.BitField.V2)), "0x5"); |
| Expect(IBaz.BitField.dumpBitfield(IBaz.BitField.VALL), "V0 | V1 | V2 | V3 | VALL"); |
| Expect(IBaz.BitField.dumpBitfield((byte)(IBaz.BitField.V1 | IBaz.BitField.V3 | 0xF0)), |
| "V1 | V3 | 0xf0"); |
| |
| Expect(proxy.toString(), IBaz.kInterfaceName + "@Proxy"); |
| } |
| |
| { |
| // Ensure that native parcel is cleared even if the corresponding |
| // Java object isn't GC'd. |
| ArrayList<Integer> data4K = new ArrayList<>(1024); |
| for (int i = 0; i < 1024; i++) { |
| data4K.add(i); |
| } |
| |
| for (int i = 0; i < 1024; i++) { |
| // If they are not properly cleaned up, these calls will put 4MB of data in |
| // kernel binder buffer, and will fail. |
| try { |
| proxy.mapThisVector(data4K); |
| } catch (RemoteException ex) { |
| throw new RuntimeException("Failed at call #" + Integer.toString(i), ex); |
| } |
| } |
| } |
| |
| { |
| // TestArrays |
| IBase.LotsOfPrimitiveArrays in = new IBase.LotsOfPrimitiveArrays(); |
| |
| for (int i = 0; i < 128; ++i) { |
| in.byte1[i] = (byte)i; |
| in.boolean1[i] = (i & 4) != 0; |
| in.double1[i] = i; |
| } |
| |
| int m = 0; |
| for (int i = 0; i < 8; ++i) { |
| for (int j = 0; j < 128; ++j, ++m) { |
| in.byte2[i][j] = (byte)m; |
| in.boolean2[i][j] = (m & 4) != 0; |
| in.double2[i][j] = m; |
| } |
| } |
| |
| m = 0; |
| for (int i = 0; i < 8; ++i) { |
| for (int j = 0; j < 16; ++j) { |
| for (int k = 0; k < 128; ++k, ++m) { |
| in.byte3[i][j][k] = (byte)m; |
| in.boolean3[i][j][k] = (m & 4) != 0; |
| in.double3[i][j][k] = m; |
| } |
| } |
| } |
| |
| IBase.LotsOfPrimitiveArrays out = proxy.testArrays(in); |
| ExpectTrue(in.equals(out)); |
| } |
| |
| { |
| // testByteVecs |
| |
| ArrayList<byte[]> in = new ArrayList<byte[]>(); |
| |
| int k = 0; |
| for (int i = 0; i < in.size(); ++i) { |
| byte[] elem = new byte[128]; |
| for (int j = 0; j < 128; ++j, ++k) { |
| elem[j] = (byte)k; |
| } |
| in.add(elem); |
| } |
| |
| ArrayList<byte[]> out = proxy.testByteVecs(in); |
| ExpectTrue(in.equals(out)); |
| } |
| |
| { |
| // testBooleanVecs |
| |
| ArrayList<boolean[]> in = new ArrayList<boolean[]>(); |
| |
| int k = 0; |
| for (int i = 0; i < in.size(); ++i) { |
| boolean[] elem = new boolean[128]; |
| for (int j = 0; j < 128; ++j, ++k) { |
| elem[j] = (k & 4) != 0; |
| } |
| in.add(elem); |
| } |
| |
| ArrayList<boolean[]> out = proxy.testBooleanVecs(in); |
| ExpectTrue(in.equals(out)); |
| } |
| |
| { |
| // testDoubleVecs |
| |
| ArrayList<double[]> in = new ArrayList<double[]>(); |
| |
| int k = 0; |
| for (int i = 0; i < in.size(); ++i) { |
| double[] elem = new double[128]; |
| for (int j = 0; j < 128; ++j, ++k) { |
| elem[j] = k; |
| } |
| in.add(elem); |
| } |
| |
| ArrayList<double[]> out = proxy.testDoubleVecs(in); |
| ExpectTrue(in.equals(out)); |
| } |
| |
| { |
| // testProxyEquals |
| // TODO(b/68727931): test passthrough services as well. |
| |
| IBase proxy1 = IBase.getService("baz"); |
| IBase proxy2 = IBase.getService("baz"); |
| IBaz proxy3 = IBaz.getService("baz"); |
| IBazCallback callback1 = new BazCallback(); |
| IBazCallback callback2 = new BazCallback(); |
| IServiceManager manager = IServiceManager.getService(); |
| |
| // test hwbinder proxies |
| ExpectEqual(proxy1, proxy2); // same proxy class |
| ExpectEqual(proxy1, proxy3); // different proxy class |
| |
| // negative tests |
| ExpectNotEqual(proxy1, null); |
| ExpectNotEqual(proxy1, callback1); // proxy != stub |
| ExpectNotEqual(proxy1, manager); |
| |
| // HidlSupport.interfacesEqual use overridden .equals for stubs |
| ExpectEqual(callback1, callback1); |
| ExpectEqual(callback1, callback2); |
| callback1.hey(); |
| ExpectNotEqual(callback1, callback2); |
| callback2.hey(); |
| ExpectEqual(callback1, callback2); |
| |
| // test hash for proxies |
| java.util.HashSet<IBase> set = new java.util.HashSet<>(); |
| set.add(proxy1); |
| ExpectTrue(set.contains(proxy1)); // hash is stable |
| ExpectTrue(set.contains(proxy2)); |
| ExpectFalse(set.contains(manager)); |
| } |
| { |
| IBaz baz = IBaz.getService("baz"); |
| ExpectTrue(baz != null); |
| IBaz.StructWithInterface swi = new IBaz.StructWithInterface(); |
| swi.dummy = baz; |
| swi.number = 12345678; |
| IBaz.StructWithInterface swi_back = baz.haveSomeStructWithInterface(swi); |
| ExpectTrue(swi_back != null); |
| ExpectTrue(swi_back.dummy != null); |
| ExpectTrue(HidlSupport.interfacesEqual(baz, swi_back.dummy)); |
| ExpectTrue(swi_back.number == 12345678); |
| } |
| |
| // --- DEATH RECIPIENT TESTING --- |
| // This must always be done last, since it will kill the native server process |
| HidlDeathRecipient recipient1 = new HidlDeathRecipient(); |
| HidlDeathRecipient recipient2 = new HidlDeathRecipient(); |
| |
| final int cookie1 = 0x1481; |
| final int cookie2 = 0x1482; |
| ExpectTrue(proxy.linkToDeath(recipient1, cookie1)); |
| ExpectTrue(proxy.linkToDeath(recipient2, cookie2)); |
| ExpectTrue(proxy.unlinkToDeath(recipient2)); |
| try { |
| proxy.dieNow(); |
| } catch (RemoteException e) { |
| // Expected |
| } |
| ExpectTrue(recipient1.waitUntilServiceDied(2000 /*timeoutMillis*/)); |
| ExpectTrue(!recipient2.waitUntilServiceDied(2000 /*timeoutMillis*/)); |
| ExpectTrue(recipient1.cookieMatches(cookie1)); |
| Log.d(TAG, "OK, exiting"); |
| |
| } |
| |
| class Baz extends IBaz.Stub { |
| // from IBase |
| public void someBaseMethod() { |
| Log.d(TAG, "Baz someBaseMethod"); |
| } |
| |
| public IBase.Foo someOtherBaseMethod(IBase.Foo foo) { |
| Log.d(TAG, "Baz someOtherBaseMethod " + foo.toString()); |
| return foo; |
| } |
| |
| public IBase.Foo[] someMethodWithFooArrays(IBase.Foo[] fooInput) { |
| Log.d(TAG, "Baz someMethodWithFooArrays " + fooInput.toString()); |
| |
| IBase.Foo[] fooOutput = new IBase.Foo[2]; |
| fooOutput[0] = fooInput[1]; |
| fooOutput[1] = fooInput[0]; |
| |
| return fooOutput; |
| } |
| |
| public ArrayList<IBase.Foo> someMethodWithFooVectors( |
| ArrayList<IBase.Foo> fooInput) { |
| Log.d(TAG, "Baz someMethodWithFooVectors " + fooInput.toString()); |
| |
| ArrayList<IBase.Foo> fooOutput = new ArrayList<IBase.Foo>(); |
| fooOutput.add(fooInput.get(1)); |
| fooOutput.add(fooInput.get(0)); |
| |
| return fooOutput; |
| } |
| |
| public IBase.VectorOfArray someMethodWithVectorOfArray( |
| IBase.VectorOfArray in) { |
| Log.d(TAG, "Baz someMethodWithVectorOfArray " + in.toString()); |
| |
| IBase.VectorOfArray out = new IBase.VectorOfArray(); |
| int n = in.addresses.size(); |
| for (int i = 0; i < n; ++i) { |
| out.addresses.add(in.addresses.get(n - i - 1)); |
| } |
| |
| 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 " + in.toString()); |
| |
| IBase.StringMatrix3x5 out = new IBase.StringMatrix3x5(); |
| for (int i = 0; i < 3; ++i) { |
| for (int j = 0; j < 5; ++j) { |
| out.s[i][j] = in.s[j][i]; |
| } |
| } |
| |
| return out; |
| } |
| |
| public String[][] transpose2(String[][] in) { |
| Log.d(TAG, "Baz transpose2 " + in.toString()); |
| |
| String[][] out = new String[3][5]; |
| for (int i = 0; i < 3; ++i) { |
| for (int j = 0; j < 5; ++j) { |
| out[i][j] = in[j][i]; |
| } |
| } |
| |
| return out; |
| } |
| |
| public boolean someBoolMethod(boolean x) { |
| Log.d(TAG, "Baz someBoolMethod(" + x + ")"); |
| |
| return !x; |
| } |
| |
| public boolean[] someBoolArrayMethod(boolean[] x) { |
| Log.d(TAG, "Baz someBoolArrayMethod(" |
| + x.toString() + ")"); |
| |
| boolean[] out = new boolean[4]; |
| out[0] = !x[0]; |
| out[1] = !x[1]; |
| out[2] = !x[2]; |
| out[3] = true; |
| |
| return out; |
| } |
| |
| public ArrayList<Boolean> someBoolVectorMethod(ArrayList<Boolean> x) { |
| Log.d(TAG, "Baz someBoolVectorMethod(" + x.toString() + ")"); |
| |
| ArrayList<Boolean> out = new ArrayList<Boolean>(); |
| for (int i = 0; i < x.size(); ++i) { |
| out.add(!x.get(i)); |
| } |
| |
| return out; |
| } |
| |
| public void doThis(float param) { |
| Log.d(TAG, "Baz doThis " + param); |
| } |
| |
| public int doThatAndReturnSomething(long param) { |
| Log.d(TAG, "Baz doThatAndReturnSomething " + param); |
| return 666; |
| } |
| |
| public double doQuiteABit(int a, long b, float c, double d) { |
| Log.d(TAG, "Baz doQuiteABit " + a + ", " + b + ", " + c + ", " + d); |
| return 666.5; |
| } |
| |
| public int[] doSomethingElse(int[] param) { |
| Log.d(TAG, "Baz doSomethingElse " + param.toString()); |
| |
| int[] something = new int[32]; |
| for (int i = 0; i < 15; ++i) { |
| something[i] = 2 * param[i]; |
| something[15 + i] = param[i]; |
| } |
| something[30] = 1; |
| something[31] = 2; |
| |
| return something; |
| } |
| |
| public String doStuffAndReturnAString() { |
| Log.d(TAG, "doStuffAndReturnAString"); |
| return "Hello, world!"; |
| } |
| |
| public ArrayList<Integer> mapThisVector(ArrayList<Integer> param) { |
| Log.d(TAG, "mapThisVector " + param.toString()); |
| |
| ArrayList<Integer> out = new ArrayList<Integer>(); |
| |
| for (int i = 0; i < param.size(); ++i) { |
| out.add(2 * param.get(i)); |
| } |
| |
| return out; |
| } |
| |
| public void takeAMask(byte bf, byte first, IBase.MyMask second, byte third, |
| takeAMaskCallback cb) { |
| cb.onValues(bf, (byte)(bf | first), |
| (byte)(second.value & bf), (byte)((bf | bf) & third)); |
| } |
| |
| public LotsOfPrimitiveArrays testArrays(LotsOfPrimitiveArrays in) { |
| return in; |
| } |
| |
| public ArrayList<byte[]> testByteVecs(ArrayList<byte[]> in) { |
| return in; |
| } |
| |
| public ArrayList<boolean[]> testBooleanVecs(ArrayList<boolean[]> in) { |
| return in; |
| } |
| |
| public ArrayList<double[]> testDoubleVecs(ArrayList<double[]> in) { |
| return in; |
| } |
| |
| public byte returnABitField() { |
| return 0; |
| } |
| |
| public int size(int size) { |
| return size; |
| } |
| |
| @Override |
| public ArrayList<NestedStruct> getNestedStructs() throws RemoteException { |
| return new ArrayList<>(); |
| } |
| |
| class BazCallback extends IBazCallback.Stub { |
| public void heyItsMe(IBazCallback cb) { |
| Log.d(TAG, "SERVER: heyItsMe"); |
| } |
| |
| public void hey() { |
| Log.d(TAG, "SERVER: hey"); |
| } |
| } |
| |
| public void callMe(IBazCallback cb) throws RemoteException { |
| Log.d(TAG, "callMe"); |
| cb.heyItsMe(new BazCallback()); |
| } |
| |
| private IBazCallback mStoredCallback; |
| public void callMeLater(IBazCallback cb) { |
| mStoredCallback = cb; |
| } |
| |
| public void iAmFreeNow() throws RemoteException { |
| if (mStoredCallback != null) { |
| mStoredCallback.hey(); |
| } |
| } |
| |
| public void dieNow() { |
| // Not tested in Java |
| } |
| |
| public byte useAnEnum(byte zzz) { |
| Log.d(TAG, "useAnEnum " + zzz); |
| return SomeEnum.quux; |
| } |
| |
| public String[] haveSomeStrings(String[] array) { |
| Log.d(TAG, "haveSomeStrings [" |
| + "\"" + array[0] + "\", " |
| + "\"" + array[1] + "\", " |
| + "\"" + array[2] + "\"]"); |
| |
| String[] result = new String[2]; |
| result[0] = "Hello"; |
| result[1] = "World"; |
| |
| return result; |
| } |
| |
| public ArrayList<String> haveAStringVec(ArrayList<String> vector) { |
| Log.d(TAG, "haveAStringVec [" |
| + "\"" + vector.get(0) + "\", " |
| + "\"" + vector.get(1) + "\", " |
| + "\"" + vector.get(2) + "\"]"); |
| |
| ArrayList<String> result = new ArrayList<String>(); |
| result.add("Hello"); |
| result.add("World"); |
| |
| return result; |
| } |
| |
| public void returnABunchOfStrings(returnABunchOfStringsCallback cb) { |
| cb.onValues("Eins", "Zwei", "Drei"); |
| } |
| |
| public StructWithInterface haveSomeStructWithInterface(StructWithInterface swi) { |
| return swi; |
| } |
| } |
| |
| private void server() throws RemoteException { |
| HwBinder.configureRpcThreadpool(1, true); |
| |
| Baz baz = new Baz(); |
| baz.registerAsService("baz"); |
| |
| HwBinder.joinRpcThreadpool(); |
| } |
| } |