• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020, Google LLC
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  * Neither the name of Google LLC nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 package com.android.tools.smali.dexlib2;
32 
33 import com.google.common.collect.ImmutableSet;
34 import com.google.common.collect.ImmutableSet.Builder;
35 
36 import java.util.HashMap;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.StringJoiner;
40 
41 public enum HiddenApiRestriction {
42     WHITELIST(0, "whitelist", false),
43     GREYLIST(1, "greylist", false),
44     BLACKLIST(2, "blacklist", false),
45     GREYLIST_MAX_O(3, "greylist-max-o", false),
46     GREYLIST_MAX_P(4, "greylist-max-p", false),
47     GREYLIST_MAX_Q(5, "greylist-max-q", false),
48     GREYLIST_MAX_R(6, "greylist-max-r", false),
49     CORE_PLATFORM_API(8, "core-platform-api", true),
50     TEST_API(16, "test-api", true);
51 
52     private static final HiddenApiRestriction[] hiddenApiFlags = new HiddenApiRestriction[] {
53             WHITELIST,
54             GREYLIST,
55             BLACKLIST,
56             GREYLIST_MAX_O,
57             GREYLIST_MAX_P,
58             GREYLIST_MAX_Q,
59             GREYLIST_MAX_R
60     };
61 
62     private static final HiddenApiRestriction[] domainSpecificApiFlags = new HiddenApiRestriction[] {
63             CORE_PLATFORM_API,
64             TEST_API
65     };
66 
67     private static final Map<String, HiddenApiRestriction> hiddenApiRestrictionsByName;
68 
69     static {
70         hiddenApiRestrictionsByName = new HashMap<>();
71         for (HiddenApiRestriction hiddenApiRestriction : HiddenApiRestriction.values()) {
hiddenApiRestriction.toString()72             hiddenApiRestrictionsByName.put(hiddenApiRestriction.toString(), hiddenApiRestriction);
73         }
74     }
75 
76     private static final int HIDDENAPI_FLAG_MASK = 0x7;
77 
78     private final int value;
79     private final String name;
80     private final boolean isDomainSpecificApiFlag;
81 
HiddenApiRestriction(int value, String name, boolean isDomainSpecificApiFlag)82     HiddenApiRestriction(int value, String name, boolean isDomainSpecificApiFlag) {
83         this.value = value;
84         this.name = name;
85         this.isDomainSpecificApiFlag = isDomainSpecificApiFlag;
86     }
87 
toString()88     public String toString() {
89         return name;
90     }
91 
getValue()92     public int getValue() {
93         return value;
94     }
95 
isSet(int value)96     public boolean isSet(int value) {
97         if (isDomainSpecificApiFlag) {
98             return (value & this.value) != 0;
99         } else {
100             return (value & HIDDENAPI_FLAG_MASK) == this.value;
101         }
102     }
103 
isDomainSpecificApiFlag()104     public boolean isDomainSpecificApiFlag() {
105         return isDomainSpecificApiFlag;
106     }
107 
getAllFlags(int value)108     public static Set<HiddenApiRestriction> getAllFlags(int value) {
109         HiddenApiRestriction normalRestriction = hiddenApiFlags[value & HIDDENAPI_FLAG_MASK];
110 
111         int domainSpecificPart = (value & ~HIDDENAPI_FLAG_MASK);
112         if (domainSpecificPart == 0) {
113             return ImmutableSet.of(normalRestriction);
114         }
115         Builder<HiddenApiRestriction> builder = ImmutableSet.builder();
116         builder.add(normalRestriction);
117         for (HiddenApiRestriction domainSpecificApiFlag : domainSpecificApiFlags) {
118             if (domainSpecificApiFlag.isSet(value)) {
119                 builder.add(domainSpecificApiFlag);
120             }
121         }
122         return builder.build();
123     }
124 
formatHiddenRestrictions(int value)125     public static String formatHiddenRestrictions(int value) {
126         StringJoiner joiner = new StringJoiner("|");
127         for (HiddenApiRestriction hiddenApiRestriction : getAllFlags(value)) {
128             joiner.add(hiddenApiRestriction.toString());
129         }
130         return joiner.toString();
131     }
132 
combineFlags(Iterable<HiddenApiRestriction> flags)133     public static int combineFlags(Iterable<HiddenApiRestriction> flags) {
134         boolean gotHiddenApiFlag = false;
135 
136         int value = 0;
137 
138         for (HiddenApiRestriction flag : flags) {
139             if (flag.isDomainSpecificApiFlag) {
140                 value += flag.value;
141             } else {
142                 if (gotHiddenApiFlag) {
143                     throw new IllegalArgumentException(
144                             "Cannot combine multiple flags for hidden api restrictions");
145                 }
146                 gotHiddenApiFlag = true;
147                 value += flag.value;
148             }
149         }
150 
151         return value;
152     }
153 
forName(String name)154     public static HiddenApiRestriction forName(String name) {
155         return hiddenApiRestrictionsByName.get(name);
156     }
157 }
158