diff options
author | Mike Moroney <mmoro@google.com> | 2022-05-26 13:18:44 -0700 |
---|---|---|
committer | Mike Moroney <mmoro@google.com> | 2022-06-01 20:26:43 +0000 |
commit | 032c24158c76daad78b60a8ec5b949ba47768446 (patch) | |
tree | dd4fed0bd07596e2215c297daacb24bb49aaa569 | |
parent | 1450d83a1bfd37a029a5e6cb0a938e4a62d344b9 (diff) | |
download | analytics-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.kt | 73 | ||||
-rw-r--r-- | shared/src/test/java/com/android/tools/analytics/AnalyticsSettingsTest.kt | 7 |
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() } |