fix(application-settings): use correct storage on Android N and above
Fixes the use of Android Device Storage for Application Settings to avoid runtime error cause by user accessing SharedPreferances when the device is locked:
Unable to create application com.tns.NativeScriptApplication: com.tns.NativeScriptException: Error calling module function
Error: java.lang.IllegalStateException: SharedPreferences in credential encrypted storage are not available until after user is unlocked
Logic is based on the snippet from Google Archive here:
https://github.com/googlearchive/android-DirectBoot/blob/737ab9a214debbf3c940360b834077ccc3035ff3/Application/src/main/java/com/example/android/directboot/alarms/AlarmStorage.java#L42
// All N devices have split storage areas, but we may need to
// move the existing preferences to the new device protected
// storage area, which is where the data lives from now on.
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign the CLA at https://www.nativescript.org/cla.
CLA has not been signed by users: @nikoTM.
After signing the CLA, you can ask me to recheck this PR by posting @cla-bot check as a comment to the PR.
@cla-bot check
The cla-bot has been summoned, and re-checked this pull request!
@NathanWalker I added comments on this
I think this would be considered a breaking change. If the android device supports and is using direct boot mode, then there is two storage locations. The "User locked" storage, and the "Device locked" storage. Google recommends only using the device locked storage if you strictly need parts of your app to run while the device is locked from a fresh reboot, and to only put data into it regarding those functions that run in direct boot mode.
Use device encrypted storage only for information that must be accessible during Direct Boot mode. Don't use device encrypted storage as a general-purpose encrypted store. For private user information, or encrypted data that isn't needed during Direct Boot mode, use credential encrypted storage.
The rest of your app should only use the user locked storage as to ensure that information like user tokens are secured by the users passcode.
The changes proposed in this PR only utilize the device locked storage, so any developers using application settings to store sensitive info on behalf of the user will now be using a less secure storage method without realizing it.
I think the developer should be able to access either storage locations and decide which one to use. Someone with more knowledge of the Android runtime and background services might be able to better explain how developers should access one or the other.
@Archez while that's true and this change has a security implications, ApplicationSettings are not meant to be a storage for secure information, it's meant to be used to store...well settings. There is no difference between what we have and what this PR is proposing once the device is unlocked. There are plugins available to store secure data.
@nikoTM I think the root cause is that the preferences are accessed when the phone is locked after boot. That should not happen IMHO.
We experience lots of ANRs due to that, even though the issue was supposedly fixed by this PR https://github.com/NativeScript/android-runtime/pull/1712 - but even when using android-runtime 8.2.3 and above, we get the original issue.