Save the date! Android Dev Summit is coming to Mountain View, CA on November 7-8, 2018.

Restrictions on non-SDK interfaces

Android 9 (API level 28) 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 9 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 Android 9. The system prints logs and potentially displays toasts if your app accesses certain "greylisted" non-SDK interfaces. If your app calls a "blacklisted" non-SDK interface, the system 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 9, but to which we don't 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.

Some APIs are on a "blacklist", stricter than the greylisted methods. Blacklisted methods cause apps to throw exceptions as shown in the table in Results of keeping non-SDK interfaces.

Android 9 supports StrictMode for non-SDK interfaces, called 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

FAQ

General questions

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 Android 9?

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.
  • dark-greylist:
    • For apps whose target SDK is below API level 28: each use of a dark greylist interface is permitted.
    • For apps whose target SDK is API level 28 or higher: 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 NoSuchMethodError/NoSuchFieldException whenever 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?

A logcat warning is printed of the form Accessing hidden field|method .... In addition, toast messages are shown for debuggable apps, and logcat messages are printed for any 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 does the dark grey list in the Android 9 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:

  make hiddenapi-aosp-blacklist

And then they will find the file in:

  out/target/common/obj/PACKAGING/hiddenapi-aosp-blacklist.txt

 

What is the approximate size of these lists?

The lists are approximately:

  • whitelist (also known as 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 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.

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.