1 /*
2  * Copyright (C) 2015, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.aidl.tests;
18 
19 import android.aidl.tests.SimpleParcelable;
20 import android.aidl.tests.TestFailException;
21 import android.aidl.tests.TestLogger;
22 import android.app.Activity;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.os.ServiceSpecificException;
26 import android.os.Bundle;
27 import android.os.IBinder;
28 import android.os.PersistableBundle;
29 import android.os.RemoteException;
30 import android.os.ServiceManager;
31 import android.util.Log;
32 import java.io.File;
33 import java.io.FileDescriptor;
34 import java.io.FileInputStream;
35 import java.io.FileOutputStream;
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.Collections;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.HashMap;
43 
44 // Generated
45 import android.aidl.tests.INamedCallback;
46 import android.aidl.tests.ITestService;
47 
48 public class TestServiceClient extends Activity {
49     private static final String TAG = "TestServiceClient";
50 
51     private TestLogger mLog;
52     private String mSuccessSentinel;
53     private String mFailureSentinel;
54 
init()55     private void init() {
56         Intent intent = getIntent();
57         mLog = new TestLogger(this);
58         mLog.log("Reading sentinels from intent...");
59         mSuccessSentinel = intent.getStringExtra("sentinel.success");
60         mFailureSentinel = intent.getStringExtra("sentinel.failure");
61         if (mSuccessSentinel == null || mFailureSentinel == null) {
62             String message = "Failed to read intent extra input.";
63             Log.e(TAG, message);
64             mLog.close();
65             throw new RuntimeException(message);
66         }
67     }
68 
getService()69     private ITestService getService() throws TestFailException {
70         IBinder service = new ServiceManager().getService(
71                 ITestService.class.getName());
72         if (service == null) {
73             mLog.logAndThrow("Failed to obtain binder...");
74         }
75         ITestService ret = ITestService.Stub.asInterface(service);
76         if (ret == null) {
77             mLog.logAndThrow("Failed to cast IBinder instance.");
78         }
79         return ret;
80     }
81 
checkPrimitiveRepeat(ITestService service)82     private void checkPrimitiveRepeat(ITestService service)
83             throws TestFailException {
84         mLog.log("Checking that service can repeat primitives back...");
85         try {
86             {
87                 boolean query = true;
88                 boolean response = service.RepeatBoolean(query);
89                 if (query != response) {
90                     mLog.logAndThrow("Repeat with " + query +
91                                      " responded " + response);
92                 }
93             }
94             {
95                 char query = 'A';
96                 char response = service.RepeatChar(query);
97                 if (query != response) {
98                     mLog.logAndThrow("Repeat with " + query +
99                                      " responded " + response);
100                 }
101             }
102             {
103                 byte query = -128;
104                 byte response = service.RepeatByte(query);
105                 if (query != response) {
106                     mLog.logAndThrow("Repeat with " + query +
107                                      " responded " + response);
108                 }
109             }
110             {
111                 int query = 1 << 30;
112                 int response = service.RepeatInt(query);
113                 if (query != response) {
114                     mLog.logAndThrow("Repeat with " + query +
115                                      " responded " + response);
116                 }
117             }
118             {
119                 int query[] = {ITestService.TEST_CONSTANT,
120                                ITestService.TEST_CONSTANT2,
121                                ITestService.TEST_CONSTANT3,
122                                ITestService.TEST_CONSTANT4,
123                                ITestService.TEST_CONSTANT5,
124                                ITestService.TEST_CONSTANT6,
125                                ITestService.TEST_CONSTANT7,
126                                ITestService.TEST_CONSTANT8};
127                 for (int i = 0; i < query.length; i++) {
128                     int response = service.RepeatInt(query[i]);
129                     if (query[i] != response) {
130                         mLog.logAndThrow("Repeat with " + query[i] +
131                                 " responded " + response);
132                     }
133                 }
134             }
135             {
136                 long query = 1L << 60;
137                 long response = service.RepeatLong(query);
138                 if (query != response) {
139                     mLog.logAndThrow("Repeat with " + query +
140                                      " responded " + response);
141                 }
142             }
143             {
144                 float query = 1.0f/3.0f;
145                 float response = service.RepeatFloat(query);
146                 if (query != response) {
147                     mLog.logAndThrow("Repeat with " + query +
148                                      " responded " + response);
149                 }
150             }
151             {
152                 double query = 1.0/3.0;
153                 double response = service.RepeatDouble(query);
154                 if (query != response) {
155                     mLog.logAndThrow("Repeat with " + query +
156                                      " responded " + response);
157                 }
158             }
159             {
160                 Map<String, Object> query = new HashMap<String, Object>();
161                 query.put("first_val", new Byte((byte)-128));
162                 query.put("second_val", new Integer(1<<30));
163                 query.put("third_val", "OHAI");
164                 Object response = service.RepeatMap(query);
165                 if (!query.equals(response)) {
166                     mLog.logAndThrow("Repeat with " + query +
167                                      " responded " + response);
168                 }
169             }
170 
171             List<String> queries = Arrays.asList(
172                 "not empty", "", "\0",
173                 ITestService.STRING_TEST_CONSTANT,
174                 ITestService.STRING_TEST_CONSTANT2);
175             for (String query : queries) {
176                 String response = service.RepeatString(query);
177                 if (!query.equals(response)) {
178                     mLog.logAndThrow("Repeat request with '" + query + "'" +
179                                      " of length " + query.length() +
180                                      " responded with '" + response + "'" +
181                                      " of length " + response.length());
182                 }
183             }
184         } catch (RemoteException ex) {
185             mLog.log(ex.toString());
186             mLog.logAndThrow("Service failed to repeat a primitive back.");
187         }
188         mLog.log("...Basic primitive repeating works.");
189     }
190 
checkArrayReversal(ITestService service)191     private void checkArrayReversal(ITestService service)
192             throws TestFailException {
193         mLog.log("Checking that service can reverse and return arrays...");
194         try {
195             {
196                 boolean[] input = {true, false, false, false};
197                 boolean echoed[] = new boolean[input.length];
198                 boolean[] reversed = service.ReverseBoolean(input, echoed);
199                 if (!Arrays.equals(input, echoed)) {
200                     mLog.logAndThrow("Failed to echo input array back.");
201                 }
202                 if (input.length != reversed.length) {
203                     mLog.logAndThrow("Reversed array is the wrong size.");
204                 }
205                 for (int i = 0; i < input.length; ++i) {
206                     int j = reversed.length - (1 + i);
207                     if (input[i] != reversed[j]) {
208                         mLog.logAndThrow(
209                                 "input[" + i + "] = " + input[i] +
210                                 " but reversed value = " + reversed[j]);
211                     }
212                 }
213             }
214             {
215                 byte[] input = {0, 1, 2};
216                 byte echoed[] = new byte[input.length];
217                 byte[] reversed = service.ReverseByte(input, echoed);
218                 if (!Arrays.equals(input, echoed)) {
219                     mLog.logAndThrow("Failed to echo input array back.");
220                 }
221                 if (input.length != reversed.length) {
222                     mLog.logAndThrow("Reversed array is the wrong size.");
223                 }
224                 for (int i = 0; i < input.length; ++i) {
225                     int j = reversed.length - (1 + i);
226                     if (input[i] != reversed[j]) {
227                         mLog.logAndThrow(
228                                 "input[" + i + "] = " + input[i] +
229                                 " but reversed value = " + reversed[j]);
230                     }
231                 }
232             }
233             {
234                 char[] input = {'A', 'B', 'C', 'D', 'E'};
235                 char echoed[] = new char[input.length];
236                 char[] reversed = service.ReverseChar(input, echoed);
237                 if (!Arrays.equals(input, echoed)) {
238                     mLog.logAndThrow("Failed to echo input array back.");
239                 }
240                 if (input.length != reversed.length) {
241                     mLog.logAndThrow("Reversed array is the wrong size.");
242                 }
243                 for (int i = 0; i < input.length; ++i) {
244                     int j = reversed.length - (1 + i);
245                     if (input[i] != reversed[j]) {
246                         mLog.logAndThrow(
247                                 "input[" + i + "] = " + input[i] +
248                                 " but reversed value = " + reversed[j]);
249                     }
250                 }
251             }
252             {
253                 int[] input = {-1, 0, 1, 2, 3, 4, 5, 6};
254                 int echoed[] = new int[input.length];
255                 int[] reversed = service.ReverseInt(input, echoed);
256                 if (!Arrays.equals(input, echoed)) {
257                     mLog.logAndThrow("Failed to echo input array back.");
258                 }
259                 if (input.length != reversed.length) {
260                     mLog.logAndThrow("Reversed array is the wrong size.");
261                 }
262                 for (int i = 0; i < input.length; ++i) {
263                     int j = reversed.length - (1 + i);
264                     if (input[i] != reversed[j]) {
265                         mLog.logAndThrow(
266                                 "input[" + i + "] = " + input[i] +
267                                 " but reversed value = " + reversed[j]);
268                     }
269                 }
270             }
271             {
272                 long[] input = {-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8};
273                 long echoed[] = new long[input.length];
274                 long[] reversed = service.ReverseLong(input, echoed);
275                 if (!Arrays.equals(input, echoed)) {
276                     mLog.logAndThrow("Failed to echo input array back.");
277                 }
278                 if (input.length != reversed.length) {
279                     mLog.logAndThrow("Reversed array is the wrong size.");
280                 }
281                 for (int i = 0; i < input.length; ++i) {
282                     int j = reversed.length - (1 + i);
283                     if (input[i] != reversed[j]) {
284                         mLog.logAndThrow(
285                                 "input[" + i + "] = " + input[i] +
286                                 " but reversed value = " + reversed[j]);
287                     }
288                 }
289             }
290             {
291                 float[] input = {0.0f, 1.0f, -0.3f};
292                 float echoed[] = new float[input.length];
293                 float[] reversed = service.ReverseFloat(input, echoed);
294                 if (!Arrays.equals(input, echoed)) {
295                     mLog.logAndThrow("Failed to echo input array back.");
296                 }
297                 if (input.length != reversed.length) {
298                     mLog.logAndThrow("Reversed array is the wrong size.");
299                 }
300                 for (int i = 0; i < input.length; ++i) {
301                     int j = reversed.length - (1 + i);
302                     if (input[i] != reversed[j]) {
303                         mLog.logAndThrow(
304                                 "input[" + i + "] = " + input[i] +
305                                 " but reversed value = " + reversed[j]);
306                     }
307                 }
308             }
309             {
310                 double[] input = {-1.0, -4.0, -2.0};
311                 double echoed[] = new double[input.length];
312                 double[] reversed = service.ReverseDouble(input, echoed);
313                 if (!Arrays.equals(input, echoed)) {
314                     mLog.logAndThrow("Failed to echo input array back.");
315                 }
316                 if (input.length != reversed.length) {
317                     mLog.logAndThrow("Reversed array is the wrong size.");
318                 }
319                 for (int i = 0; i < input.length; ++i) {
320                     int j = reversed.length - (1 + i);
321                     if (input[i] != reversed[j]) {
322                         mLog.logAndThrow(
323                                 "input[" + i + "] = " + input[i] +
324                                 " but reversed value = " + reversed[j]);
325                     }
326                 }
327             }
328             {
329                 String[] input = {"For", "relaxing", "times"};
330                 String echoed[] = new String[input.length];
331                 String[] reversed = service.ReverseString(input, echoed);
332                 if (!Arrays.equals(input, echoed)) {
333                     mLog.logAndThrow("Failed to echo input array back.");
334                 }
335                 if (input.length != reversed.length) {
336                     mLog.logAndThrow("Reversed array is the wrong size.");
337                 }
338                 for (int i = 0; i < input.length; ++i) {
339                     int j = reversed.length - (1 + i);
340                     if (!input[i].equals(reversed[j])) {
341                         mLog.logAndThrow(
342                                 "input[" + i + "] = " + input[i] +
343                                 " but reversed value = " + reversed[j]);
344                     }
345                 }
346             }
347         } catch (RemoteException ex) {
348             mLog.log(ex.toString());
349             mLog.logAndThrow("Service failed to reverse an array.");
350         }
351         mLog.log("...service can reverse and return arrays.");
352     }
353 
checkBinderExchange( ITestService service)354     private void checkBinderExchange(
355                 ITestService service) throws TestFailException {
356       mLog.log("Checking exchange of binders...");
357       try {
358           INamedCallback got = service.GetOtherTestService("Smythe");
359           mLog.log("Received test service");
360           String name = got.GetName();
361 
362           if (!name.equals("Smythe")) {
363               mLog.logAndThrow("Tried to get service with name 'Smythe'" +
364                                " and found service with name '" + name + "'");
365           }
366 
367           if (!service.VerifyName(got, "Smythe")) {
368               mLog.logAndThrow("Test service could not verify name of 'Smythe'");
369           }
370       } catch (RemoteException ex) {
371           mLog.log(ex.toString());
372           mLog.logAndThrow("Service failed to exchange binders.");
373       }
374       mLog.log("...Exchange of binders works");
375     }
376 
checkListReversal(ITestService service)377     private void checkListReversal(ITestService service)
378             throws TestFailException {
379         mLog.log("Checking that service can reverse and return lists...");
380         try {
381             {
382                 List<String> input = Arrays.asList("Walk", "into", "Córdoba");
383                 List<String> echoed = new ArrayList<String>();
384                 List<String> reversed = service.ReverseStringList(input, echoed);
385                 if (!input.equals(echoed)) {
386                     mLog.logAndThrow("Failed to echo input List<String> back.");
387                 }
388                 Collections.reverse(input);
389                 if (!input.equals(reversed)) {
390                     mLog.logAndThrow("Reversed list is not correct.");
391                 }
392             }
393         } catch (RemoteException ex) {
394             mLog.log(ex.toString());
395             mLog.logAndThrow("Service failed to reverse an List<String>.");
396         }
397         mLog.log("...service can reverse and return lists.");
398     }
399 
checkSimpleParcelables(ITestService service)400     private void checkSimpleParcelables(ITestService service)
401             throws TestFailException {
402         mLog.log("Checking that service can repeat and reverse SimpleParcelable objects...");
403         try {
404             {
405                 SimpleParcelable input = new SimpleParcelable("foo", 42);
406                 SimpleParcelable out_param = new SimpleParcelable();
407                 SimpleParcelable returned =
408                         service.RepeatSimpleParcelable(input, out_param);
409                 if (!input.equals(out_param)) {
410                     mLog.log(input.toString() + " != " + out_param.toString());
411                     mLog.logAndThrow("out param SimpleParcelable was not equivalent");
412                 }
413                 if (!input.equals(returned)) {
414                     mLog.log(input.toString() + " != " + returned.toString());
415                     mLog.logAndThrow("returned SimpleParcelable was not equivalent");
416                 }
417             }
418             {
419                 SimpleParcelable[] input = new SimpleParcelable[3];
420                 input[0] = new SimpleParcelable("a", 1);
421                 input[1] = new SimpleParcelable("b", 2);
422                 input[2] = new SimpleParcelable("c", 3);
423                 SimpleParcelable[] repeated = new SimpleParcelable[3];
424                 SimpleParcelable[] reversed = service.ReverseSimpleParcelables(
425                         input, repeated);
426                 if (!Arrays.equals(input, repeated)) {
427                     mLog.logAndThrow(
428                             "Repeated list of SimpleParcelable objects did not match.");
429                 }
430                 if (input.length != reversed.length) {
431                     mLog.logAndThrow(
432                             "Reversed list of SimpleParcelable objects had wrong length.");
433                 }
434                 for (int i = 0, k = input.length - 1;
435                      i < input.length;
436                      ++i, --k) {
437                     if (!input[i].equals(reversed[k])) {
438                         mLog.log(input[i].toString() + " != " +
439                                  reversed[k].toString());
440                         mLog.logAndThrow("reversed SimpleParcelable was not equivalent");
441                     }
442                 }
443             }
444         } catch (Exception ex) {
445             mLog.log(ex.toString());
446             mLog.logAndThrow("Service failed to handle SimpleParcelable objects.");
447         }
448         mLog.log("...service can manipulate SimpleParcelable objects.");
449     }
450 
checkPersistableBundles(ITestService service)451     private void checkPersistableBundles(ITestService service)
452             throws TestFailException {
453         mLog.log("Checking that service can repeat and reverse PersistableBundle objects...");
454         try {
455             {
456                 PersistableBundle emptyBundle = new PersistableBundle();
457                 PersistableBundle returned = service.RepeatPersistableBundle(emptyBundle);
458                 if (emptyBundle.size() != 0 || returned.size() != 0) {
459                     mLog.log(emptyBundle.toString() + " != " + returned.toString());
460                     mLog.logAndThrow("returned empty PersistableBundle object was not equivalent");
461                 }
462                 mLog.log("...service can repeat and reverse empty PersistableBundle objects...");
463             }
464             {
465                 final String testBoolKey = new String("testBool");
466                 final String testIntKey = new String("testInt");
467                 final String testNestedIntKey = new String("testNestedInt");
468                 final String testLongKey = new String("testLong");
469                 final String testDoubleKey = new String("testDouble");
470                 final String testStringKey = new String("testString");
471                 final String testBoolArrayKey = new String("testBoolArray");
472                 final String testIntArrayKey = new String("testIntArray");
473                 final String testLongArrayKey = new String("testLongArray");
474                 final String testDoubleArrayKey = new String("testDoubleArray");
475                 final String testStringArrayKey = new String("testStringArray");
476                 final String testPersistableBundleKey = new String("testPersistableBundle");
477                 PersistableBundle nonEmptyBundle = new PersistableBundle();
478                 nonEmptyBundle.putBoolean(testBoolKey, false);
479                 nonEmptyBundle.putInt(testIntKey, 33);
480                 nonEmptyBundle.putLong(testLongKey, 34359738368L);
481                 nonEmptyBundle.putDouble(testDoubleKey, 1.1);
482                 nonEmptyBundle.putString(testStringKey, new String("Woot!"));
483                 nonEmptyBundle.putBooleanArray(testBoolArrayKey, new boolean[] {true, false, true});
484                 nonEmptyBundle.putIntArray(testIntArrayKey, new int[] {33, 44, 55, 142});
485                 nonEmptyBundle.putLongArray(
486                     testLongArrayKey, new long[] {34L, 8371L, 34359738375L});
487                 nonEmptyBundle.putDoubleArray(testDoubleArrayKey, new double[] {2.2, 5.4});
488                 nonEmptyBundle.putStringArray(testStringArrayKey, new String[] {"hello", "world!"});
489                 PersistableBundle testNestedPersistableBundle = new PersistableBundle();
490                 testNestedPersistableBundle.putInt(testNestedIntKey, 345);
491                 nonEmptyBundle.putPersistableBundle(
492                     testPersistableBundleKey, testNestedPersistableBundle);
493                 PersistableBundle returned = service.RepeatPersistableBundle(nonEmptyBundle);
494                 if (returned.size() != nonEmptyBundle.size()
495                     || returned.getBoolean(testBoolKey) != nonEmptyBundle.getBoolean(testBoolKey)
496                     || returned.getInt(testIntKey) != nonEmptyBundle.getInt(testIntKey)
497                     || returned.getLong(testLongKey) != nonEmptyBundle.getLong(testLongKey)
498                     || returned.getDouble(testDoubleKey) != nonEmptyBundle.getDouble(testDoubleKey)
499                     || !returned.getString(testStringKey)
500                                 .equals(nonEmptyBundle.getString(testStringKey))
501                     || !Arrays.equals(nonEmptyBundle.getBooleanArray(testBoolArrayKey),
502                                       returned.getBooleanArray(testBoolArrayKey))
503                     || !Arrays.equals(nonEmptyBundle.getIntArray(testIntArrayKey),
504                                       returned.getIntArray(testIntArrayKey))
505                     || !Arrays.equals(nonEmptyBundle.getLongArray(testLongArrayKey),
506                                       returned.getLongArray(testLongArrayKey))
507                     || !Arrays.equals(nonEmptyBundle.getDoubleArray(testDoubleArrayKey),
508                                       returned.getDoubleArray(testDoubleArrayKey))
509                     || !Arrays.equals(nonEmptyBundle.getStringArray(testStringArrayKey),
510                                       returned.getStringArray(testStringArrayKey))) {
511                     PersistableBundle temp =
512                         returned.getPersistableBundle(testPersistableBundleKey);
513                     if (temp == null
514                         || temp.getInt(testNestedIntKey)
515                             != testNestedPersistableBundle.getInt(testNestedIntKey)) {
516                         mLog.log(nonEmptyBundle.toString() + " != " + returned.toString());
517                         mLog.logAndThrow("returned non-empty PersistableBundle " +
518                                          "object was not equivalent");
519                     }
520                 }
521                 mLog.log("...service can repeat and reverse non-empty " +
522                          "PersistableBundle objects...");
523             }
524             {
525                 PersistableBundle[] input = new PersistableBundle[3];
526                 PersistableBundle first = new PersistableBundle();
527                 PersistableBundle second = new PersistableBundle();
528                 PersistableBundle third = new PersistableBundle();
529                 final String testIntKey = new String("testInt");
530                 final String testLongKey = new String("testLong");
531                 final String testDoubleKey = new String("testDouble");
532                 first.putInt(testIntKey, 1231);
533                 second.putLong(testLongKey, 222222L);
534                 third.putDouble(testDoubleKey, 10.8);
535                 input[0] = first;
536                 input[1] = second;
537                 input[2] = third;
538                 final int original_input_size = input.length;
539                 PersistableBundle[] repeated = new PersistableBundle[input.length];
540                 PersistableBundle[] reversed = service.ReversePersistableBundles(input, repeated);
541                 if (input.length != repeated.length || input.length != original_input_size) {
542                     mLog.logAndThrow("Repeated list of PersistableBundle objects had " +
543                                      "wrong length.");
544                 }
545                 if (input[0].getInt(testIntKey) != repeated[0].getInt(testIntKey)
546                     || input[1].getLong(testLongKey) != repeated[1].getLong(testLongKey)
547                     || input[2].getDouble(testDoubleKey) != repeated[2].getDouble(testDoubleKey)) {
548                     mLog.logAndThrow("Repeated list of PersistableBundle objects did not match.");
549                 }
550                 if (input.length != reversed.length || input.length != original_input_size) {
551                     mLog.logAndThrow("Reversed list of PersistableBundle objects had " +
552                                      "wrong length.");
553                 }
554                 if (input[0].getInt(testIntKey) != reversed[2].getInt(testIntKey)
555                     || input[1].getLong(testLongKey) != reversed[1].getLong(testLongKey)
556                     || input[2].getDouble(testDoubleKey) != reversed[0].getDouble(testDoubleKey)) {
557                     mLog.logAndThrow("reversed PersistableBundle objects were not equivalent");
558                 }
559                 mLog.log("...service can repeat and reverse arrays of " +
560                          "non-empty PersistableBundle objects...");
561             }
562         } catch (Exception ex) {
563             mLog.log(ex.toString());
564             mLog.logAndThrow("Service failed to handle PersistableBundle objects.");
565         }
566         mLog.log("...service can manipulate PersistableBundle objects.");
567     }
568 
checkFileDescriptorPassing(ITestService service)569     private void checkFileDescriptorPassing(ITestService service)
570             throws TestFailException {
571         mLog.log("Checking that service can receive and return file descriptors...");
572         try {
573             FileOutputStream fileOutputStream =
574                     openFileOutput("test-dummy", Context.MODE_PRIVATE);
575 
576             FileDescriptor descriptor = fileOutputStream.getFD();
577             FileDescriptor journeyed = service.RepeatFileDescriptor(descriptor);
578             fileOutputStream.close();
579 
580             FileOutputStream journeyedStream = new FileOutputStream(journeyed);
581 
582             String testData = "FrazzleSnazzleFlimFlamFlibbityGumboChops";
583             byte[] output = testData.getBytes();
584             journeyedStream.write(output);
585             journeyedStream.close();
586 
587             FileInputStream fileInputStream = openFileInput("test-dummy");
588             byte[] input = new byte[output.length];
589             if (fileInputStream.read(input) != input.length) {
590                 mLog.logAndThrow("Read short count from file");
591             }
592 
593             if (!Arrays.equals(input, output)) {
594                 mLog.logAndThrow("Read incorrect data");
595             }
596         } catch (RemoteException ex) {
597             mLog.log(ex.toString());
598             mLog.logAndThrow("Service failed to repeat a file descriptor.");
599         } catch (IOException ex) {
600             mLog.log(ex.toString());
601             mLog.logAndThrow("Exception while operating on temporary file");
602         }
603         mLog.log("...service can receive and return file descriptors.");
604     }
605 
checkServiceSpecificExceptions( ITestService service)606     private void checkServiceSpecificExceptions(
607                 ITestService service) throws TestFailException {
608         mLog.log("Checking application exceptions...");
609         for (int i = -1; i < 2; ++i) {
610             try {
611                 service.ThrowServiceException(i);
612             } catch (RemoteException ex) {
613                 mLog.logAndThrow("Service threw RemoteException: " +
614                                  ex.toString());
615             } catch (ServiceSpecificException ex) {
616                 if (ex.errorCode != i) {
617                     mLog.logAndThrow("Service threw wrong error code: " + i);
618                 }
619             }
620         }
621         mLog.log("...application exceptions work");
622     }
623 
checkUtf8Strings(ITestService service)624     private void checkUtf8Strings(ITestService service)
625             throws TestFailException {
626         mLog.log("Checking that service can work with UTF8 strings...");
627         // Note that Java's underlying encoding is UTF16.
628         final List<String> utf8_queries = Arrays.asList(
629               "typical string",
630               "",
631               "\0\0\0",
632               // Java doesn't handle unicode code points above U+FFFF well.
633               new String(Character.toChars(0x1F701)) + "\u03A9");
634         final List<String> utf8_queries_and_nulls = Arrays.asList(
635               "typical string",
636               null,
637               "",
638               "\0\0\0",
639               null,
640               // Java doesn't handle unicode code points above U+FFFF well.
641               new String(Character.toChars(0x1F701)) + "\u03A9");
642         try {
643             for (String query : utf8_queries) {
644                 String response = service.RepeatUtf8CppString(query);
645                 if (!query.equals(response)) {
646                     mLog.logAndThrow("Repeat request with '" + query + "'" +
647                                      " of length " + query.length() +
648                                      " responded with '" + response + "'" +
649                                      " of length " + response.length());
650                 }
651             }
652             {
653                 String[] input = (String[])utf8_queries.toArray();
654                 String echoed[] = new String[input.length];
655                 String[] reversed = service.ReverseUtf8CppString(input, echoed);
656                 if (!Arrays.equals(input, echoed)) {
657                     mLog.logAndThrow("Failed to echo utf8 input array back.");
658                 }
659                 if (input.length != reversed.length) {
660                     mLog.logAndThrow("Reversed utf8 array is the wrong size.");
661                 }
662                 for (int i = 0; i < input.length; ++i) {
663                     int j = reversed.length - (1 + i);
664                     if (!input[i].equals(reversed[j])) {
665                         mLog.logAndThrow(
666                                 "input[" + i + "] = " + input[i] +
667                                 " but reversed value = " + reversed[j]);
668                     }
669                 }
670             }
671             {
672                 String[] input = (String[])utf8_queries_and_nulls.toArray();
673                 String echoed[] = new String[input.length];
674                 String[] reversed = service.ReverseNullableUtf8CppString(input,
675                     echoed);
676                 if (!Arrays.equals(input, echoed)) {
677                     mLog.logAndThrow("Failed to echo utf8 input array back.");
678                 }
679                 if (input.length != reversed.length) {
680                     mLog.logAndThrow("Reversed utf8 array is the wrong size.");
681                 }
682                 for (int i = 0; i < input.length; ++i) {
683                     int j = reversed.length - (1 + i);
684                     if (input[i] == null && reversed[j] == null) {
685                         continue;
686                     }
687 
688                     if (!input[i].equals(reversed[j])) {
689                         mLog.logAndThrow(
690                                 "input[" + i + "] = " + input[i] +
691                                 " but reversed value = " + reversed[j]);
692                     }
693                 }
694             }
695         } catch (RemoteException ex) {
696             mLog.log(ex.toString());
697             mLog.logAndThrow("Service failed to handle utf8 strings.");
698         }
699         mLog.log("...UTF8 annotations work.");
700     }
701 
702     @Override
onCreate(Bundle savedInstanceState)703     protected void onCreate(Bundle savedInstanceState) {
704         super.onCreate(savedInstanceState);
705         Log.i(TAG, "Starting!");
706         try {
707           init();
708           ITestService service = getService();
709           checkPrimitiveRepeat(service);
710           checkArrayReversal(service);
711           checkBinderExchange(service);
712           checkListReversal(service);
713           checkSimpleParcelables(service);
714           checkPersistableBundles(service);
715           checkFileDescriptorPassing(service);
716           checkServiceSpecificExceptions(service);
717           checkUtf8Strings(service);
718           new NullableTests(service, mLog).runTests();
719 
720           mLog.log(mSuccessSentinel);
721         } catch (TestFailException e) {
722             mLog.log(mFailureSentinel);
723             throw new RuntimeException(e);
724         } finally {
725             if (mLog != null) {
726                 mLog.close();
727             }
728         }
729     }
730 }
731