preface
Google sinceAndroid L (6.0)Since then, security and performance updates have been continuously implemented, and android P (9.0) is no exception, to a greater extent, the implementation of previous versions of some of the warnings, whether youTarget ApiWhether 28 or not will be affected.
1. Affect all applications (regardless of TargetApi 28+ or not)
1.1 Non-SDK interface Restrictions
This restriction is not limited to the SDK layer (direct reference or reflection), but also extends to the JNI layer. In fact, as early as Android N, it limits the set of symbols used by C/C++, and if the NDK has unnotified changes, it will no doubt crash the application.
1.1.1 SDK interface and non-SDK Interface
SDK interface refers to the interface recorded in the Android framework software package. In order to allow developers to have a transition time and serve as a warning, Google sets different levels of list types for non-SDK interface:
- Whitelist: SDK
- Light grey list: Non-SDK functions/fields that are still accessible.
- Deep Grey list: * ForTarget ApiApplications with an SDK lower than API 28 allow the use of the deep grey list interface.
- For applications whose Target Api SDK is Api 28 or higher: the behavior is the same as the blacklist.
- Blacklist: Regardless of the Target Api SDK. The platform will behave as if the interface doesn’t exist. For example, whenever the application to try to keep to use interface, platform can trigger NoSuchMethodError/NoSuchFieldException.
We usually need to pay attention to the development of the dark gray list and blacklist, do not care too much about the light gray list, because the previous mentioned can directly reference non-SDK interface, here basically refers to the direct reference to the light gray list interface.
For example: In the official light grey list, it lists many interfaces that we usually use, such as Intent to obtain resources:
Landroid/content/Intent; ->FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT:I Landroid/content/Intent; ->getExtra(Ljava/lang/String;) Ljava/lang/Object; Landroid/content/Intent; ->getExtra(Ljava/lang/String; Ljava/lang/Object;) Ljava/lang/Object;Copy the code
However, this is the most common Api we use, so don’t worry too much about it. The light grey list is a very low level warning, and the client mediation urgently needs to solve the blacklist list: the blacklist is basically the Api we don’t use in the normal application level development, for example:
Lsun/util/calendar/BaseCalendar; ->getMonthLength(II)ICopy the code
Corresponding code in SDK:
Public int getMonthLength(CalendarDate var1) {BaseCalendar.Date var2 = (BaseCalendar.Date)var1; BaseCalendar. int var3 = var2.getMonth();if (var3 >= 1 && var3 <= 12) {
return this.getMonthLength(var2.getNormalizedYear(), var3);
} else {
throw new IllegalArgumentException("Illegal month value: "+ var3); Private int getMonthLength(int var1, int var2) {int var3 = DAYS_IN_MONTH[var2];if (var2 == 2 && this.isLeapYear(var1)) {
++var3;
}
return var3;
}
Copy the code
So, blacklisting may sound scary, but it doesn’t have a big impact on the inventory of apps, because it’s mostly private, rare methods.
The deep Grey list has the largest impact, because it is strongly not recommended. However, in order to give developers buffer time, only Target Api 28+ will have exceptions. Representative apis include DexFile class:
Ldalvik/system/DexFile; -><init>(Ljava/io/File; Ljava/lang/ClassLoader; [Ldalvik/system/DexPathList$Element;) V Ldalvik/system/DexFile; -><init>(Ljava/lang/String; Ljava/lang/ClassLoader; [Ldalvik/system/DexPathList$Element;) V Ldalvik/system/DexFile; -><init>(Ljava/lang/String; Ljava/lang/String; ILjava/lang/ClassLoader; [Ldalvik/system/DexPathList$Element;) V Ldalvik/system/DexFile; -><init>(Ljava/nio/ByteBuffer;) V Ldalvik/system/DexFile; ->DEX2OAT_FOR_BOOT_IMAGE:I Ldalvik/system/DexFile; ->DEX2OAT_FOR_FILTER:I Ldalvik/system/DexFile; ->DEX2OAT_FOR_RELOCATION:I Ldalvik/system/DexFile; ->DEX2OAT_FROM_SCRATCH:I Ldalvik/system/DexFile; ->NO_DEXOPT_NEEDED:I Ldalvik/system/DexFile; ->closeDexFile(Ljava/lang/Object;) Z Ldalvik/system/DexFile; ->createCookieWithArray([BII)Ljava/lang/Object; Ldalvik/system/DexFile; ->createCookieWithDirectBuffer(Ljava/nio/ByteBuffer;II)Ljava/lang/Object; Ldalvik/system/DexFile; ->defineClass(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/Object;Ldalvik/system/DexFile;Ljava/util/List; )Ljava/lang/Class; Ldalvik/system/DexFile;->defineClassNative(Ljava/lang/String;Ljava/lang/ClassLoader; Ljava/lang/Object;Ldalvik/system/DexFile;)Ljava/lang/Class;Copy the code
And AssetManager related:
Landroid/content/res/AssetManager; ->TAG:Ljava/lang/String; Landroid/content/res/AssetManager; ->addAssetPathInternal(Ljava/lang/String; Z)I Landroid/content/res/AssetManager; ->addAssetPathNative(Ljava/lang/String; Z)I Landroid/content/res/AssetManager; ->addAssetPaths([Ljava/lang/String;)[I Landroid/content/res/AssetManager;->addOverlayPathNative(Ljava/lang/String; )I Landroid/content/res/AssetManager;->applyStyle(JIIJ[IIJJ)VCopy the code
The inclusion of these two categories on the Dark Grey list basically knocks out all the hotfix frameworks on the market, which means that if your App is targeted at version 28+ and running on Android P, these hotfix frameworks may not work properly.
At the GMTC(Global Front-end Technology Conference) in June this year, the architect of JINGdong made a speech “When plug-ins meet Android P”, which was mentioned in the de-black technology. Currently, the non-SDK limitations of Android P have affected the plug-in framework of Jingdong.
1.1.2 Obtaining relevant non-SDK list
There are two ways:
-
If you have AOSP projects locally, run them in the root directory
make hiddenapi-aosp-blacklist Copy the code
Files can then be found in the following locations:
out/target/common/obj/PACKAGING/hiddenapi-aosp-blacklist.txt
Copy the code
- A better way is to directly use the official compiled results, which can be viewed here.
1.1.3 Check the non-SDK in the project
You can search the list of classes you want, but veridex, an automated scanning tool, is available.
Download to your local directory and find the script directory for your system:
Scan with command:
Appcompat. Sh -- -- dex - file = apk pathCopy the code
You can see that our project only has a dark grey list of warnings.
1.1.4 Invoking the non-SDK interface
The following is the result of using the non-SDK interface in various ways:
access | The results of |
---|---|
The Dalvik directive references fields | Trigger NoSuchFieldError |
The Dalvik directive references functions | Trigger a NoSuchMethodError |
Reflection via class.getDeclaredField () or class.getField () | Trigger NoSuchFieldException |
Reflection via class.getDeclaredMethod () or class.getMethod () | Trigger NoSuchMethodException |
Reflection via class.getDeclaredfields () or class.getfields () | No non-SDK members appear in the results |
Either class.getDeclaredMethods () or class.getMethods (). | Reflection results show no non-SDK members. |
Call JNI with env->GetFieldID() | Returns NULL, raising NoSuchFieldError |
Call JNI with env->GetMethodID() | Returns NULL, raising NoSuchMethodError |
1.2 Security Related
1.2.1 Encryption Changes
The Crypto Java Encryption Architecture (JCA) provider has now been removed
Similarly, NoSuchProviderException will occur:
SecureRandom.getInstance("SHA1PRNG", "Crypto")
Copy the code
On devices prior to Android P, using the Crypto provider will work if target < 24 (N) and will fail if target 24+
On adnrodi P devices, Crypto is completely removed, so NoSuchProviderException is thrown regardless of target’s value
Bouncy Castle versions of many algorithms are deprecated
The encryption feature BC provider has been removed, according to the official blog post:
Starting in Android P, we plan to deprecate some functionality from the BC provider that's duplicated by the AndroidOpenSSL (also known as Conscrypt) provider
If targetApi >= P (28+) will raise NoSuchAlgorithmException, the following will be affected:
Cipher.getInstance("AES/CBC/PKCS7PADDING"."BC") or
Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC"))
Copy the code
Therefore, it is recommended to use the default implementation instead of specifying the provider.
1.3 Privacy
Access to background applications is restricted
- Your application cannot access the microphone or camera.
- Sensors that use continuous reporting mode, such as accelerometers and gyroscopes, do not receive events.
- Sensors that use change or one-time report modes do not receive events.
If your application needs to detect sensor events on a device running Android 9, use the foreground service.
Permission Group Change
Android P introduces the CALL_LOG permission group and moves the READ_CALL_LOG, WRITE_CALL_LOG, and PROCESS_OUTGOING_CALLS permissions to this group. In previous versions of Android, these permissions were in the PHONE permission group
Wifi scan permission change:
Android 8.0 and Android 8.1:
A successful call WifiManager. GetScanResults () need a permission to any of the following:
- ACCESS_FINE_LOCATION
- ACCESS_COARSE_LOCATION
- CHANGE_WIFI_STATE
If the calling application does not have any of these permissions, the call will fail and display a SecurityException.
Android 9 and later:
A successful call to wifimanager.startscan () requires all of the following:
- Your application has ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions.
- Your application has CHANGE_WIFI_STATE permission.
A successful call WifiManager. GetScanResults () need to meet all of the following conditions:
- Your application has ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions.
- Your application has ACCESS_WIFI_STATE permission.
- The location service is enabled on the device (choose Settings > Location).
If the calling application does not meet all of these requirements, the call will fail and display a SecurityException.
A similar limitation applies to the getConnectionInfo() function, which returns a WifiInfo object describing the current Wi-Fi connection. Only functions of this object can be used to retrieve the SSID and BSSID values if the calling application has the following permissions:
- ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION
- ACCESS_WIFI_STATE Retrieving an SSID or BSSID also requires enabling Location services on the device (under Settings > Location).
Use the host name of the certificate for authentication
In RFC 2818, fallback to CN has been deprecated. As a result, Android no longer falls back to using CN. To validate the host name, the server must present a certificate that matches the SAN. Certificates that do not contain SAN that match the host name are no longer trusted
1.4 Other Restrictions
1.4.1 Disabling the Apache HTTP Client Affects Applications that use non-standard ClassLoaders
In fact, since the release of Android 6, Apache HTTP client support has been removed in favor of the HttpURLConnection class because it can reduce network usage through transparent compression and response caching. And to minimize power consumption, we’ve since become accustomed to using the Apache HTTP API by adding:
android {
useLibrary 'org.apache.http.legacy'
}
Copy the code
Androd P, the content library has been removed from bootCLASspath by default and is not available for applications.
By default, the Apache HTTP API is not available, even though the library is declared in build.geadle. Apps running on Android P devices:
-
Target 28, the default is NoClassDefFoundError, because this library is disabled, to continue using the Apache HTTP client, Apps targeting Android 9 and later can add the following to their Androidmanifest.xml:
<uses-library android:name="org.apache.http.legacy" android:required="false"/> Copy the code
-
Target < 28 can be consistent with Android 6.0.
Bootclasspath is a Linux system variable. It is a class that is preloaded when the system boots to improve system performance. This is the bootclasspath variable on Mi MIX (7.0) :
/system/bin/sh: /system/framework/core-oj.jar:/system/framework/core-libart.jar:/system/framework/conscrypt.jar:/system/framework/okhttp .jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/fra mework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/ims-common.jar:/sy stem/framework/apache-xml.jar:/system/framework/org.apache.http.legacy.boot.jar:/system/framework/vivo-framework.jar:/sy stem/framework/tcmiface.jar:/system/framework/telephony-ext.jar:/system/framework/vivo-media.jar:/system/framework/qcril hook.jar:/system/framework/WfdCommon.jar:/system/framework/com.qti.location.sdk.jar:/system/framework/oem-services.jar:/ system/framework/qcom.fmradio.jar: not foundCopy the code
Variables are: / system/framework/org. Apache HTTP. Legacy. The boot. The jar, will help us to load, so the system default allows you to use.
This is the bootCLASspath variable on Android P:
/system/framework/core-oj.jar:/system/framework/core-libart.jar:/system/framework/conscrypt.jar:/system/framework/okhttp .jar:/system/framework/bouncycastle.jar:/system/framework/apache-xml.jar:/system/framework/ext.jar:/system/framework/fra mework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/ims-common.jar:/sy Stem/framework/android. Hidl. Base - V1.0 - Java. Jar: / system/framework/android hidl. The manager - V1.0 - Java. Jar: / system/framework/fr amework-oahl-backward-compatibility.jar:/system/framework/android.test.base.jar generic_x86_64:/ $Copy the code
There is no apache HTTP library, but they have a common feature, is the system built-in Apache package, in /system/framework/ directory:
, but I have a puzzle, that is, the DexPathList value is different between android P device and lower version (>M) :
android P
:
PathClassLoader// This is httpClient's ClassLoader DexPathList[[zip file"/system/framework/org.apache.http.legacy.boot.jar",
zip file "/data/app/com.example.leixiang.demoapp-hOOUC7E0LuRvgmYC38vd5w==/base.apk"
],nativeLibraryDirectories=[/data/app/com.example.leixiang.demoapp-hOOUC7E0LuRvgmYC38vd5w==/lib/x86_64, /system/lib64]]
Copy the code
android N
:
Dalvik. System. PathClassLoader / / this is httpClient this [DexPathList [[zip file"/data/app/com.example.leixiang.demoapp-1/base.apk"
],nativeLibraryDirectories=[/data/app/com.example.leixiang.demoapp-1/lib/arm64, /system/lib64, /vendor/lib64]]]
Copy the code
The difference between them is that there are more Apache packages in DexPathList on Android N devices, but their loaders are still PathClassLoader. I think it may be that apache HTTP related classes are no longer pre-loaded on P system. So add him to the DexPathList? And P before the system loads the classes in bootclasspath also use the PathClassLoader? This needs to be studied.
1.5 Power Management Optimization
Android 9 introduces a new battery management feature called app standby groups. The application standby group helps the system schedule the priority of application request resources based on the recent application usage time and frequency. Each application is grouped into one of five priority groups based on usage patterns. The system limits the device resources that each application can access based on the group to which the application belongs:
active
If the user is currently using the app, the app will be placed in the “active” group, for example:
- The application has started an Activity
- The application is running foreground services
- The application’s synchronization adapter is associated with a Content Provider used by a foreground application
- If the app is in the “active” group, no restrictions are placed on the app’s jobs, alerts, or FCM messages.
FCM refers to Google push, domestic do not think, as for the long connection and heartbeat package will be limited to the specific operation of domestic manufacturers.
The working set
If an application runs frequently but is not currently active, it is placed in the “working set” group. For example, a social media app that users start most of the time might be in the “working set” group. If applications are used indirectly, they are also promoted to the “working set” group.
The commonly used
If the app is used regularly, but not necessarily every day, it will fall into the “frequently used” group. For example, an exercise tracking app a user runs at a gym might be in the “used” group.
Don’t use
If the app is not used often, it falls into the “rarely used” group. For example, a hotel app that a user runs only during a hotel stay might be in the “rarely used” group.
Never use
Apps that are installed but never run fall into the “never used” group. The system imposes very strong restrictions on these applications.
We can use UsageStatsManager. GetAppStandbyBucket () to see which one we’re in a group, the API is 21 added.
However, users can configure the low power consumption whitelist to get rid of the restriction of grouping.
The following are the activity restrictions for each group:
Setting | Jobs * | Alarms | Network | Firebase Cloud Messaging § |
---|---|---|---|---|
User Restricts Background Activity | ||||
Restrictions enabled: | Never | Never | Never | No restriction |
Doze | ||||
Doze active: | Deferred to window | Regular alarms: Deferred to window While-idle alarms: Deferred up to 9 minutes | Deferred to window | High priority: No restriction Normal priority: Deferred to window |
App Standby Buckets (by bucket) | ||||
Active: | No restriction | No restriction | No restriction | No restriction |
Working set: | Deferred up to 2 hours | Deferred up to 6 minute | No restriction | No restriction |
Frequent: | Deferred up to 8 hours | Deferred up to 30 minutes | No restriction | High priority: 10/day |
Rare: | Deferred up to 24 hours | Deferred up to 2 hours | Deferred up to 24 hours | High priority: 5/day |
We can test the behavior by placing our debug devices in specific groups through adb commands.
$ adb shell am set-standby-bucket packagename active|working_set|frequent|rare
Copy the code
2. For Taget 28+ applications
2.1 Reception Service
The foreground service allows you to keep your application active, as mentioned above.
Target 28+ Applications that use foreground services must request FOREGROUND_SERVICE permission. This is a common permission, so the system automatically grants this permission to applications that request it.
2.2 Privacy Change
Build sequence number deprecation
In Android 9, build. SERIAL is always set to “UNKNOWN” to protect user privacy.
If your application needs access to the hardware serial number of the device, you should request READ_PHONE_STATE permission instead, and then call getSerial().
Android P SDK API:
/**
* A hardware serial number, if available. Alphanumeric only, case-insensitive.
* For apps targeting SDK higher than {@link Build.VERSION_CODES#O_MR1} this
* field is set to {@link Build#UNKNOWN}.
*
* @deprecated Use {@link #getSerial()} instead.
**/
@Deprecated
// IMPORTANT: This field should be initialized via a function call to
// prevent its value being inlined in the app during compilation because
// we will later set it to the value based on the app's target SDK. public static final String SERIAL = getString("no.such.thing");Copy the code
DNS privacy
Apps targeting Android 9 should use the proprietary DNS API. Specifically, when the system resolver is performing DNS-over-TLS, the application should ensure that any built-in DNS client uses the encrypted DNS to look up the same hostname as the system, or deactivate it in favor of the system resolver. Settings -> private DNS:
2.3 security
Enable network Transport Layer Security protocol (TLS) by default
If your application Target 28 +, default isCleartextTrafficPermitted () function returns false. If your application to enable clear need for a specific domain name, you must be in the application of the network security configuration for these domain names will be cleartextTrafficPermitted explicitly set to true.
Denial produces the following log error output:
W/Glide: Load failed for http://xxx-99billxx.ufile.ucloud.cn/online/image/A1707101417703-349-0xxhdpi
java.io.IOException: Cleartext HTTP traffic to xxx-99billxx.ufile.ucloud.cn not permitted
Copy the code
Note: This API was only introduced in API 23. Therefore, if the application cannot change the server to HTTPS in time due to some historical reasons, the configuration file should allow plaintext transfer for a specific domain name, that is, HTTP service.
Define the configuration file res/ XML /network_security_config.xml:
<? xml version="1.0" encoding="utf-8"? > <network-security-config> <domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">secure.example.com</domain>
</domain-config>
</network-security-config>
Copy the code
It is then declared in manifest.xml
<? xml version="1.0" encoding="utf-8"? > <manifest ... > <application android:networkSecurityConfig="@xml/network_security_config". >... </application> </manifest>Copy the code
Network – based data directory by process
To improve application stability and data integrity in Android 9, applications can no longer share the same WebView data directory with multiple processes. Such data directories typically store cookies, HTTP caches, and other persistent and temporary storage related to web browsing
If your application must be used in the process of multiple WebView instance, you must first use the WebView. SetDataDirectorySuffix () function specifies the unique data directory for each process suffixes, and then in the process of the given instance of the WebView. This function puts each process’s network data into its own directory within the application data directory.
Note: Even if you use setDataDirectorySuffix(), cookies and other network data are not shared across application process boundaries. If multiple processes in your application need to access the same network data, you need to replicate data between those processes yourself. For example, you can call getCookie() and setCookie() to manually transfer the number of cookies between different processes
3. The new features
Kotlin friendly
Improved Dexer and coordinated Jetbranins to improve Kotlin Compier to run faster on Android P, and talked to the Jetbrains team to provide a new Kotlin plugin.
ImageDecoder
The alternative BitmapFactory can load bitmaps and Drawable from streams, files, Byte buffers, urls, supports precise sizing, and supports loading giFs, WebPs, and rounded corners.
wifi RTT
In the indoor, IEEE 802.11MC Wi-Fi Protocol measures the distance from nearby wifi connection points (2 ~ 3), using RTT, can be accurate to 1 ~ 2 meters on hardware supported Android P devices. Applications can use the new RTT API to measure the distance to a nearby RTT-enabled Wi-Fi access point (AP). Devices do not need to be connected to an AP to use RTT
Use uses-feature to mark:
<uses-feature android:name="android.hardware.wifi.rtt" />
Copy the code
PrecomputedText
Displaying text can be complex, including multiple fonts, line spacing, letter spacing, text orientation, line breaks, hyphens, and more. TextView must do a lot of work to measure and lay out a given text: read font files, find glyphs, determine shapes, measure bounding boxes, and cache words in an internal word cache. What’s more, all of this work happens on the UI thread, which can cause your application to lose frames measuring text that can take up to 90% of the time it takes to set up text
Android P is officially introduced, for android P previously used through Jetpack’s PrecomputedTextCompat.
// UI thread
val params: PrecomputedText.Params = textView.getTextMetricsParams()
val ref = WeakReference(textView)
executor.execute {
// background thread
val text = PrecomputedText.create("Hello", params) val textView = ref.get() textView? .post { // UI thread val textViewRef = ref.get() textViewRef? .text = text } }Copy the code
Magnifier
Android P introduces a text magnifying glass to improve the user’s experience of selecting text. The magnifying glass helps the user precisely position the cursor or text selection handle by viewing enlarged text through a pane that can be dragged over the text, simply overwriting the view’s **OnTouchEvent()** method:
Fun onTouchEvent (Event: MotionEvent) : Boolean {when (event.actionmasked) {motionEvent.action_down - > magnifier. Show (event.x, ACTION_MOVE - > magnifier. Show (event.x, event.y) motionEvent. ACTION_UP - > magnifier.Copy the code
Unfortunately, there are no compatible classes for lower version devices (<P).
DEX file ART conversion ahead of time
On devices running Android 9 or later, the Android Runtime (ART) precompiler further optimizes the compressed Dalvik Executable format (DEX) file by converting the DEX file in the application package into a more compact representation. This change allows your application to start faster and consume less disk space and memory.
This improvement is particularly beneficial for low-end devices with slower disk I/O speeds.
The resources
-
YouTube video brief introduction
-
Encryption function changes
-
Crypto removed
-
Tls is enabled by default on Android P
-
Network Security Configuration
-
DNS over TLS
-
Biometric optimization
-
The text optimization
-
Battery management