Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/platform interaction stability improvements #106

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/blank.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: Set up Java env
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'

- name: Make gradlew executable
run: chmod +x ./gradlew

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/instumented_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ jobs:
- name: Set up Java env
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '11'
distribution: 'temurin'
java-version: '17'

- name: Instrumented tests
id: instrumented_tests
Expand Down
20 changes: 15 additions & 5 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
}

android {
compileSdk = 33
compileSdk = 34

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.

defaultConfig {
applicationId = "com.fingerprintjs.android.playground"
Expand Down Expand Up @@ -47,7 +47,7 @@
isMinifyEnabled = true
proguardFiles (getDefaultProguardFile ("proguard-android-optimize.txt"), "proguard-rules.pro")
signingConfig = signingConfigs.getByName("releaseDummySign")
setMatchingFallbacks("release")
matchingFallbacks += listOf("release")
}
// same as previous, but also profileable
// when changing the name of the following build type, don't forget to update src/{this_build_type} dir
Expand All @@ -65,12 +65,21 @@
}
}

compileOptions {
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}

buildFeatures {
compose = true
buildConfig = true
}

composeOptions {
kotlinCompilerExtensionVersion = "1.4.7"
kotlinCompilerExtensionVersion = "1.5.3"
}
}

Expand All @@ -95,8 +104,9 @@

implementation("com.google.accompanist:accompanist-pager:0.27.0")

implementation("com.google.dagger:dagger:2.44")
kapt("com.google.dagger:dagger-compiler:2.44")
val daggerVersion = "2.48"
implementation("com.google.dagger:dagger:$daggerVersion")
kapt("com.google.dagger:dagger-compiler:$daggerVersion")

implementation("com.google.code.gson:gson:2.10")
}
3 changes: 1 addition & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ buildscript {
gradlePluginPortal()
}
dependencies {
classpath("com.android.tools.build:gradle:7.4.2")
classpath("com.android.tools.build:gradle:8.1.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Constants.kotlinVersion}")
classpath("com.github.dcendents:android-maven-gradle-plugin:2.1")
}
}

Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/Constants.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
object Constants {
const val kotlinVersion = "1.8.21"
const val kotlinVersion = "1.9.10"
}
26 changes: 23 additions & 3 deletions fingerprint/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,23 @@
}

android {
compileSdk = 33
publishing {
singleVariant("release") {
withSourcesJar()
}
}

compileSdk = 34

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.

defaultConfig {
minSdk = 21
// This property does not affect the library itself, but affects test apk and lint.
// As for now, I don't see any non-deprecated ways of accomplishing this task.
// Discussions:
// https://stackoverflow.com/questions/76084080/apply-targetsdk-in-android-instrumentation-test
// https://issuetracker.google.com/issues/230625468 (looks like lint.targetSdk and testOptions.targetSdk will become available soon)

Check warning

Code scanning / detekt

Line detected that is longer than the defined maximum line length in the code style. Warning

Line detected that is longer than the defined maximum line length in the code style.
targetSdk = 33

minSdk = 21

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
Expand Down Expand Up @@ -62,6 +74,14 @@
}
}
}

