1 /*
2  * Copyright (C) 2022 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 com.google.android.lint.parcel
18 
19 import com.android.tools.lint.checks.infrastructure.LintDetectorTest
20 import com.android.tools.lint.checks.infrastructure.TestLintTask
21 import com.android.tools.lint.checks.infrastructure.TestMode
22 import com.android.tools.lint.detector.api.Detector
23 import com.android.tools.lint.detector.api.Issue
24 
25 @Suppress("UnstableApiUsage")
26 class SaferParcelCheckerTest : LintDetectorTest() {
getDetectornull27     override fun getDetector(): Detector = SaferParcelChecker()
28 
29     override fun getIssues(): List<Issue> = listOf(
30         SaferParcelChecker.ISSUE_UNSAFE_API_USAGE
31     )
32 
33     override fun lint(): TestLintTask =
34         super.lint()
35             .allowMissingSdk(true)
36             // We don't do partial analysis in the platform
37             .skipTestModes(TestMode.PARTIAL)
38 
39     /** Parcel Tests */
40 
41     fun testParcelDetectUnsafeReadSerializable() {
42         lint()
43             .files(
44                 java(
45                     """
46                         package test.pkg;
47                         import android.os.Parcel;
48                         import java.io.Serializable;
49 
50                         public class TestClass {
51                             private TestClass(Parcel p) {
52                                 Serializable ans = p.readSerializable();
53                             }
54                         }
55                         """
56                 ).indented(),
57                 *includes
58             )
59             .expectIdenticalTestModeOutput(false)
60             .run()
61             .expect(
62                 """
63                         src/test/pkg/TestClass.java:7: Warning: Unsafe Parcel.readSerializable() \
64                         API usage [UnsafeParcelApi]
65                                 Serializable ans = p.readSerializable();
66                                                    ~~~~~~~~~~~~~~~~~~~~
67                         0 errors, 1 warnings
68                         """.addLineContinuation()
69             )
70     }
71 
testParcelDoesNotDetectSafeReadSerializablenull72     fun testParcelDoesNotDetectSafeReadSerializable() {
73         lint()
74             .files(
75                 java(
76                     """
77                         package test.pkg;
78                         import android.os.Parcel;
79                         import java.io.Serializable;
80 
81                         public class TestClass {
82                             private TestClass(Parcel p) {
83                                 String ans = p.readSerializable(null, String.class);
84                             }
85                         }
86                         """
87                 ).indented(),
88                 *includes
89             )
90             .run()
91             .expect("No warnings.")
92     }
93 
testParcelDetectUnsafeReadArrayListnull94     fun testParcelDetectUnsafeReadArrayList() {
95         lint()
96             .files(
97                 java(
98                     """
99                         package test.pkg;
100                         import android.os.Parcel;
101 
102                         public class TestClass {
103                             private TestClass(Parcel p) {
104                                 ArrayList ans = p.readArrayList(null);
105                             }
106                         }
107                         """
108                 ).indented(),
109                 *includes
110             )
111             .run()
112             .expect(
113                 """
114                         src/test/pkg/TestClass.java:6: Warning: Unsafe Parcel.readArrayList() API \
115                         usage [UnsafeParcelApi]
116                                 ArrayList ans = p.readArrayList(null);
117                                                 ~~~~~~~~~~~~~~~~~~~~~
118                         0 errors, 1 warnings
119                         """.addLineContinuation()
120             )
121     }
122 
testParcelDoesNotDetectSafeReadArrayListnull123     fun testParcelDoesNotDetectSafeReadArrayList() {
124         lint()
125             .files(
126                 java(
127                     """
128                                 package test.pkg;
129                                 import android.content.Intent;
130                                 import android.os.Parcel;
131 
132                                 public class TestClass {
133                                     private TestClass(Parcel p) {
134                                         ArrayList<Intent> ans = p.readArrayList(null, Intent.class);
135                                     }
136                                 }
137                                 """
138                 ).indented(),
139                 *includes
140             )
141             .run()
142             .expect("No warnings.")
143     }
144 
testParcelDetectUnsafeReadListnull145     fun testParcelDetectUnsafeReadList() {
146         lint()
147             .files(
148                 java(
149                     """
150                                 package test.pkg;
151                                 import android.content.Intent;
152                                 import android.os.Parcel;
153                                 import java.util.List;
154 
155                                 public class TestClass {
156                                     private TestClass(Parcel p) {
157                                         List<Intent> list = new ArrayList<Intent>();
158                                         p.readList(list, null);
159                                     }
160                                 }
161                                 """
162                 ).indented(),
163                 *includes
164             )
165             .run()
166             .expect(
167                 """
168                         src/test/pkg/TestClass.java:9: Warning: Unsafe Parcel.readList() API usage \
169                         [UnsafeParcelApi]
170                                 p.readList(list, null);
171                                 ~~~~~~~~~~~~~~~~~~~~~~
172                         0 errors, 1 warnings
173                         """.addLineContinuation()
174             )
175     }
176 
testDParceloesNotDetectSafeReadListnull177     fun testDParceloesNotDetectSafeReadList() {
178         lint()
179             .files(
180                 java(
181                     """
182                                 package test.pkg;
183                                 import android.content.Intent;
184                                 import android.os.Parcel;
185                                 import java.util.List;
186 
187                                 public class TestClass {
188                                     private TestClass(Parcel p) {
189                                         List<Intent> list = new ArrayList<Intent>();
190                                         p.readList(list, null, Intent.class);
191                                     }
192                                 }
193                                 """
194                 ).indented(),
195                 *includes
196             )
197             .run()
198             .expect("No warnings.")
199     }
200 
testParcelDetectUnsafeReadParcelablenull201     fun testParcelDetectUnsafeReadParcelable() {
202         lint()
203             .files(
204                 java(
205                     """
206                                 package test.pkg;
207                                 import android.content.Intent;
208                                 import android.os.Parcel;
209 
210                                 public class TestClass {
211                                     private TestClass(Parcel p) {
212                                         Intent ans = p.readParcelable(null);
213                                     }
214                                 }
215                                 """
216                 ).indented(),
217                 *includes
218             )
219             .run()
220             .expect(
221                 """
222                         src/test/pkg/TestClass.java:7: Warning: Unsafe Parcel.readParcelable() API \
223                         usage [UnsafeParcelApi]
224                                 Intent ans = p.readParcelable(null);
225                                              ~~~~~~~~~~~~~~~~~~~~~~
226                         0 errors, 1 warnings
227                         """.addLineContinuation()
228             )
229     }
230 
testParcelDoesNotDetectSafeReadParcelablenull231     fun testParcelDoesNotDetectSafeReadParcelable() {
232         lint()
233             .files(
234                 java(
235                     """
236                                 package test.pkg;
237                                 import android.content.Intent;
238                                 import android.os.Parcel;
239 
240                                 public class TestClass {
241                                     private TestClass(Parcel p) {
242                                         Intent ans = p.readParcelable(null, Intent.class);
243                                     }
244                                 }
245                                 """
246                 ).indented(),
247                 *includes
248             )
249             .run()
250             .expect("No warnings.")
251     }
252 
testParcelDetectUnsafeReadParcelableListnull253     fun testParcelDetectUnsafeReadParcelableList() {
254         lint()
255             .files(
256                 java(
257                     """
258                                 package test.pkg;
259                                 import android.content.Intent;
260                                 import android.os.Parcel;
261                                 import java.util.List;
262 
263                                 public class TestClass {
264                                     private TestClass(Parcel p) {
265                                         List<Intent> list = new ArrayList<Intent>();
266                                         List<Intent> ans = p.readParcelableList(list, null);
267                                     }
268                                 }
269                                 """
270                 ).indented(),
271                 *includes
272             )
273             .run()
274             .expect(
275                 """
276                         src/test/pkg/TestClass.java:9: Warning: Unsafe Parcel.readParcelableList() \
277                         API usage [UnsafeParcelApi]
278                                 List<Intent> ans = p.readParcelableList(list, null);
279                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
280                         0 errors, 1 warnings
281                         """.addLineContinuation()
282             )
283     }
284 
testParcelDoesNotDetectSafeReadParcelableListnull285     fun testParcelDoesNotDetectSafeReadParcelableList() {
286         lint()
287             .files(
288                 java(
289                     """
290                                 package test.pkg;
291                                 import android.content.Intent;
292                                 import android.os.Parcel;
293                                 import java.util.List;
294 
295                                 public class TestClass {
296                                     private TestClass(Parcel p) {
297                                         List<Intent> list = new ArrayList<Intent>();
298                                         List<Intent> ans =
299                                                 p.readParcelableList(list, null, Intent.class);
300                                     }
301                                 }
302                                 """
303                 ).indented(),
304                 *includes
305             )
306             .run()
307             .expect("No warnings.")
308     }
309 
testParcelDetectUnsafeReadSparseArraynull310     fun testParcelDetectUnsafeReadSparseArray() {
311         lint()
312             .files(
313                 java(
314                     """
315                                 package test.pkg;
316                                 import android.content.Intent;
317                                 import android.os.Parcel;
318                                 import android.util.SparseArray;
319 
320                                 public class TestClass {
321                                     private TestClass(Parcel p) {
322                                         SparseArray<Intent> ans = p.readSparseArray(null);
323                                     }
324                                 }
325                                 """
326                 ).indented(),
327                 *includes
328             )
329             .run()
330             .expect(
331                 """
332                         src/test/pkg/TestClass.java:8: Warning: Unsafe Parcel.readSparseArray() API\
333                          usage [UnsafeParcelApi]
334                                 SparseArray<Intent> ans = p.readSparseArray(null);
335                                                           ~~~~~~~~~~~~~~~~~~~~~~~
336                         0 errors, 1 warnings
337                         """.addLineContinuation()
338             )
339     }
340 
testParcelDoesNotDetectSafeReadSparseArraynull341     fun testParcelDoesNotDetectSafeReadSparseArray() {
342         lint()
343             .files(
344                 java(
345                     """
346                                 package test.pkg;
347                                 import android.content.Intent;
348                                 import android.os.Parcel;
349                                 import android.util.SparseArray;
350 
351                                 public class TestClass {
352                                     private TestClass(Parcel p) {
353                                         SparseArray<Intent> ans =
354                                                 p.readSparseArray(null, Intent.class);
355                                     }
356                                 }
357                                 """
358                 ).indented(),
359                 *includes
360             )
361             .run()
362             .expect("No warnings.")
363     }
364 
testParcelDetectUnsafeReadSArraynull365     fun testParcelDetectUnsafeReadSArray() {
366         lint()
367             .files(
368                 java(
369                     """
370                                 package test.pkg;
371                                 import android.content.Intent;
372                                 import android.os.Parcel;
373 
374                                 public class TestClass {
375                                     private TestClass(Parcel p) {
376                                         Intent[] ans = p.readArray(null);
377                                     }
378                                 }
379                                 """
380                 ).indented(),
381                 *includes
382             )
383             .run()
384             .expect(
385                 """
386                         src/test/pkg/TestClass.java:7: Warning: Unsafe Parcel.readArray() API\
387                          usage [UnsafeParcelApi]
388                                 Intent[] ans = p.readArray(null);
389                                                ~~~~~~~~~~~~~~~~~
390                         0 errors, 1 warnings
391                         """.addLineContinuation()
392             )
393     }
394 
testParcelDoesNotDetectSafeReadArraynull395     fun testParcelDoesNotDetectSafeReadArray() {
396         lint()
397             .files(
398                 java(
399                     """
400                                 package test.pkg;
401                                 import android.content.Intent;
402                                 import android.os.Parcel;
403 
404                                 public class TestClass {
405                                     private TestClass(Parcel p) {
406                                         Intent[] ans = p.readArray(null, Intent.class);
407                                     }
408                                 }
409                                 """
410                 ).indented(),
411                 *includes
412             )
413             .run()
414             .expect("No warnings.")
415     }
416 
testParcelDetectUnsafeReadParcelableSArraynull417     fun testParcelDetectUnsafeReadParcelableSArray() {
418         lint()
419             .files(
420                 java(
421                     """
422                                 package test.pkg;
423                                 import android.content.Intent;
424                                 import android.os.Parcel;
425 
426                                 public class TestClass {
427                                     private TestClass(Parcel p) {
428                                         Intent[] ans = p.readParcelableArray(null);
429                                     }
430                                 }
431                                 """
432                 ).indented(),
433                 *includes
434             )
435             .run()
436             .expect(
437                 """
438                         src/test/pkg/TestClass.java:7: Warning: Unsafe Parcel.readParcelableArray() API\
439                          usage [UnsafeParcelApi]
440                                 Intent[] ans = p.readParcelableArray(null);
441                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
442                         0 errors, 1 warnings
443                         """.addLineContinuation()
444             )
445     }
446 
testParcelDoesNotDetectSafeReadParcelableArraynull447     fun testParcelDoesNotDetectSafeReadParcelableArray() {
448         lint()
449             .files(
450                 java(
451                     """
452                                 package test.pkg;
453                                 import android.content.Intent;
454                                 import android.os.Parcel;
455 
456                                 public class TestClass {
457                                     private TestClass(Parcel p) {
458                                         Intent[] ans = p.readParcelableArray(null, Intent.class);
459                                     }
460                                 }
461                                 """
462                 ).indented(),
463                 *includes
464             )
465             .run()
466             .expect("No warnings.")
467     }
468 
469     /** Bundle Tests */
470 
testBundleDetectUnsafeGetParcelablenull471     fun testBundleDetectUnsafeGetParcelable() {
472         lint()
473             .files(
474                 java(
475                     """
476                                 package test.pkg;
477                                 import android.content.Intent;
478                                 import android.os.Bundle;
479 
480                                 public class TestClass {
481                                     private TestClass(Bundle b) {
482                                         Intent ans = b.getParcelable("key");
483                                     }
484                                 }
485                                 """
486                 ).indented(),
487                 *includes
488             )
489             .run()
490             .expect(
491                 """
492                     src/test/pkg/TestClass.java:7: Warning: Unsafe Bundle.getParcelable() API usage [UnsafeParcelApi]
493                             Intent ans = b.getParcelable("key");
494                                          ~~~~~~~~~~~~~~~~~~~~~~
495                     0 errors, 1 warnings
496                         """.addLineContinuation()
497             )
498     }
499 
testBundleDoesNotDetectSafeGetParcelablenull500     fun testBundleDoesNotDetectSafeGetParcelable() {
501         lint()
502             .files(
503                 java(
504                     """
505                                 package test.pkg;
506                                 import android.content.Intent;
507                                 import android.os.Bundle;
508 
509                                 public class TestClass {
510                                     private TestClass(Bundle b) {
511                                         Intent ans = b.getParcelable("key", Intent.class);
512                                     }
513                                 }
514                                 """
515                 ).indented(),
516                 *includes
517             )
518             .run()
519             .expect("No warnings.")
520     }
521 
testBundleDetectUnsafeGetParcelableArrayListnull522     fun testBundleDetectUnsafeGetParcelableArrayList() {
523         lint()
524             .files(
525                 java(
526                     """
527                                 package test.pkg;
528                                 import android.content.Intent;
529                                 import android.os.Bundle;
530 
531                                 public class TestClass {
532                                     private TestClass(Bundle b) {
533                                         ArrayList<Intent> ans = b.getParcelableArrayList("key");
534                                     }
535                                 }
536                                 """
537                 ).indented(),
538                 *includes
539             )
540             .run()
541             .expect(
542                 """
543                     src/test/pkg/TestClass.java:7: Warning: Unsafe Bundle.getParcelableArrayList() API usage [UnsafeParcelApi]
544                             ArrayList<Intent> ans = b.getParcelableArrayList("key");
545                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
546                     0 errors, 1 warnings
547                         """.addLineContinuation()
548             )
549     }
550 
testBundleDoesNotDetectSafeGetParcelableArrayListnull551     fun testBundleDoesNotDetectSafeGetParcelableArrayList() {
552         lint()
553             .files(
554                 java(
555                     """
556                                 package test.pkg;
557                                 import android.content.Intent;
558                                 import android.os.Bundle;
559 
560                                 public class TestClass {
561                                     private TestClass(Bundle b) {
562                                         ArrayList<Intent> ans = b.getParcelableArrayList("key", Intent.class);
563                                     }
564                                 }
565                                 """
566                 ).indented(),
567                 *includes
568             )
569             .run()
570             .expect("No warnings.")
571     }
572 
testBundleDetectUnsafeGetParcelableArraynull573     fun testBundleDetectUnsafeGetParcelableArray() {
574         lint()
575             .files(
576                 java(
577                     """
578                                 package test.pkg;
579                                 import android.content.Intent;
580                                 import android.os.Bundle;
581 
582                                 public class TestClass {
583                                     private TestClass(Bundle b) {
584                                         Intent[] ans = b.getParcelableArray("key");
585                                     }
586                                 }
587                                 """
588                 ).indented(),
589                 *includes
590             )
591             .run()
592             .expect(
593                 """
594                     src/test/pkg/TestClass.java:7: Warning: Unsafe Bundle.getParcelableArray() API usage [UnsafeParcelApi]
595                             Intent[] ans = b.getParcelableArray("key");
596                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~
597                     0 errors, 1 warnings
598                         """.addLineContinuation()
599             )
600     }
601 
testBundleDoesNotDetectSafeGetParcelableArraynull602     fun testBundleDoesNotDetectSafeGetParcelableArray() {
603         lint()
604             .files(
605                 java(
606                     """
607                                 package test.pkg;
608                                 import android.content.Intent;
609                                 import android.os.Bundle;
610 
611                                 public class TestClass {
612                                     private TestClass(Bundle b) {
613                                         Intent[] ans = b.getParcelableArray("key", Intent.class);
614                                     }
615                                 }
616                                 """
617                 ).indented(),
618                 *includes
619             )
620             .run()
621             .expect("No warnings.")
622     }
623 
testBundleDetectUnsafeGetSparseParcelableArraynull624     fun testBundleDetectUnsafeGetSparseParcelableArray() {
625         lint()
626             .files(
627                 java(
628                     """
629                                 package test.pkg;
630                                 import android.content.Intent;
631                                 import android.os.Bundle;
632 
633                                 public class TestClass {
634                                     private TestClass(Bundle b) {
635                                         SparseArray<Intent> ans = b.getSparseParcelableArray("key");
636                                     }
637                                 }
638                                 """
639                 ).indented(),
640                 *includes
641             )
642             .run()
643             .expect(
644                 """
645                     src/test/pkg/TestClass.java:7: Warning: Unsafe Bundle.getSparseParcelableArray() API usage [UnsafeParcelApi]
646                             SparseArray<Intent> ans = b.getSparseParcelableArray("key");
647                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
648                     0 errors, 1 warnings
649                         """.addLineContinuation()
650             )
651     }
652 
testBundleDoesNotDetectSafeGetSparseParcelableArraynull653     fun testBundleDoesNotDetectSafeGetSparseParcelableArray() {
654         lint()
655             .files(
656                 java(
657                     """
658                                 package test.pkg;
659                                 import android.content.Intent;
660                                 import android.os.Bundle;
661 
662                                 public class TestClass {
663                                     private TestClass(Bundle b) {
664                                         SparseArray<Intent> ans = b.getSparseParcelableArray("key", Intent.class);
665                                     }
666                                 }
667                                 """
668                 ).indented(),
669                 *includes
670             )
671             .run()
672             .expect("No warnings.")
673     }
674 
675     /** Intent Tests */
676 
testIntentDetectUnsafeGetParcelableExtranull677     fun testIntentDetectUnsafeGetParcelableExtra() {
678         lint()
679             .files(
680                 java(
681                     """
682                                 package test.pkg;
683                                 import android.content.Intent;
684 
685                                 public class TestClass {
686                                     private TestClass(Intent i) {
687                                         Intent ans = i.getParcelableExtra("name");
688                                     }
689                                 }
690                                 """
691                 ).indented(),
692                 *includes
693             )
694             .run()
695             .expect(
696                 """
697                     src/test/pkg/TestClass.java:6: Warning: Unsafe Intent.getParcelableExtra() API usage [UnsafeParcelApi]
698                             Intent ans = i.getParcelableExtra("name");
699                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
700                     0 errors, 1 warnings
701                         """.addLineContinuation()
702             )
703     }
704 
testIntentDoesNotDetectSafeGetParcelableExtranull705     fun testIntentDoesNotDetectSafeGetParcelableExtra() {
706         lint()
707             .files(
708                 java(
709                     """
710                                 package test.pkg;
711                                 import android.content.Intent;
712 
713                                 public class TestClass {
714                                     private TestClass(Intent i) {
715                                         Intent ans = i.getParcelableExtra("name", Intent.class);
716                                     }
717                                 }
718                                 """
719                 ).indented(),
720                 *includes
721             )
722             .run()
723             .expect("No warnings.")
724     }
725 
726 
727     /** Stubs for classes used for testing */
728 
729 
730     private val includes =
731         arrayOf(
732             manifest().minSdk("33"),
733             java(
734                 """
735                         package android.os;
736                         import java.util.ArrayList;
737                         import java.util.List;
738                         import java.util.Map;
739                         import java.util.HashMap;
740 
741                         public final class Parcel {
742                             // Deprecated
743                             public Object[] readArray(ClassLoader loader) { return null; }
744                             public ArrayList readArrayList(ClassLoader loader) { return null; }
745                             public HashMap readHashMap(ClassLoader loader) { return null; }
746                             public void readList(List outVal, ClassLoader loader) {}
747                             public void readMap(Map outVal, ClassLoader loader) {}
748                             public <T extends Parcelable> T readParcelable(ClassLoader loader) { return null; }
749                             public Parcelable[] readParcelableArray(ClassLoader loader) { return null; }
750                             public Parcelable.Creator<?> readParcelableCreator(ClassLoader loader) { return null; }
751                             public <T extends Parcelable> List<T> readParcelableList(List<T> list, ClassLoader cl) { return null; }
752                             public Serializable readSerializable() { return null; }
753                             public <T> SparseArray<T> readSparseArray(ClassLoader loader) { return null; }
754 
755                             // Replacements
756                             public <T> T[] readArray(ClassLoader loader, Class<T> clazz) { return null; }
757                             public <T> ArrayList<T> readArrayList(ClassLoader loader, Class<? extends T> clazz) { return null; }
758                             public <K, V> HashMap<K,V> readHashMap(ClassLoader loader, Class<? extends K> clazzKey, Class<? extends V> clazzValue) { return null; }
759                             public <T> void readList(List<? super T> outVal, ClassLoader loader, Class<T> clazz) {}
760                             public <K, V> void readMap(Map<? super K, ? super V> outVal, ClassLoader loader, Class<K> clazzKey, Class<V> clazzValue) {}
761                             public <T> T readParcelable(ClassLoader loader, Class<T> clazz) { return null; }
762                             public <T> T[] readParcelableArray(ClassLoader loader, Class<T> clazz) { return null; }
763                             public <T> Parcelable.Creator<T> readParcelableCreator(ClassLoader loader, Class<T> clazz) { return null; }
764                             public <T> List<T> readParcelableList(List<T> list, ClassLoader cl, Class<T> clazz) { return null; }
765                             public <T> T readSerializable(ClassLoader loader, Class<T> clazz) { return null; }
766                             public <T> SparseArray<T> readSparseArray(ClassLoader loader, Class<? extends T> clazz) { return null; }
767                         }
768                         """
769             ).indented(),
770             java(
771                 """
772                         package android.os;
773                         import java.util.ArrayList;
774                         import java.util.List;
775                         import java.util.Map;
776                         import java.util.HashMap;
777 
778                         public final class Bundle {
779                             // Deprecated
780                             public <T extends Parcelable> T getParcelable(String key) { return  null; }
781                             public <T extends Parcelable> ArrayList<T> getParcelableArrayList(String key) { return null; }
782                             public Parcelable[] getParcelableArray(String key) { return null; }
783                             public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(String key) { return null; }
784 
785                             // Replacements
786                             public <T> T getParcelable(String key, Class<T> clazz) { return  null; }
787                             public <T> ArrayList<T> getParcelableArrayList(String key, Class<? extends T> clazz) { return null; }
788                             public <T> T[] getParcelableArray(String key, Class<T> clazz) { return null; }
789                             public <T> SparseArray<T> getSparseParcelableArray(String key, Class<? extends T> clazz) { return null; }
790 
791                         }
792                         """
793             ).indented(),
794             java(
795                 """
796                         package android.os;
797                         public interface Parcelable {}
798                         """
799             ).indented(),
800             java(
801                 """
802                         package android.content;
803                         public class Intent implements Parcelable, Cloneable {
804                             // Deprecated
805                             public <T extends Parcelable> T getParcelableExtra(String name) { return null; }
806 
807                             // Replacements
808                             public <T> T getParcelableExtra(String name, Class<T> clazz) { return null; }
809 
810                         }
811                         """
812             ).indented(),
813             java(
814                 """
815                         package android.util;
816                         public class SparseArray<E> implements Cloneable {}
817                         """
818             ).indented(),
819         )
820 
821     // Substitutes "backslash + new line" with an empty string to imitate line continuation
addLineContinuationnull822     private fun String.addLineContinuation(): String = this.trimIndent().replace("\\\n", "")
823 }
824