Skip to content

fix: end initialization early if device storage is in the locked state #2348

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ interface IApplicationService {
*/
val isInForeground: Boolean

/**
* Whether the device storage for the user data is accessible.
*
* Always return true for API 23 and below as the device booted into an unlocked state by default
*/
val isDeviceStorageUnlocked: Boolean

/**
* How the application was entered. This is writeable to allow for the setting
* to [AppEntryAction.NOTIFICATION_CLICK] when it is determined a notification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import android.content.ComponentCallbacks
import android.content.Context
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.os.UserManager
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.DialogFragment
Expand Down Expand Up @@ -70,6 +72,25 @@ class ApplicationService() : IApplicationService, ActivityLifecycleCallbacks, On
private val wasInBackground: Boolean
get() = !isInForeground || nextResumeIsFirstActivity

/**
* Retrieve whether the user data is accessible.
*
* On Android 7.0+ (API 24+), encrypted user data is inaccessible until the user unlocks the device for the first time after boot.
* This includes:
* * getSharedPreferences()
* * Any file-based storage in the default credential-encrypted context
*
* Apps that auto-run on boot or background services triggered early may hit this issue.
*/
override val isDeviceStorageUnlocked: Boolean
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val userManager = appContext.getSystemService(Context.USER_SERVICE) as UserManager
userManager.isUserUnlocked
} else {
// Prior to API 24, the device booted into an unlocked state by default
true
}

/**
* Call to "start" this service, expected to be called during initialization of the SDK.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,16 @@ internal class OneSignalImp : IOneSignal, IServiceProvider {

PreferenceStoreFix.ensureNoObfuscatedPrefStore(context)

val applicationService = services.getService<IApplicationService>()

// start the application service. This is called explicitly first because we want
// to make sure it has the context provided on input, for all other startable services
// to depend on if needed.
val applicationService = services.getService<IApplicationService>()
(applicationService as ApplicationService).start(context)
if (!applicationService.isDeviceStorageUnlocked) {
Logging.warn("initWithContext called when device storage is locked, no user data is accessible!")
return false
}

// Give the logging singleton access to the application service to support visual logging.
Logging.applicationService = applicationService
Expand Down
Loading