• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.android.sdkparcelables
18 
19 /** A class that uses an ancestor map to find all classes that
20  * implement android.os.Parcelable, including indirectly through
21  * super classes or super interfaces.
22  */
23 class ParcelableDetector {
24     companion object {
ancestorsToParcelablesnull25         fun ancestorsToParcelables(ancestors: Map<String, Ancestors>): List<String> {
26             val impl = Impl(ancestors)
27             impl.build()
28             return impl.parcelables
29         }
30 
31         const val PARCELABLE_CLASS = "android/os/Parcelable"
32     }
33 
34     private class Impl(val ancestors: Map<String, Ancestors>) {
35         val isParcelableCache = HashMap<String, Boolean>()
36         val parcelables = ArrayList<String>()
37 
buildnull38         fun build() {
39             val classList = ancestors.keys
40             classList.filterTo(parcelables, { (it != PARCELABLE_CLASS) && isParcelable(it) })
41             parcelables.sort()
42         }
43 
isParcelablenull44         private fun isParcelable(c: String?): Boolean {
45             if (c == null) {
46                 return false
47             }
48 
49             if (c == PARCELABLE_CLASS) {
50                 return true
51             }
52 
53             val old = isParcelableCache[c]
54             if (old != null) {
55                 return old
56             }
57 
58             val cAncestors = ancestors[c] ?:
59                     throw RuntimeException("class $c missing ancestor information")
60 
61             val seq = (cAncestors.interfaces?.asSequence() ?: emptySequence()) +
62                     cAncestors.superName
63 
64             val ancestorIsParcelable = seq.any(this::isParcelable)
65 
66             isParcelableCache[c] = ancestorIsParcelable
67             return ancestorIsParcelable
68         }
69     }
70 }
71