1 /*
2  * Copyright (C) 2007 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.dx.rop.code;
18 
19 import com.android.dx.util.Hex;
20 
21 /**
22  * Constants used as "access flags" in various places in classes, and
23  * related utilities. Although, at the rop layer, flags are generally
24  * ignored, this is the layer of communication, and as such, this
25  * package is where these definitions belong. The flag definitions are
26  * identical to Java access flags, but {@code ACC_SUPER} isn't
27  * used at all in translated code, and {@code ACC_SYNCHRONIZED}
28  * is only used in a very limited way.
29  */
30 public final class AccessFlags {
31     /** public member / class */
32     public static final int ACC_PUBLIC = 0x0001;
33 
34     /** private member */
35     public static final int ACC_PRIVATE = 0x0002;
36 
37     /** protected member */
38     public static final int ACC_PROTECTED = 0x0004;
39 
40     /** static member */
41     public static final int ACC_STATIC = 0x0008;
42 
43     /** final member / class */
44     public static final int ACC_FINAL = 0x0010;
45 
46     /**
47      * synchronized method; only valid in dex files for {@code native}
48      * methods
49      */
50     public static final int ACC_SYNCHRONIZED = 0x0020;
51 
52     /**
53      * class with new-style {@code invokespecial} for superclass
54      * method access
55      */
56     public static final int ACC_SUPER = 0x0020;
57 
58     /** volatile field */
59     public static final int ACC_VOLATILE = 0x0040;
60 
61     /** bridge method (generated) */
62     public static final int ACC_BRIDGE = 0x0040;
63 
64     /** transient field */
65     public static final int ACC_TRANSIENT = 0x0080;
66 
67     /** varargs method */
68     public static final int ACC_VARARGS = 0x0080;
69 
70     /** native method */
71     public static final int ACC_NATIVE = 0x0100;
72 
73     /** "class" is in fact an public static final interface */
74     public static final int ACC_INTERFACE = 0x0200;
75 
76     /** abstract method / class */
77     public static final int ACC_ABSTRACT = 0x0400;
78 
79     /**
80      * method with strict floating point ({@code strictfp})
81      * behavior
82      */
83     public static final int ACC_STRICT = 0x0800;
84 
85     /** synthetic member */
86     public static final int ACC_SYNTHETIC = 0x1000;
87 
88     /** class is an annotation type */
89     public static final int ACC_ANNOTATION = 0x2000;
90 
91     /**
92      * class is an enumerated type; field is an element of an enumerated
93      * type
94      */
95     public static final int ACC_ENUM = 0x4000;
96 
97     /** method is a constructor */
98     public static final int ACC_CONSTRUCTOR = 0x10000;
99 
100     /**
101      * method was declared {@code synchronized}; has no effect on
102      * execution (other than inspecting this flag, per se)
103      */
104     public static final int ACC_DECLARED_SYNCHRONIZED = 0x20000;
105 
106     /** flags defined on classes */
107     public static final int CLASS_FLAGS =
108         ACC_PUBLIC | ACC_FINAL | ACC_SUPER | ACC_INTERFACE | ACC_ABSTRACT |
109         ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM;
110 
111     /** flags defined on inner classes */
112     public static final int INNER_CLASS_FLAGS =
113         ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL |
114         ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION |
115         ACC_ENUM;
116 
117     /** flags defined on fields */
118     public static final int FIELD_FLAGS =
119         ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL |
120         ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM;
121 
122     /** flags defined on methods */
123     public static final int METHOD_FLAGS =
124         ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL |
125         ACC_SYNCHRONIZED | ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE |
126         ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC | ACC_CONSTRUCTOR |
127         ACC_DECLARED_SYNCHRONIZED;
128 
129     /** indicates conversion of class flags */
130     private static final int CONV_CLASS = 1;
131 
132     /** indicates conversion of field flags */
133     private static final int CONV_FIELD = 2;
134 
135     /** indicates conversion of method flags */
136     private static final int CONV_METHOD = 3;
137 
138     /**
139      * This class is uninstantiable.
140      */
AccessFlags()141     private AccessFlags() {
142         // This space intentionally left blank.
143     }
144 
145     /**
146      * Returns a human-oriented string representing the given access flags,
147      * as defined on classes (not fields or methods).
148      *
149      * @param flags the flags
150      * @return {@code non-null;} human-oriented string
151      */
classString(int flags)152     public static String classString(int flags) {
153         return humanHelper(flags, CLASS_FLAGS, CONV_CLASS);
154     }
155 
156     /**
157      * Returns a human-oriented string representing the given access flags,
158      * as defined on inner classes.
159      *
160      * @param flags the flags
161      * @return {@code non-null;} human-oriented string
162      */
innerClassString(int flags)163     public static String innerClassString(int flags) {
164         return humanHelper(flags, INNER_CLASS_FLAGS, CONV_CLASS);
165     }
166 
167     /**
168      * Returns a human-oriented string representing the given access flags,
169      * as defined on fields (not classes or methods).
170      *
171      * @param flags the flags
172      * @return {@code non-null;} human-oriented string
173      */
fieldString(int flags)174     public static String fieldString(int flags) {
175         return humanHelper(flags, FIELD_FLAGS, CONV_FIELD);
176     }
177 
178     /**
179      * Returns a human-oriented string representing the given access flags,
180      * as defined on methods (not classes or fields).
181      *
182      * @param flags the flags
183      * @return {@code non-null;} human-oriented string
184      */
methodString(int flags)185     public static String methodString(int flags) {
186         return humanHelper(flags, METHOD_FLAGS, CONV_METHOD);
187     }
188 
189     /**
190      * Returns whether the flag {@code ACC_PUBLIC} is on in the given
191      * flags.
192      *
193      * @param flags the flags to check
194      * @return the value of the {@code ACC_PUBLIC} flag
195      */
isPublic(int flags)196     public static boolean isPublic(int flags) {
197         return (flags & ACC_PUBLIC) != 0;
198     }
199 
200     /**
201      * Returns whether the flag {@code ACC_PROTECTED} is on in the given
202      * flags.
203      *
204      * @param flags the flags to check
205      * @return the value of the {@code ACC_PROTECTED} flag
206      */
isProtected(int flags)207     public static boolean isProtected(int flags) {
208         return (flags & ACC_PROTECTED) != 0;
209     }
210 
211     /**
212      * Returns whether the flag {@code ACC_PRIVATE} is on in the given
213      * flags.
214      *
215      * @param flags the flags to check
216      * @return the value of the {@code ACC_PRIVATE} flag
217      */
isPrivate(int flags)218     public static boolean isPrivate(int flags) {
219         return (flags & ACC_PRIVATE) != 0;
220     }
221 
222     /**
223      * Returns whether the flag {@code ACC_STATIC} is on in the given
224      * flags.
225      *
226      * @param flags the flags to check
227      * @return the value of the {@code ACC_STATIC} flag
228      */
isStatic(int flags)229     public static boolean isStatic(int flags) {
230         return (flags & ACC_STATIC) != 0;
231     }
232 
233     /**
234      * Returns whether the flag {@code ACC_CONSTRUCTOR} is on in
235      * the given flags.
236      *
237      * @param flags the flags to check
238      * @return the value of the {@code ACC_CONSTRUCTOR} flag
239      */
isConstructor(int flags)240     public static boolean isConstructor(int flags) {
241         return (flags & ACC_CONSTRUCTOR) != 0;
242     }
243 
244     /**
245      * Returns whether the flag {@code ACC_INTERFACE} is on in
246      * the given flags.
247      *
248      * @param flags the flags to check
249      * @return the value of the {@code ACC_INTERFACE} flag
250      */
isInterface(int flags)251     public static boolean isInterface(int flags) {
252         return (flags & ACC_INTERFACE) != 0;
253     }
254 
255     /**
256      * Returns whether the flag {@code ACC_SYNCHRONIZED} is on in
257      * the given flags.
258      *
259      * @param flags the flags to check
260      * @return the value of the {@code ACC_SYNCHRONIZED} flag
261      */
isSynchronized(int flags)262     public static boolean isSynchronized(int flags) {
263         return (flags & ACC_SYNCHRONIZED) != 0;
264     }
265 
266     /**
267      * Returns whether the flag {@code ACC_ABSTRACT} is on in the given
268      * flags.
269      *
270      * @param flags the flags to check
271      * @return the value of the {@code ACC_ABSTRACT} flag
272      */
isAbstract(int flags)273     public static boolean isAbstract(int flags) {
274         return (flags & ACC_ABSTRACT) != 0;
275     }
276 
277     /**
278      * Returns whether the flag {@code ACC_NATIVE} is on in the given
279      * flags.
280      *
281      * @param flags the flags to check
282      * @return the value of the {@code ACC_NATIVE} flag
283      */
isNative(int flags)284     public static boolean isNative(int flags) {
285         return (flags & ACC_NATIVE) != 0;
286     }
287 
288     /**
289      * Returns whether the flag {@code ACC_ANNOTATION} is on in the given
290      * flags.
291      *
292      * @param flags the flags to check
293      * @return the value of the {@code ACC_ANNOTATION} flag
294      */
isAnnotation(int flags)295     public static boolean isAnnotation(int flags) {
296         return (flags & ACC_ANNOTATION) != 0;
297     }
298 
299     /**
300      * Returns whether the flag {@code ACC_DECLARED_SYNCHRONIZED} is
301      * on in the given flags.
302      *
303      * @param flags the flags to check
304      * @return the value of the {@code ACC_DECLARED_SYNCHRONIZED} flag
305      */
isDeclaredSynchronized(int flags)306     public static boolean isDeclaredSynchronized(int flags) {
307         return (flags & ACC_DECLARED_SYNCHRONIZED) != 0;
308     }
309 
310     /**
311      * Returns whether the flag {@code ACC_ENUM} is on in the given flags.
312      *
313      * @param flags the flags to check
314      * @return the value of the {@code ACC_ENUM} flag
315      */
isEnum(int flags)316     public static boolean isEnum(int flags) {
317         return (flags & ACC_ENUM) != 0;
318     }
319 
320     /**
321      * Helper to return a human-oriented string representing the given
322      * access flags.
323      *
324      * @param flags the defined flags
325      * @param mask mask for the "defined" bits
326      * @param what what the flags represent (one of {@code CONV_*})
327      * @return {@code non-null;} human-oriented string
328      */
humanHelper(int flags, int mask, int what)329     private static String humanHelper(int flags, int mask, int what) {
330         StringBuilder sb = new StringBuilder(80);
331         int extra = flags & ~mask;
332 
333         flags &= mask;
334 
335         if ((flags & ACC_PUBLIC) != 0) {
336             sb.append("|public");
337         }
338         if ((flags & ACC_PRIVATE) != 0) {
339             sb.append("|private");
340         }
341         if ((flags & ACC_PROTECTED) != 0) {
342             sb.append("|protected");
343         }
344         if ((flags & ACC_STATIC) != 0) {
345             sb.append("|static");
346         }
347         if ((flags & ACC_FINAL) != 0) {
348             sb.append("|final");
349         }
350         if ((flags & ACC_SYNCHRONIZED) != 0) {
351             if (what == CONV_CLASS) {
352                 sb.append("|super");
353             } else {
354                 sb.append("|synchronized");
355             }
356         }
357         if ((flags & ACC_VOLATILE) != 0) {
358             if (what == CONV_METHOD) {
359                 sb.append("|bridge");
360             } else {
361                 sb.append("|volatile");
362             }
363         }
364         if ((flags & ACC_TRANSIENT) != 0) {
365             if (what == CONV_METHOD) {
366                 sb.append("|varargs");
367             } else {
368                 sb.append("|transient");
369             }
370         }
371         if ((flags & ACC_NATIVE) != 0) {
372             sb.append("|native");
373         }
374         if ((flags & ACC_INTERFACE) != 0) {
375             sb.append("|interface");
376         }
377         if ((flags & ACC_ABSTRACT) != 0) {
378             sb.append("|abstract");
379         }
380         if ((flags & ACC_STRICT) != 0) {
381             sb.append("|strictfp");
382         }
383         if ((flags & ACC_SYNTHETIC) != 0) {
384             sb.append("|synthetic");
385         }
386         if ((flags & ACC_ANNOTATION) != 0) {
387             sb.append("|annotation");
388         }
389         if ((flags & ACC_ENUM) != 0) {
390             sb.append("|enum");
391         }
392         if ((flags & ACC_CONSTRUCTOR) != 0) {
393             sb.append("|constructor");
394         }
395         if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) {
396             sb.append("|declared_synchronized");
397         }
398 
399         if ((extra != 0) || (sb.length() == 0)) {
400             sb.append('|');
401             sb.append(Hex.u2(extra));
402         }
403 
404         return sb.substring(1);
405     }
406 }
407