Skip to content

Commit

Permalink
Merge pull request #517 from adobe/staging
Browse files Browse the repository at this point in the history
  • Loading branch information
praveek authored Jul 26, 2023
2 parents d7ca19d + b527dcb commit 8195cbb
Show file tree
Hide file tree
Showing 35 changed files with 621 additions and 185 deletions.
1 change: 1 addition & 0 deletions code/core/api/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,7 @@ public abstract interface class com/adobe/marketing/mobile/services/DeviceInform
public abstract fun getOperatingSystemVersion ()Ljava/lang/String;
public abstract fun getPropertyFromManifest (Ljava/lang/String;)Ljava/lang/String;
public abstract fun getRunMode ()Ljava/lang/String;
public abstract fun getSystemLocale ()Ljava/util/Locale;
public abstract fun registerOneTimeNetworkConnectionActiveListener (Lcom/adobe/marketing/mobile/services/DeviceInforming$NetworkConnectionActiveListener;)Z
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class DeviceInfoServiceTests {
ServiceProviderModifier.setAppContextService(MockAppContextService())
deviceInfoService = ServiceProvider.getInstance().deviceInfoService
assertNull(deviceInfoService.activeLocale)
assertTrue(deviceInfoService.systemLocale.displayLanguage.isNotEmpty())
assertNull(deviceInfoService.displayInformation)
assertEquals(
DeviceInforming.DeviceType.UNKNOWN,
Expand Down Expand Up @@ -73,6 +74,11 @@ class DeviceInfoServiceTests {
assertTrue(deviceInfoService.activeLocale.displayLanguage.isNotEmpty())
}

@Test
fun testGetSystemLocale() {
assertTrue(deviceInfoService.systemLocale.displayLanguage.isNotEmpty())
}

@Test
fun testGetCurrentOrientation() {
assertTrue(deviceInfoService.currentOrientation >= 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
package com.adobe.marketing.mobile.services;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import org.junit.After;
import org.junit.Assert;
Expand All @@ -25,19 +27,19 @@
@RunWith(AndroidJUnit4.class)
public class SqliteDataQueueTests {

private File dbFile;
private DataQueue dataQueue;
private static final String QUEUE_NAME = "test.dataQueue";

@Before
public void setUp() {
Context context = ApplicationProvider.getApplicationContext();
dbFile = context.getDatabasePath(QUEUE_NAME);
dataQueue = new SQLiteDataQueue(context.getDatabasePath(QUEUE_NAME).getPath());
}

@After
public void tearDown() {
Context context = ApplicationProvider.getApplicationContext();
File dbFile = getDatabase();
if (dbFile != null && dbFile.exists()) {
dbFile.delete();
}
Expand Down Expand Up @@ -98,4 +100,84 @@ public void testClear() {
List<DataEntity> results = dataQueue.peek(4);
Assert.assertEquals(0, results.size());
}

@Test
public void testAddToCorruptedDatabase() {
dataQueue.add(new DataEntity("test_data_1"));
dataQueue.add(new DataEntity("test_data_2"));
Assert.assertEquals(2, dataQueue.count());

corruptDatabase();
Assert.assertTrue(isDatabaseCorrupt());

// After detecting db is corrupt, resets the database and then adds the new entry.
Assert.assertTrue(dataQueue.add(new DataEntity("test_data_3")));
Assert.assertEquals(1, dataQueue.count());
Assert.assertEquals("test_data_3", dataQueue.peek().getData());
Assert.assertFalse(isDatabaseCorrupt());
}

@Test
public void testRemoveFromCorruptedDatabase() {
dataQueue.add(new DataEntity("test_data_1"));
dataQueue.add(new DataEntity("test_data_2"));
Assert.assertEquals(2, dataQueue.count());

corruptDatabase();
Assert.assertTrue(isDatabaseCorrupt());

// After detecting db is corrupt, resets the database.
Assert.assertFalse(dataQueue.remove());
Assert.assertEquals(0, dataQueue.count());
Assert.assertFalse(isDatabaseCorrupt());
}

@Test
public void testClearCorruptedDatabase() {
dataQueue.add(new DataEntity("test_data_1"));
dataQueue.add(new DataEntity("test_data_2"));
Assert.assertEquals(2, dataQueue.count());

corruptDatabase();
Assert.assertTrue(isDatabaseCorrupt());

// After detecting db is corrupt, resets the database.
Assert.assertTrue(dataQueue.clear());
Assert.assertEquals(0, dataQueue.count());
Assert.assertFalse(isDatabaseCorrupt());
}

private File getDatabase() {
Context context = ApplicationProvider.getApplicationContext();
return context.getDatabasePath(QUEUE_NAME);
}

private void corruptDatabase() {
File dbFile = getDatabase();
if (dbFile == null) {
return;
}
try {
FileOutputStream fos = new FileOutputStream(getDatabase());
fos.write(new byte[1024]);
fos.close();
} catch (Exception e) {

}
}

private boolean isDatabaseCorrupt() {
File dbFile = getDatabase();
if (dbFile == null) {
return true;
}
try {
SQLiteDatabase database =
SQLiteDatabase.openDatabase(
dbFile.getPath(), null, SQLiteDatabase.OPEN_READONLY);
return database == null || !database.isDatabaseIntegrityOk();
} catch (Exception e) {
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ package com.adobe.marketing.mobile.internal

internal object CoreConstants {
const val LOG_TAG = "MobileCore"
const val VERSION = "2.2.3"
const val VERSION = "2.3.0"

object EventDataKeys {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ internal class AppIdManager {
* @return the existing appId stored in shared preferences if it exists,
* null otherwise.
*/
private fun getAppIDFromPersistence(): String? {
internal fun getAppIDFromPersistence(): String? {
return configStateStoreCollection?.getString(
ConfigurationStateManager.PERSISTED_APPID,
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,14 @@ internal class ConfigurationExtension : Extension {
return
}

// Check if this is an internal request ovewriting explicit configure with appId request.
val isInternalEvent = DataReader.optBoolean(event.eventData, CONFIGURATION_REQUEST_CONTENT_IS_INTERNAL_EVENT, false)
if (isStaleAppIdUpdateRequest(appId, isInternalEvent)) {
Log.trace(TAG, TAG, "An explicit configure with AppId request has preceded this internal event.")
sharedStateResolver?.resolve(configurationStateManager.environmentAwareConfiguration)
return
}

// Stop all event processing for the extension until new configuration download is attempted
api.stopEvents()

Expand Down Expand Up @@ -540,4 +548,24 @@ internal class ConfigurationExtension : Extension {
}
}
}

/**
* Determines if the current AppID update request is stale.
* A request is considered stale if it is a configuration request sent internally
* and there is a newer request that has been sent externally via {@link MobileCore#configureWithAppId(String)}
*
* @param newAppId the new app ID with which the configuration update is being requested
* @param isInternalEvent whether the current request is an initial configuration request
* @return true if the current request is stale, false otherwise
*/
private fun isStaleAppIdUpdateRequest(newAppId: String, isInternalEvent: Boolean): Boolean {
// Because events are dispatched and processed serially, external config with app id events
// cannot be stale.
if (!isInternalEvent) return false

// Load the currently persisted app id for validation
val persistedAppId = appIdManager.getAppIDFromPersistence()

return !persistedAppId.isNullOrBlank() && newAppId != persistedAppId
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,20 @@ interface DisplayInformation {
String getApplicationVersionCode();

/**
* Returns the currently selected / active locale value (as set by the user on the system).
* Returns the currently selected / active locale value with respect to the application context.
*
* @return A {@link Locale} value, if available, null otherwise
*/
Locale getActiveLocale();

/**
* Returns the currently selected / active locale value on the device settings as set by the
* user.
*
* @return A {@link Locale} value, if available, null otherwise
*/
Locale getSystemLocale();

/**
* Returns information about the display hardware, as returned by the underlying OS.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ class DeviceInfoService implements DeviceInforming {
DeviceInfoService() {}

/**
* Returns the currently selected / active locale value (as set by the user on the system).
* Returns the currently selected / active locale value with respect to the application context.
*
* @return A {@link Locale} value, if available, null otherwise.
* @return A {@link Locale} value, if available, null otherwise
*/
public Locale getActiveLocale() {
final Context context = getApplicationContext();
Expand All @@ -56,23 +56,18 @@ public Locale getActiveLocale() {
return null;
}

final Resources resources = context.getResources();

if (resources == null) {
return null;
}

final Configuration configuration = resources.getConfiguration();

if (configuration == null) {
return null;
}
return getLocaleFromResources(context.getResources());
}

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
return configuration.locale;
} else {
return configuration.getLocales().get(0);
}
/**
* Returns the currently selected / active locale value on the device settings as set by the
* user.
*
* @return A {@link Locale} value, if available, null otherwise
*/
@Override
public Locale getSystemLocale() {
return getLocaleFromResources(Resources.getSystem());
}

@Override
Expand Down Expand Up @@ -581,6 +576,29 @@ public String getLocaleString() {
return result;
}

/**
* Returns the preferred locale value from the Resources object.
*
* @return A {@link Locale} value, if available, null otherwise
*/
private Locale getLocaleFromResources(final Resources resources) {
if (resources == null) {
return null;
}

final Configuration configuration = resources.getConfiguration();

if (configuration == null) {
return null;
}

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
return configuration.locale;
} else {
return configuration.getLocales().get(0);
}
}

/**
* Checks if a {@code String} is null, empty or it only contains whitespaces.
*
Expand Down
Loading

0 comments on commit 8195cbb

Please sign in to comment.