Android P introduces new restrictions on the use of non-SDK interfaces, whether directly, via reflection, or via JNI. These restrictions are applied whenever an app references a non-SDK interface or attempts to obtain its handle using reflection or JNI. For more information about this decision, see Improving Stability by Reducing Usage of non-SDK Interfaces.
In general, apps should only use the officially documented parts of the classes in the SDK. In particular, this means that you should not plan to access methods or fields that are not listed in the SDK when you interact with a class via semantics such as reflection.
Using such methods or fields has a high risk of breaking your app.
Differentiating between SDK and non-SDK interfaces
Generally speaking, SDK interfaces are those ones found documented in the Android framework Package Index. Handling of non-SDK interfaces is an implementation detail that the API abstracts away; it is subject to change without notice.
Android P introduces new restrictions on the use of non-SDK interfaces, whether directly, via reflection, or via JNI. These restrictions are applied whenever an app references a non-SDK interface or attempts to obtain its handle using reflection or JNI.
Testing for non-SDK interfaces
You can test your app by downloading the newest version of the Developer Preview of Android P. The Developer Preview prints logs and potentially displays toasts if your app accesses certain, "greylisted" non-SDK interface. If your app calls a "blacklisted" non-SDK interface, the Developer Preview throws an error.
Pay attention to the toasts, which call attention to interfaces that are proposed for restriction. Also, make sure to inspect your app's log messages, which contain more detailed information about the non-SDK interface that your app accessed, including the declaring class, name, and type in the format used by the Android runtime. Log messages also indicate the means of access: direct, via reflection, or via JNI. Last, log messages show whether the called non-SDK interface belongs to the greylist or the blacklist.
You can use
adb logcat to access these log messages, which
appear under the PID of the running app. For example, an entry in the log
might read as follows:
Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)
Greylisted non-SDK interfaces encompass methods and fields which continue to function in Android P, but to which we do not guarantee access in future versions of the platform. If there is a reason that you cannot implement an alternative strategy to a greylisted API, you may file a bug to request reconsideration of the restriction.
Developer Preview 2 moves to a blacklist methods that had been part of a second, "dark" greylist in Developer Preview 1. Blacklisted methods cause apps to throw exceptions as shown in the table in Results of keeping non-SDK interfaces.
Developer Preview 2 also adds
StrictMode support for non-SDK interfaces,
detectNonSdkApiUsage, so that when your app calls a greylisted app,
the stack trace shows the context.
Results of keeping non-SDK interfaces
The following table provides details about means of access and their respective results.
|Means of access||Result|
|Dalvik instruction referencing a field||NoSuchFieldError thrown|
|Dalvik instruction referencing a method||NoSuchMethodError thrown|
|Reflection via Class.getDeclaredField() or Class.getField()||NoSuchFieldException thrown|
|Reflection via Class.getDeclaredMethod(), Class.getMethod()||NoSuchMethodException thrown|
|Reflection via Class.getDeclaredFields(), Class.getFields()||Non-SDK members not in results|
|Reflection via Class.getDeclaredMethods(), Class.getMethods()||Non-SDK members not in results|
|JNI via env->GetFieldID()||NULL returned, NoSuchFieldError thrown|
|JNI via env->GetMethodID()||NULL returned, NoSuchMethodError thrown|
What are non-SDK interfaces?
They are Java fields and methods that are not part of the official Android SDK. They are implementation details that are subject to change without notice.
What is happening in P?
We are setting up restrictions on the use of non-SDK interfaces. The form of these restrictions vary (see How can I detect non-SDK interface uses when my app is running?), but can affect the behavior of your application if you are using non-SDK interfaces.
If I currently use a non-SDK interface, where should I request it?
Please file a Feature Request, and provide detailed info about your use case.
What are the different lists for restricting non-SDK interfaces, and what are their corresponding meaning in terms of restrictive behavior?
Below are the types of lists:
- whitelist: the SDK
- light-greylist: non SDK methods / fields that are still accessible.
- For apps whose target SDK is below P: each use of a dark greylist interface is permitted.
- For apps whose target SDK is P or above: same behavior as blacklist
- blacklist: restricted regardless of target SDK. The platform will behave as if the interface is absent. For example, it will throw
NoSuchFieldExceptionwhenever the app is trying to use it, and will not include it when the app wants to know the list of fields/methods of a particular class.
My app uses many third-party libraries, which makes it difficult for me to find any private APIs that are being used. Is there a compile-time tool to help me track violations?
You can try the static analysis tool veridex available in AOSP.
How can I detect non-SDK interface uses when my app is running?
The answer depends on which Developer Preview / Beta build of P you are trying your app. In all cases, a logcat warning is printed of the form
Accessing hidden field|method .... Also:
- In DP1 and Beta2: a toast message containing “Detected problems with API compatibility” is shown during activity launch for uses of non-SDK interfaces in the dark greylist.
- Since Beta1: On
detectNonSdkApiUsage()to receive a callback when a hidden API is called, for example to add a custom log entry.
- In the final release of P, toast messages will only be shown for debuggable apps, and logcat messages will only be printed for non-SDK interfaces that are denied.
How can Google be sure they will capture the needs of all apps through the issuetracker?
We initially seeded the list through static analysis of apps which we have supplemented with:
- manual testing of top Play and non Play apps
- internal reports
- automatic data collection from internal users
- developer preview reports
- additional static analysis designed to conservatively include more false positives
How can I enable access to non-SDK APIs?
Enabling access to non-SDK APIs is possible on development devices using adb.
If you want to see API access information in adb logcat output, you can change the API enforcement policy:
adb shell settings put global hidden_api_policy_pre_p_apps 1 adb shell settings put global hidden_api_policy_p_apps 1
To reset this to the default setting:
adb shell settings delete global hidden_api_policy_pre_p_apps adb shell settings delete global hidden_api_policy_p_apps
These commands do not require a rooted device.
The meaning of the integer given is:
- 0: Disable non-SDK API usage detection. This will also disable logging, and also break the strict mode API, detectNonSdkApiUsage(). Not recommended.
- 1: "Just warn" - permit access to all non-SDK APIs, but keep warnings in the log. The strict mode API will keep working.
- 2: Disallow usage of dark grey and black listed APIs.
- 3: Disallow usage of blacklisted APIs, but allow usage of dark grey listed APIs.
About the API lists
What is the status of the lists in preview and beta builds?
During P development, we have had different iterations of these lists:
- DP1: Only light grey and dark grey lists. All the non-SDK interfaces we intend to restrict were in dark grey.
- Beta1: Only light grey and black lists. The light grey list got extended from DP1, and the rest of the non-SDK interfaces moved from dark grey to black.
- Beta2: Three lists implemented. We have moved many blacklist interfaces to dark grey list.
You should expect the restrictions in Beta2 to be close to the final build.
What does the dark grey list in the P release build contain?
The dark grey list contains methods / fields we haven’t seen being used during our development period, but that we may have missed. The methods / fields that are selected to be in the dark grey list are the ones closely related to the public interfaces in the SDK and the light grey list.
Where are the greylists / blacklist located?
They are built as part of the platform. You can find prebuilt entries here:
- platform/prebuilts/runtime/appcompat/hiddenapi-light-greylist.txt: AOSP list of light grey APIs
- platform/prebuilts/runtime/appcompat/hiddenapi-dark-greylist.txt: AOSP list of dark grey APIs
Additionally, this list contains the SDK 28 list of light grey APIs.
The blacklist and dark grey list are build time derived. We’ve added a build rule that generates the lists on AOSP. It's not the same as the blacklist in P, but the overlap is reasonably good. A developer can download AOSP and then generate the blacklist with the following command:
And then they will find the file in:
What is the approximate size of these lists?
As of beta2 the lists are approximately:
- whitelist (aka SDK) ~= 74,000 methods and fields
- light-greylist ~= 11,000 methods and fields
- dark-greylist ~= 121,000 methods and fields
- blacklist ~= 9,000 methods and fields
Where can I find the blacklist / greylists in the DP system image?
They are encoded in the field and method access flag bits in platform dex files. There is no separate file in the system image that contains these lists.
Are the blacklist / greylists the same on different OEM devices with the same Android versions?
Yes OEMs can add their own apis to the blacklist, but cannot remove things from the original/AOSP black or grey lists. The CDD prevents such changes and CTS tests ensure that the Android Runtime is enforcing the list.
Regarding non-SDK interfaces restriction, do DP builds behave the same way as the final build?
The toasts should only show up in the DP versions, not the full / final launch. In addition:
- DP1 has no blacklist, just light and dark greylist warnings.
- Beta1 moved dark greylist APIs to blacklist.
- Beta2 moved the majority of blacklist APIs to dark greylist. The lists should be close to the finally shipping lists, but still subject to change based on ongoing feedback.
Related App compatibility questions
Is there any restriction on non-NDK interfaces in native code?
SDK covers the Java language. For the NDK for native C/C++ code, we did this in Android Nougat. See: Improving Stability with Private C/C++ Symbol Restrictions in Android N
Is there any plan to restrict dex2oat or dex file manipulation?
We don’t have active plans to restrict access to the dex2oat binary, but we do not intend for the dex file format to be stable or a public interface beyond the portions that are publicly specified in the Dalvik Executable format. We reserve the right to modify or eliminate dex2oat and the unspecified portions of the dex format at any time. Please also note that derived files produced by dex2oat such as odex (also known as oat), vdex, cdex are all unspecified formats.
What if a crucial 3p SDK (in particular, an obfuscator) cannot prevent using non-SDK interfaces, but does commit to maintain compatibility with future Android versions? Can Android waive its warnings?
We do not have plans to waive compatibility requirements on a per-SDK basis. If an SDK partner feels that they are unable to maintain compatibility with the current whitelist + greylist API set, they should file a bug requesting the non-SDK methods they will need.
Does the non-SDK interfaces restrictions apply to all apps including system and first-party apps, not just third-party apps?
Yes, however, we exempt apps signed with the platform key, and we also have a package whitelist for some system image apps. Note that these exemptions only apply to apps that are in the system image (or updated system image apps).
The list is intended only for apps that build against the private platform APIs, rather than the SDK APIs (i.e.
LOCAL_PRIVATE_PLATFORM_APIS := true).
Some developers have posted the private API restrictions mechanism and bypassing techniques. What do you comment on it? Will you make the restrictions even harder?
We're aware of the potential workarounds. The good thing is most apps are sticking to public APIs. While we try to make it harder to invoke non-SDK interfaces to ensure compatibility, we need to balance this with keeping the runtime easy to debug. We'll continue to evaluate underlying implementation and work with developers.