compileOptions {
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class.java) {
Expand All @@ -74,7 +94,7 @@
implementation("org.jetbrains.kotlin:kotlin-stdlib:${Constants.kotlinVersion}")
implementation("androidx.appcompat:appcompat:1.6.1")
testImplementation("junit:junit:4.13.2")
testImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0")
testImplementation("io.mockk:mockk:1.12.7")
androidTestImplementation("androidx.test.ext:junit-ktx:1.1.5")
androidTestImplementation("androidx.test:runner:1.5.2")
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,24 @@ import com.fingerprintjs.android.fingerprint.signal_providers.hardware.HardwareS
import com.fingerprintjs.android.fingerprint.signal_providers.installed_apps.InstalledAppsSignalGroupProvider
import com.fingerprintjs.android.fingerprint.signal_providers.os_build.OsBuildSignalGroupProvider
import com.fingerprintjs.android.fingerprint.tools.DeprecationMessages
import com.fingerprintjs.android.fingerprint.tools.DummyResults
import com.fingerprintjs.android.fingerprint.tools.FingerprintingLegacySchemeSupportExtensions
import com.fingerprintjs.android.fingerprint.tools.hashers.Hasher
import com.fingerprintjs.android.fingerprint.tools.hashers.MurMur3x64x128Hasher
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import com.fingerprintjs.android.fingerprint.tools.logs.Logger
import com.fingerprintjs.android.fingerprint.tools.logs.ePleaseReport
import com.fingerprintjs.android.fingerprint.tools.safe.safe
import com.fingerprintjs.android.fingerprint.tools.safe.safeAsync


public class Fingerprinter internal constructor(
private val legacyArgs: LegacyArgs?,
private val fpSignalsProvider: FingerprintingSignalsProvider,
private val deviceIdSignalsProvider: DeviceIdSignalsProvider,
) {

private val executor: ExecutorService = Executors.newSingleThreadExecutor()

@Volatile
private var deviceIdResult: DeviceIdResult? = null
@Volatile
private var fingerprintResult: FingerprintResult? = null

/**
Expand Down Expand Up @@ -59,7 +61,12 @@ public class Fingerprinter internal constructor(
return
}

executor.execute {
safeAsync(
onError = {
listener.invoke(DummyResults.deviceIdResult)
Logger.ePleaseReport(it)
}
) {
val deviceIdResult = DeviceIdResult(
legacyArgs.deviceIdProvider.fingerprint(),
legacyArgs.deviceIdProvider.rawData().gsfId().value,
Expand All @@ -82,7 +89,12 @@ public class Fingerprinter internal constructor(
* @param listener device ID listener.
*/
public fun getDeviceId(version: Version, listener: (DeviceIdResult) -> Unit) {
executor.execute {
safeAsync(
onError = {
listener.invoke(DummyResults.deviceIdResult)
Logger.ePleaseReport(it)
}
) {
listener.invoke(
DeviceIdResult(
deviceId = deviceIdSignalsProvider.getSignalMatching(version).getIdString(),
Expand Down Expand Up @@ -128,7 +140,12 @@ public class Fingerprinter internal constructor(
listener.invoke(it)
return
}
executor.execute {
safeAsync(
onError = {
listener.invoke(DummyResults.fingerprintResult)
Logger.ePleaseReport(it)
}
) {
val fingerprintSb = StringBuilder()

fingerprintSb.apply {
Expand Down Expand Up @@ -178,8 +195,12 @@ public class Fingerprinter internal constructor(
hasher: Hasher = MurMur3x64x128Hasher(),
listener: (String) -> (Unit),
) {
executor.execute {

safeAsync(
onError = {
listener.invoke(DummyResults.fingerprint)
Logger.ePleaseReport(it)
}
) {
val result = if (version < Version.fingerprintingFlattenedSignalsFirstVersion) {
val joinedHashes = with(FingerprintingLegacySchemeSupportExtensions) {
listOf(
Expand Down Expand Up @@ -221,7 +242,9 @@ public class Fingerprinter internal constructor(
fingerprintingSignals: List<FingerprintingSignal<*>>,
hasher: Hasher = MurMur3x64x128Hasher(),
): String {
return hasher.hash(fingerprintingSignals)
return safe { hasher.hash(fingerprintingSignals) }
.onFailure { Logger.ePleaseReport(it) }
.getOrDefault(DummyResults.fingerprint)
}

private fun Hasher.hash(fingerprintingSignals: List<FingerprintingSignal<*>>): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@
import com.fingerprintjs.android.fingerprint.signal_providers.os_build.OsBuildSignalGroupProvider
import com.fingerprintjs.android.fingerprint.tools.hashers.Hasher
import com.fingerprintjs.android.fingerprint.tools.hashers.MurMur3x64x128Hasher
import com.fingerprintjs.android.fingerprint.tools.safe.safeLazy
import com.fingerprintjs.android.fingerprint.tools.safe.safe


/**
* A factory for [Fingerprinter] class.
*/
public object FingerprinterFactory {

private var configuration: Configuration = Configuration(version = Fingerprinter.Version.fingerprintingGroupedSignalsLastVersion.intValue)
private var configuration = Configuration(version = Fingerprinter.Version.fingerprintingGroupedSignalsLastVersion.intValue)

Check warning

Code scanning / detekt

Line detected that is longer than the defined maximum line length in the code style. Warning

Line detected that is longer than the defined maximum line length in the code style.
private var instance: Fingerprinter? = null
private var hasher: Hasher = MurMur3x64x128Hasher()

Expand Down Expand Up @@ -179,83 +181,73 @@
private fun createCpuInfoProvider() = CpuInfoProviderImpl()

private fun createMemoryInfoProvider(context: Context): MemInfoProvider {
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val internalStorageDir = Environment.getRootDirectory().absolutePath
val internalStorageStatFs = StatFs(internalStorageDir)

val externalStorageDir = context.getExternalFilesDir(null)
val externalStorageDirPath = externalStorageDir?.absolutePath
val externalStorageStatFs =
if (externalStorageDirPath != null && externalStorageDir.canRead()) {
StatFs(externalStorageDirPath)
} else {
null
}

return MemInfoProviderImpl(
activityManager,
internalStorageStatFs,
externalStorageStatFs
activityManager = safeLazy { context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager },
internalStorageStats = safeLazy { StatFs(Environment.getRootDirectory()!!.absolutePath!!) },
externalStorageStats = safeLazy {
context.getExternalFilesDir(null)
?.takeIf { it.canRead() }
?.let { StatFs(it.absolutePath!!) }!!
},
)
}

private fun createOsBuildInfoProvider() = OsBuildInfoProviderImpl()

private fun createGsfIdProvider(context: Context) = GsfIdProvider(context.contentResolver!!)
private fun createGsfIdProvider(context: Context) = GsfIdProvider(
safe { context.contentResolver!! }.getOrDefault(null)
)

private fun createMediaDrmProvider() = MediaDrmIdProvider()

private fun createAndroidIdProvider(context: Context) =
AndroidIdProvider(context.contentResolver!!)
private fun createAndroidIdProvider(context: Context) = AndroidIdProvider(
safe { context.contentResolver!! }.getOrDefault(null)
)

private fun createSensorDataSource(context: Context) = SensorDataSourceImpl(
context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
safeLazy { context.getSystemService(Context.SENSOR_SERVICE) as SensorManager }
)

private fun createInputDevicesDataSource(context: Context) = InputDevicesDataSourceImpl(
context.getSystemService(Context.INPUT_SERVICE) as InputManager
safeLazy { context.getSystemService(Context.INPUT_SERVICE) as InputManager }
)

private fun createPackageManagerDataSource(context: Context) = PackageManagerDataSourceImpl(
context.packageManager
safeLazy { context.packageManager!! }
)

private fun createSettingsDataSource(context: Context) = SettingsDataSourceImpl(
context.contentResolver
safeLazy { context.contentResolver!! }
)


private fun createDevicePersonalizationDataSource(context: Context) =
DevicePersonalizationInfoProviderImpl(
RingtoneManager(context),
context.assets,
context.resources.configuration
ringtoneManager = safeLazy { RingtoneManager(context) },
assetManager = safeLazy { context.assets!! },
configuration = safeLazy { context.resources!!.configuration!! },
)

private fun createFingerprintSensorStatusProvider(context: Context) =
FingerprintSensorInfoProviderImpl(
FingerprintManagerCompat.from(context)
safeLazy { FingerprintManagerCompat.from(context)!! }
)

private fun createDeviceSecurityProvider(context: Context) = DeviceSecurityInfoProviderImpl(
context.getSystemService(Context.DEVICE_POLICY_SERVICE) as? DevicePolicyManager,
context.getSystemService(Context.KEYGUARD_SERVICE) as? KeyguardManager
safeLazy { context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager },
safeLazy { context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager },
)

private fun createCodecInfoProvider() = CodecInfoProviderImpl(
MediaCodecList(MediaCodecList.ALL_CODECS)
safeLazy { MediaCodecList(MediaCodecList.ALL_CODECS) }
)

private fun createBatteryInfoDataSource(context: Context) = BatteryInfoProviderImpl(
context
)
private fun createBatteryInfoDataSource(context: Context) = BatteryInfoProviderImpl(context)

private fun createCameraInfoProvider(): CameraInfoProvider {
return CameraInfoProviderImpl()
}
private fun createCameraInfoProvider(): CameraInfoProvider = CameraInfoProviderImpl()

private fun createGpuInfoProvider(context: Context) =
GpuInfoProviderImpl(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager)
GpuInfoProviderImpl(safeLazy { context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager } )

//endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ import android.annotation.SuppressLint
import android.content.ContentResolver
import android.provider.Settings
import com.fingerprintjs.android.fingerprint.tools.DeprecationMessages
import com.fingerprintjs.android.fingerprint.tools.executeSafe
import com.fingerprintjs.android.fingerprint.tools.safe.safe


@Deprecated(message = DeprecationMessages.UNREACHABLE_SYMBOL_UNINTENDED_PUBLIC_API)
public class AndroidIdProvider(
private val contentResolver: ContentResolver
private val contentResolver: ContentResolver?
) {
@SuppressLint("HardwareIds")
public fun getAndroidId(): String {
return executeSafe({
return safe {
Settings.Secure.getString(
contentResolver,
contentResolver!!,
Settings.Secure.ANDROID_ID
)
}, "")
)!!
}.getOrDefault("")
}
}
Loading
Loading