summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Moroney <mmoro@google.com>2022-05-26 13:18:44 -0700
committerMike Moroney <mmoro@google.com>2022-06-01 20:26:43 +0000
commit032c24158c76daad78b60a8ec5b949ba47768446 (patch)
treedd4fed0bd07596e2215c297daacb24bb49aaa569
parent1450d83a1bfd37a029a5e6cb0a938e4a62d344b9 (diff)
downloadanalytics-library-032c24158c76daad78b60a8ec5b949ba47768446.tar.gz
Recreate corrupted analytics settings
This prevents the consent dialog from appearing on each startup Bug: 233779727 Test: AnalyticsSettingsTest.loadBadSettingsTest Change-Id: Iefec6f28d546f47d0f21241ad58806ac119d7e81
-rw-r--r--shared/src/main/java/com/android/tools/analytics/AnalyticsSettings.kt73
-rw-r--r--shared/src/test/java/com/android/tools/analytics/AnalyticsSettingsTest.kt7
2 files changed, 51 insertions, 29 deletions
diff --git a/shared/src/main/java/com/android/tools/analytics/AnalyticsSettings.kt b/shared/src/main/java/com/android/tools/analytics/AnalyticsSettings.kt
index 61e7ed4..dc2b53d 100644
--- a/shared/src/main/java/com/android/tools/analytics/AnalyticsSettings.kt
+++ b/shared/src/main/java/com/android/tools/analytics/AnalyticsSettings.kt
@@ -32,6 +32,7 @@ import java.io.RandomAccessFile
import java.math.BigInteger
import java.net.URL
import java.nio.channels.Channels
+import java.nio.channels.FileChannel
import java.nio.channels.OverlappingFileLockException
import java.nio.file.Paths
import java.security.SecureRandom
@@ -257,30 +258,26 @@ object AnalyticsSettings {
@JvmStatic
private fun loadSettingsData(logger: ILogger): AnalyticsSettingsData {
val file = settingsFile
- if (!file.exists()) {
- return createNewAnalyticsSettingsData()
- }
- val channel = RandomAccessFile(file, "rw").channel
- try {
- val settings: AnalyticsSettingsData? = channel.tryLock().use {
- val inputStream = Channels.newInputStream(channel)
- val gson = GsonBuilder().create()
- gson.fromJson(InputStreamReader(inputStream), AnalyticsSettingsData::class.java)
- }
- if (settings == null || !isValid(settings)) {
- return createNewAnalyticsSettingsData()
+ if (file.exists()) {
+ val channel = RandomAccessFile(file, "rw").channel
+ try {
+ channel.tryLock().use {
+ AnalyticsSettingsData.parseSettingsData(channel, file, logger)?.let {
+ if (isValid(it)) {
+ return it
+ }
+ }
+ }
+ } catch (e: OverlappingFileLockException) {
+ logger.warning("Unable to lock settings file %s: %s", file.toString(), e)
+
+ val newSettings = AnalyticsSettingsData()
+ newSettings.userId = UUID.randomUUID().toString()
+ return newSettings
}
- return settings
- } catch (e: OverlappingFileLockException) {
- logger.warning("Unable to lock settings file %s: %s", file.toString(), e)
- } catch (e: JsonParseException) {
- logger.warning("Unable to parse settings file %s: %s", file.toString(), e)
- } catch (e: IllegalStateException) {
- logger.warning("Unable to parse settings file %s: %s", file.toString(), e)
}
- val newSettings = AnalyticsSettingsData()
- newSettings.userId = UUID.randomUUID().toString()
- return newSettings
+
+ return createNewAnalyticsSettingsData(logger)
}
/**
@@ -292,7 +289,7 @@ object AnalyticsSettings {
@VisibleForTesting
@JvmStatic
@Throws(IOException::class)
- private fun createNewAnalyticsSettingsData(): AnalyticsSettingsData {
+ private fun createNewAnalyticsSettingsData(logger: ILogger): AnalyticsSettingsData {
val settings = AnalyticsSettingsData()
val uidFile =
@@ -304,12 +301,11 @@ object AnalyticsSettings {
} catch (e: IOException) {
// Ignore and set new UID.
}
-
}
if (settings.userId == null) {
settings.userId = UUID.randomUUID().toString()
}
- settings.saveSettings()
+ settings.saveSettings(logger)
return settings
}
@@ -444,7 +440,7 @@ object AnalyticsSettings {
class AnalyticsSettingsData {
- fun saveSettings() {
+ fun saveSettings(logger: ILogger? = null) {
val file = AnalyticsSettings.settingsFile
val dir = file.parentFile
if (!dir.exists()) {
@@ -457,10 +453,8 @@ class AnalyticsSettingsData {
if (lock == null) {
throw IOException("Unable to lock settings file $file")
}
- val gson = GsonBuilder().create()
- val readStream = InputStreamReader(Channels.newInputStream(channel))
val existingData =
- gson.fromJson(readStream, AnalyticsSettingsData::class.java)
+ parseSettingsData(channel, file, null)
if (existingData?.saltSkew == saltSkew) {
// The salt is apparently updated by some other process. In this case we read that on the disk rather than using our own in
// order to make sure all processes use the same salt.
@@ -515,6 +509,27 @@ class AnalyticsSettingsData {
@field:SerializedName("lastOptinPromptVersion")
var lastOptinPromptVersion: String? = null
+
+ companion object {
+
+ fun parseSettingsData(
+ channel: FileChannel,
+ file: File,
+ logger: ILogger? = null
+ ): AnalyticsSettingsData? {
+ val inputStream = Channels.newInputStream(channel)
+ val gson = GsonBuilder().create()
+ return try {
+ gson.fromJson(InputStreamReader(inputStream), AnalyticsSettingsData::class.java)
+ } catch (e: JsonParseException) {
+ logger?.warning("Unable to parse settings file %s: %s", file.toString(), e)
+ null
+ } catch (e: IllegalStateException) {
+ logger?.warning("Unable to parse settings file %s: %s", file.toString(), e)
+ null
+ }
+ }
+ }
}
fun BigInteger.toByteArrayOfLength24(): ByteArray {
diff --git a/shared/src/test/java/com/android/tools/analytics/AnalyticsSettingsTest.kt b/shared/src/test/java/com/android/tools/analytics/AnalyticsSettingsTest.kt
index 7ac88eb..372117b 100644
--- a/shared/src/test/java/com/android/tools/analytics/AnalyticsSettingsTest.kt
+++ b/shared/src/test/java/com/android/tools/analytics/AnalyticsSettingsTest.kt
@@ -155,6 +155,13 @@ class AnalyticsSettingsTest {
AnalyticsSettings.initialize(countingLogger)
assertEquals(1, countingLogger.warnings)
+
+ AnalyticsSettings.setInstanceForTest(null)
+ countingLogger.warnings = 0
+ AnalyticsSettings.initialize(countingLogger)
+
+ // Verify that corrupted file has been overwritten with valid file
+ assertEquals(0, countingLogger.warnings)
} finally {
EnvironmentFakes.setSystemEnvironment()
}