Skip to content

Commit

Permalink
Not to initialize SDK if the device is in direct boot mode
Browse files Browse the repository at this point in the history
  • Loading branch information
yangyansong-adbe committed Jun 21, 2024
1 parent 84ba8a8 commit 08537bb
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 2 deletions.
2 changes: 1 addition & 1 deletion code/core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ dependencies {
testImplementation 'org.mockito:mockito-inline:4.5.1'
//noinspection GradleDependency
testImplementation 'commons-codec:commons-codec:1.15'
testImplementation 'org.robolectric:robolectric:3.6.2'
testImplementation 'org.robolectric:robolectric:4.7'
testImplementation "org.mockito.kotlin:mockito-kotlin:3.2.0"
//noinspection GradleDependency
testImplementation 'org.json:json:20160810'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@

import android.app.Activity;
import android.app.Application;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.os.UserManagerCompat;
import com.adobe.marketing.mobile.internal.AppResourceStore;
import com.adobe.marketing.mobile.internal.CoreConstants;
import com.adobe.marketing.mobile.internal.configuration.ConfigurationExtension;
Expand Down Expand Up @@ -96,6 +99,23 @@ public static void setApplication(@NonNull final Application application) {
CoreConstants.LOG_TAG, LOG_TAG, "setApplication failed - application is null");
return;
}
// Direct boot mode is supported on Android N and above
if (VERSION.SDK_INT >= VERSION_CODES.N) {
if (UserManagerCompat.isUserUnlocked(application)) {
Log.debug(
CoreConstants.LOG_TAG,
LOG_TAG,
"setApplication - device is unlocked and not in direct boot mode,"
+ " initializing the SDK.");
} else {
Log.error(
CoreConstants.LOG_TAG,
LOG_TAG,
"setApplication failed - device is in direct boot mode, SDK will not be"
+ " initialized.");
return;
}
}

if (sdkInitializedWithContext.getAndSet(true)) {
Log.debug(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
Copyright 2024 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

package com.adobe.marketing.mobile

import android.app.Application
import androidx.core.os.UserManagerCompat
import com.adobe.marketing.mobile.internal.eventhub.EventHub
import junit.framework.TestCase.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.kotlin.any
import org.mockito.kotlin.never
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.test.assertFalse

@RunWith(RobolectricTestRunner::class)
class MobileCoreRobolectricTests {

@Before
fun setup() {
MobileCore.sdkInitializedWithContext = AtomicBoolean(false)
}

@Test
@Config(sdk = [23])
fun `test setApplication when the device doesn't support direct boot mode`() {
// Android supports direct boot mode on API level 24 and above
val app = RuntimeEnvironment.application as Application
val mockedEventHub = Mockito.mock(EventHub::class.java)
Mockito.mockStatic(UserManagerCompat::class.java).use { mockedStaticUserManagerCompat ->
mockedStaticUserManagerCompat.`when`<Any> { UserManagerCompat.isUserUnlocked(Mockito.any()) }
.thenReturn(false)
MobileCore.setApplication(app)
mockedStaticUserManagerCompat.verify({ UserManagerCompat.isUserUnlocked(Mockito.any()) }, never())
}
verify(mockedEventHub, never()).executeInEventHubExecutor(any())
assertTrue(MobileCore.sdkInitializedWithContext.get())
}

@Test
@Config(sdk = [24])
fun `test setApplication when the app is not configured to run in direct boot mode`() {
val app = RuntimeEnvironment.application as Application
val mockedEventHub = Mockito.mock(EventHub::class.java)
EventHub.shared = mockedEventHub
Mockito.mockStatic(UserManagerCompat::class.java).use { mockedStaticUserManagerCompat ->
// when initializing SDK, the app is not in direct boot mode (device is unlocked)
mockedStaticUserManagerCompat.`when`<Any> { UserManagerCompat.isUserUnlocked(Mockito.any()) }.thenReturn(true)
MobileCore.setApplication(app)
mockedStaticUserManagerCompat.verify({ UserManagerCompat.isUserUnlocked(Mockito.any()) }, times(1))
}
verify(mockedEventHub, times(1)).executeInEventHubExecutor(any())
assertTrue(MobileCore.sdkInitializedWithContext.get())
}

@Test
@Config(sdk = [24])
fun `test setApplication when the app is launched in direct boot mode`() {
val app = RuntimeEnvironment.application as Application
val mockedEventHub = Mockito.mock(EventHub::class.java)
Mockito.mockStatic(UserManagerCompat::class.java).use { mockedStaticUserManagerCompat ->
// when initializing SDK, the app is in direct boot mode (device is still locked)
mockedStaticUserManagerCompat.`when`<Any> { UserManagerCompat.isUserUnlocked(Mockito.any()) }.thenReturn(false)
MobileCore.setApplication(app)
mockedStaticUserManagerCompat.verify({ UserManagerCompat.isUserUnlocked(Mockito.any()) }, times(1))
}
verify(mockedEventHub, never()).executeInEventHubExecutor(any())
assertFalse(MobileCore.sdkInitializedWithContext.get())
}
}
13 changes: 12 additions & 1 deletion code/testapp-kotlin/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.adobe.marketing.mobile.app.kotlin">

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".MyApp"
android:allowBackup="true"
Expand All @@ -26,6 +26,17 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>


<receiver android:name=".BootBroadcastReceiver"
android:exported="false"
android:directBootAware="true"
tools:targetApi="n">
<intent-filter>
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Copyright 2024 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/
package com.adobe.marketing.mobile.app.kotlin

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.core.os.UserManagerCompat

class BootBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
Log.i(
TAG, "Received action: $action, isUserUnlocked(): " + UserManagerCompat
.isUserUnlocked(context)
)
}

companion object {
private const val TAG = "BootBroadcastReceiver"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
package com.adobe.marketing.mobile.app.kotlin

import android.app.Application
import android.util.Log
import androidx.core.os.UserManagerCompat
import com.adobe.marketing.mobile.MobileCore
import com.adobe.marketing.mobile.Identity
import com.adobe.marketing.mobile.Lifecycle
Expand All @@ -22,6 +24,8 @@ class MyApp : Application() {

override fun onCreate() {
super.onCreate()

Log.i("MyApp", "[Android 2.x] Application.onCreate() - start to initialize Adobe SDK. UserManagerCompat.isUserUnlocked(): ${UserManagerCompat.isUserUnlocked(this)}")
MobileCore.setApplication(this)
MobileCore.setLogLevel(LoggingMode.VERBOSE)
// MobileCore.configureWithAppID("YOUR_APP_ID")
Expand Down

0 comments on commit 08537bb

Please sign in to comment.