From 7c9273bb0dfc209aef1d1c16bc18f0c06377468c Mon Sep 17 00:00:00 2001 From: Kirill Rozov Date: Sun, 17 Mar 2019 20:29:45 +0300 Subject: [PATCH] Added support for Android Q Beta 1 --- CHANGELOG.md | 4 + README.md | 6 +- build.gradle | 20 ++-- .../strictmodehelper/kotlin/dsl/StringMode.kt | 20 +++- .../kotlin/dsl/VmPolicyConfig.kt | 8 +- .../strictmodehelper/StrictModeCompat.java | 101 ++++++++++++++++-- 6 files changed, 139 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a19896..4e32b75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ Change Log ========== +Version 29.0.0-beta1 (2019-01-17) +--------------------------------- +Update to Android Q Beta 1 SDK (Level 29) + Version 28.0.0 (2018-06-13) --------------------------- Update to Android P SDK (Level 28) diff --git a/README.md b/README.md index f1776f0..c347d87 100644 --- a/README.md +++ b/README.md @@ -9,18 +9,18 @@ You must apply version of library for you project base on compileSdkVersion: ```groovy android { - compileSdkVersion 28 // 28 is required minimum + compileSdkVersion "android-Q" // 29 is required minimum } dependencies { // With AndroidX - implementation "com.kirich1409:strict-mode-compat:28.1.0" + implementation "com.kirich1409:strict-mode-compat:29.0.0-beta1" // Without AndroidX implementation "com.kirich1409:strict-mode-compat:28.0.0" // Kotlin Extensions - implementation "com.kirich1409:strict-mode-compat-kotlin:28.1.2" + implementation "com.kirich1409:strict-mode-compat-kotlin:29.0.0-beta1" } ``` diff --git a/build.gradle b/build.gradle index 73a681c..c004cea 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.4.0-rc01' + classpath 'com.android.tools.build:gradle:3.4.0-rc02' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' @@ -17,7 +17,13 @@ buildscript { } def getVersionCode(String versionName) { - return versionName.split("\\.").collect { String.format("%02d", it.toInteger()) }.join().toInteger() + def postfixIndex = versionName.lastIndexOf("-") + if (postfixIndex >= 0) { + versionName = versionName.substring(0, postfixIndex) + } + return versionName.split("\\.").collect { + String.format("%02d", it.toInteger()) + }.join().toInteger() } ext { @@ -25,13 +31,13 @@ ext { androidXAppCompatVersion = '1.0.2' minSdkVersion = 14 - compileSdkVersion = 28 - targetSdkVersion = 27 - buildToolsVersion = '28.0.3' + compileSdkVersion = "android-Q" + targetSdkVersion = "Q" + buildToolsVersion = "29.0.0 rc1" - strictModeCompatVersionName = '28.1.0' + strictModeCompatVersionName = '29.0.0-beta1' versionName = strictModeCompatVersionName - strictModeCompatKotlinVersionName = '28.1.2' + strictModeCompatKotlinVersionName = '29.0.0-beta1' } group = 'by.kirich1409' diff --git a/strict-mode-compat-kotlin/src/main/java/com/kirillr/strictmodehelper/kotlin/dsl/StringMode.kt b/strict-mode-compat-kotlin/src/main/java/com/kirillr/strictmodehelper/kotlin/dsl/StringMode.kt index 6e7d5df..2b813a7 100644 --- a/strict-mode-compat-kotlin/src/main/java/com/kirillr/strictmodehelper/kotlin/dsl/StringMode.kt +++ b/strict-mode-compat-kotlin/src/main/java/com/kirillr/strictmodehelper/kotlin/dsl/StringMode.kt @@ -4,7 +4,11 @@ import android.os.StrictMode import com.kirillr.strictmodehelper.StrictModeCompat @Suppress("unused") -fun initStrictMode(enable: Boolean = true, enableDefaults: Boolean = true, config: (StrictModeConfig.() -> Unit)) { +fun initStrictMode( + enable: Boolean = true, + enableDefaults: Boolean = true, + config: (StrictModeConfig.() -> Unit) +) { if (enable) { StrictModeConfig(enableDefaults).apply { config() @@ -91,9 +95,19 @@ private fun buildVmPolicy(config: VmPolicyConfig?): StrictMode.VmPolicy? { if (config.untaggedSockets) { vmPolicyBuilder.detectUntaggedSockets() } + if (config.credentialProtectedWhileLocked) { + vmPolicyBuilder.detectCredentialProtectedWhileLocked() + } + if (config.implicitDirectBoot) { + vmPolicyBuilder.detectImplicitDirectBoot() + } - config.classesInstanceLimit.toMap().forEach { (clazz, limit) -> - vmPolicyBuilder.setClassInstanceLimit(clazz.java, limit) + config.classesInstanceLimit.apply { + if (isNotEmpty()) { + toMap().forEach { (clazz, limit) -> + vmPolicyBuilder.setClassInstanceLimit(clazz.java, limit) + } + } } config.penaltyConfig.let { penaltyConfig -> diff --git a/strict-mode-compat-kotlin/src/main/java/com/kirillr/strictmodehelper/kotlin/dsl/VmPolicyConfig.kt b/strict-mode-compat-kotlin/src/main/java/com/kirillr/strictmodehelper/kotlin/dsl/VmPolicyConfig.kt index 5a68245..58a91bf 100644 --- a/strict-mode-compat-kotlin/src/main/java/com/kirillr/strictmodehelper/kotlin/dsl/VmPolicyConfig.kt +++ b/strict-mode-compat-kotlin/src/main/java/com/kirillr/strictmodehelper/kotlin/dsl/VmPolicyConfig.kt @@ -7,13 +7,17 @@ class VmPolicyConfig internal constructor(enableDefaults: Boolean) { var activityLeaks = if (enableDefaults) DEFAULT_ACTIVITY_LEAKS else false var cleartextNetwork = if (enableDefaults) DEFAULT_CLEARTEXT_NETWORK else false - var contentUriWithoutPermission = if (enableDefaults) DEFAULT_CONTENT_URI_WITHOUT_PERMISSION else false + var contentUriWithoutPermission = + if (enableDefaults) DEFAULT_CONTENT_URI_WITHOUT_PERMISSION else false var fileUriExposure = if (enableDefaults) DEFAULT_FILE_URI_EXPOSURE else false var leakedClosableObjects = if (enableDefaults) DEFAULT_LEAKED_CLOSABLE_OBJECTS else false var leakedRegistrationObjects = if (enableDefaults) DEFAULT_LEAKED_REGISTRATION_OBJECTS else false var leakedSqlLiteObjects = if (enableDefaults) DEFAULT_LEAKED_SQL_LITE_OBJECTS else false var nonSdkApiUsage = if (enableDefaults) DEFAULT_NON_SDK_API_USAGE else false var untaggedSockets = if (enableDefaults) DEFAULT_UNTAGGED_SOCKETS else false + var implicitDirectBoot = if (enableDefaults) DEFAULT_IMPLICIT_DIRECT_BOOT else false + var credentialProtectedWhileLocked = + if (enableDefaults) DEFAULT_CREDENTIAL_PROTECTED_WHILE_LOCKED else false var classesInstanceLimit = mapOf, Int>() @@ -35,6 +39,8 @@ class VmPolicyConfig internal constructor(enableDefaults: Boolean) { private const val DEFAULT_LEAKED_SQL_LITE_OBJECTS = true private const val DEFAULT_NON_SDK_API_USAGE = true private const val DEFAULT_UNTAGGED_SOCKETS = true + private const val DEFAULT_IMPLICIT_DIRECT_BOOT = true + private const val DEFAULT_CREDENTIAL_PROTECTED_WHILE_LOCKED = true } class PenaltyConfig private constructor( diff --git a/strict-mode-compat/src/main/java/com/kirillr/strictmodehelper/StrictModeCompat.java b/strict-mode-compat/src/main/java/com/kirillr/strictmodehelper/StrictModeCompat.java index 194c257..49e91bb 100644 --- a/strict-mode-compat/src/main/java/com/kirillr/strictmodehelper/StrictModeCompat.java +++ b/strict-mode-compat/src/main/java/com/kirillr/strictmodehelper/StrictModeCompat.java @@ -15,14 +15,14 @@ import android.os.strictmode.Violation; import android.util.Log; -import java.io.Closeable; -import java.util.Locale; -import java.util.concurrent.Executor; - import androidx.annotation.IntRange; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import java.io.Closeable; +import java.util.Locale; +import java.util.concurrent.Executor; + public final class StrictModeCompat { private final static String TAG = "StrictModeCompat"; @@ -706,36 +706,54 @@ public static final class Builder { private final BuilderImpl mBuilder; public Builder() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + mBuilder = new V29BuilderImpl(); + + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { mBuilder = new V28BuilderImpl(); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { mBuilder = new V26BuilderImpl(); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mBuilder = new V24BuilderImpl(); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { mBuilder = new V23BuilderImpl(); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { mBuilder = new V18BuilderImpl(); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mBuilder = new V16BuilderImpl(); + } else { mBuilder = new BaseBuilderImpl(); } } public Builder(@NonNull StrictMode.VmPolicy policy) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + mBuilder = new V28BuilderImpl(policy); + + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { mBuilder = new V28BuilderImpl(policy); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { mBuilder = new V26BuilderImpl(policy); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mBuilder = new V24BuilderImpl(policy); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { mBuilder = new V23BuilderImpl(policy); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { mBuilder = new V18BuilderImpl(policy); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mBuilder = new V16BuilderImpl(policy); + } else { mBuilder = new BaseBuilderImpl(policy); } @@ -969,6 +987,40 @@ public Builder permitNonSdkApiUsage() { mBuilder.permitNonSdkApiUsage(); return this; } + + /** + * Detect any implicit reliance on Direct Boot automatic filtering of + * {@link android.content.pm.PackageManager} values. Violations are only triggered + * when implicit calls are made while the user is locked. + *

+ * Apps becoming Direct Boot aware need to carefully inspect each query site + * and explicitly decide which combination of flags they want to use: + * + *

+ */ + public Builder detectImplicitDirectBoot() { + mBuilder.detectImplicitDirectBoot(); + return this; + } + + /** + * Detect access to filesystem paths stored in credential + * protected storage areas while the user is locked. + *

+ * When a user is locked, credential protected storage is unavailable, + * and files stored in these locations appear to not exist, which can result + * in subtle app bugs if they assume default behaviors or empty states. + * Instead, apps should store data needed while a user is locked + * under device protected storage areas. + */ + public Builder detectCredentialProtectedWhileLocked() { + mBuilder.detectCredentialProtectedWhileLocked(); + return this; + } } private interface BuilderImpl { @@ -1022,6 +1074,12 @@ private interface BuilderImpl { // Min SDK 28 void permitNonSdkApiUsage(); + + // Min SDK 29 + void detectImplicitDirectBoot(); + + // Min SDK 29 + void detectCredentialProtectedWhileLocked(); } private static class BaseBuilderImpl implements BuilderImpl { @@ -1133,6 +1191,16 @@ public void penaltyListener(@NonNull Executor executor, public void permitNonSdkApiUsage() { logUnsupportedFeature(CATEGORY, "Non SDK api usage"); } + + @Override + public void detectImplicitDirectBoot() { + logUnsupportedFeature(CATEGORY, "Implicit Direct Boot"); + } + + @Override + public void detectCredentialProtectedWhileLocked() { + logUnsupportedFeature(CATEGORY, "Credential Protected While Locked"); + } } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @@ -1263,6 +1331,27 @@ public void onVmViolation(Violation violation) { ); } } + + @TargetApi(Build.VERSION_CODES.Q) + private static class V29BuilderImpl extends V26BuilderImpl { + + V29BuilderImpl() { + } + + V29BuilderImpl(@NonNull StrictMode.VmPolicy policy) { + super(policy); + } + + @Override + public void detectImplicitDirectBoot() { + builder.detectImplicitDirectBoot(); + } + + @Override + public void detectCredentialProtectedWhileLocked() { + builder.detectCredentialProtectedWhileLocked(); + } + } } /**