| David Brazdil | 2b9c35b | 2018-01-12 15:44:43 +0000 | [diff] [blame] | 1 | HiddenApi |
| 2 | ========= |
| 3 | |
| 4 | This tool iterates over all class members inside given DEX files and modifies |
| 5 | their access flags if their signatures appear on one of two lists - greylist and |
| 6 | blacklist - provided as text file inputs. These access flags denote to the |
| 7 | runtime that the marked methods/fields should be treated as internal APIs with |
| 8 | access restricted only to platform code. Methods/fields not mentioned on the two |
| 9 | lists are assumed to be on a whitelist and left accessible by all code. |
| 10 | |
| 11 | API signatures |
| 12 | ============== |
| 13 | |
| 14 | The methods/fields to be marked are specified in two text files (greylist, |
| 15 | blacklist) provided an input. Only one signature per line is allowed. |
| 16 | |
| 17 | Types are expected in their DEX format - class descriptors are to be provided in |
| 18 | "slash" form, e.g. "Ljava/lang/Object;", primitive types in their shorty form, |
| 19 | e.g. "I" for "int", and a "[" prefix denotes an array type. Lists of types do |
| 20 | not use any separators, e.g. "ILxyz;F" for "int, xyz, float". |
| 21 | |
| 22 | Methods are encoded as: |
| 23 | `class_descriptor->method_name(parameter_types)return_type` |
| 24 | |
| 25 | Fields are encoded as: |
| 26 | `class_descriptor->field_name:field_type` |
| 27 | |
| 28 | Bit encoding |
| 29 | ============ |
| 30 | |
| 31 | Two bits of information are encoded in the DEX access flags. These are encoded |
| 32 | as unsigned LEB128 values in DEX and so as to not increase the size of the DEX, |
| 33 | different modifiers were chosen for different kinds of methods/fields. |
| 34 | |
| 35 | First bit is encoded as the inversion of visibility access flags (bits 2:0). |
| 36 | At most one of these flags can be set at any given time. Inverting these bits |
| 37 | therefore produces a value where at least two bits are set and there is never |
| 38 | any loss of information. |
| 39 | |
| 40 | Second bit is encoded differently for each given type of class member as there |
| 41 | is no single unused bit such that setting it would not increase the size of the |
| 42 | LEB128 encoding. The following bits are used: |
| 43 | |
| 44 | * bit 5 for fields as it carries no other meaning |
| 45 | * bit 5 for non-native methods, as `synchronized` can only be set on native |
| 46 | methods (the Java `synchronized` modifier is bit 17) |
| 47 | * bit 9 for native methods, as it carries no meaning and bit 8 (`native`) will |
| 48 | make the LEB128 encoding at least two bytes long |
| 49 | |
| 50 | Two following bit encoding is used to denote the membership of a method/field: |
| 51 | |
| 52 | * whitelist: `false`, `false` |
| 53 | * greylist: `true`, `false` |
| 54 | * blacklist: `true`, `true` |