diff --git a/src/Essentials/src/SecureStorage/SecureStorage.android.cs b/src/Essentials/src/SecureStorage/SecureStorage.android.cs index 7c29883b59c7..d1de8d968bc5 100644 --- a/src/Essentials/src/SecureStorage/SecureStorage.android.cs +++ b/src/Essentials/src/SecureStorage/SecureStorage.android.cs @@ -9,26 +9,21 @@ namespace Microsoft.Maui.Storage { partial class SecureStorageImplementation : ISecureStorage { - readonly object locker = new(); - - Task PlatformGetAsync(string key) + async Task PlatformGetAsync(string key) { - return Task.Run(() => + return await Task.Run(() => { try { - lock (locker) - { - ISharedPreferences sharedPreferences = GetEncryptedSharedPreferences(); - if (sharedPreferences != null) - return sharedPreferences.GetString(key, null); + ISharedPreferences sharedPreferences = GetEncryptedSharedPreferences(); + if (sharedPreferences != null) + return sharedPreferences.GetString(key, null); - // TODO: Use Logger here? - System.Diagnostics.Debug.WriteLine( - $"Unable to decrypt key, {key}, which is likely due to key corruption. Removing old key and returning null."); - PlatformRemove(key); - return null; - } + // TODO: Use Logger here? + System.Diagnostics.Debug.WriteLine( + $"Unable to decrypt key, {key}, which is likely due to key corruption. Removing old key and returning null."); + PlatformRemove(key); + return null; } catch (GeneralSecurityException) { @@ -49,45 +44,41 @@ Task PlatformGetAsync(string key) }); } - Task PlatformSetAsync(string key, string data) + async Task PlatformSetAsync(string key, string data) { - return Task.Run(() => + await Task.Run(() => { - lock (locker) - { - using ISharedPreferencesEditor editor = GetEncryptedSharedPreferences()?.Edit(); - if (data == null) - editor?.Remove(key); - else - editor?.PutString(key, data); + using ISharedPreferencesEditor editor = GetEncryptedSharedPreferences()?.Edit(); + if (data is null) + editor?.Remove(key); + else + editor?.PutString(key, data); - editor?.Apply(); - } + editor?.Apply(); }); } bool PlatformRemove(string key) { - lock (locker) - { - using ISharedPreferencesEditor editor = GetEncryptedSharedPreferences()?.Edit(); - editor?.Remove(key)?.Apply(); - } - + using ISharedPreferencesEditor editor = GetEncryptedSharedPreferences()?.Edit(); + editor?.Remove(key)?.Apply(); return true; } void PlatformRemoveAll() { - lock (locker) - { - using var editor = PreferencesImplementation.GetSharedPreferences(Alias).Edit(); - editor?.Clear()?.Apply(); - } + using var editor = PreferencesImplementation.GetSharedPreferences(Alias).Edit(); + editor?.Clear()?.Apply(); } + ISharedPreferences _prefs; ISharedPreferences GetEncryptedSharedPreferences() { + if (_prefs is not null) + { + return _prefs; + } + try { var context = Application.Context; @@ -103,7 +94,7 @@ ISharedPreferences GetEncryptedSharedPreferences() EncryptedSharedPreferences.PrefKeyEncryptionScheme.Aes256Siv, EncryptedSharedPreferences.PrefValueEncryptionScheme.Aes256Gcm); - return sharedPreferences; + return _prefs = sharedPreferences; } catch (InvalidProtocolBufferException) { @@ -115,4 +106,4 @@ ISharedPreferences GetEncryptedSharedPreferences() } } } -} \ No newline at end of file +} diff --git a/src/Essentials/test/DeviceTests/Tests/SecureStorage_Tests.cs b/src/Essentials/test/DeviceTests/Tests/SecureStorage_Tests.cs index 1fc97678f2d2..3a7e52659217 100644 --- a/src/Essentials/test/DeviceTests/Tests/SecureStorage_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/SecureStorage_Tests.cs @@ -156,5 +156,21 @@ await SecureStorage.SetAsync(i.ToString(), i.ToString()) Assert.Equal(i.ToString(), v); } } + + [Fact] + public async Task Set_Get_Remove_Async_MultipleTimes() + { + await Parallel.ForEachAsync(Enumerable.Range(0, 100), async (i, _) => + { + var key = $"key{i}"; + var value = $"value{i}"; + await SecureStorage.SetAsync(key, value); + var fetched = await SecureStorage.GetAsync(key); + Assert.Equal(value, fetched); + SecureStorage.Remove(key); + fetched = await SecureStorage.GetAsync(key); + Assert.Null(fetched); + }); + } } }