Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/build-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'adopt'
java-version: '11'
java-version: '17'
- name: Remove default github maven configuration
# Workaround for: 'Unable to decrypt local Maven settings credentials'
run: rm $Env:USERPROFILE\.m2\settings.xml
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'adopt'
java-version: '11'
java-version: '17'
- name: Remove default github maven configuration
run: rm $Env:USERPROFILE\.m2\settings.xml
- name: Setup Android SDK
Expand Down
4 changes: 2 additions & 2 deletions lib/android_build/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':maesdk')
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test.ext:junit:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,20 @@
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

@RunWith(AndroidJUnit4.class)
public class OfflineRoomUnitTest {
Expand All @@ -41,7 +51,14 @@ public void storeOneRecord() {
room.storeRecords(record);
assertEquals(1, room.getRecordCount(StorageRecord.EventLatency_Unspecified));
assertEquals(1, room.getRecordCount(StorageRecord.EventLatency_Normal));
assertThat(room.totalSize(), Matchers.greaterThan(new Long(0)));
assertThat(room.totalSize(), Matchers.greaterThan(0L));

// Verify loadPageSize() returns a valid page size
long pageSize = room.loadPageSize();
assertThat(pageSize, Matchers.greaterThan(0L));
// Verify page size is a power of 2 (e.g., 4096)
assertThat(pageSize & (pageSize - 1), Matchers.is(0L));

assertEquals(1, room.deleteAllRecords());
}
}
Expand Down Expand Up @@ -177,5 +194,94 @@ public void RetireRetries() {
}
}
}

@Test
public void ConcurrentPageSizeInitialization() throws InterruptedException {
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
try (OfflineRoom room = new OfflineRoom(appContext, "OfflineRoomConcurrent")) {
room.deleteAllRecords();

// Add a record to ensure the database is not empty
StorageRecord record = new StorageRecord(
0, "Test",
StorageRecord.EventLatency_Normal,
StorageRecord.EventPersistence_Normal,
32,
1,
0,
new byte[]{1, 2, 3});
room.storeRecords(record);

final int threadCount = 10;
final CountDownLatch startLatch = new CountDownLatch(1);
final CountDownLatch doneLatch = new CountDownLatch(threadCount);
final List<Long> pageSizes = new ArrayList<>();
final List<Long> totalSizes = new ArrayList<>();
final AtomicInteger errorCount = new AtomicInteger(0);

// Use ExecutorService for proper thread management
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
try {
// Submit tasks that will call loadPageSize() and totalSize() concurrently
for (int i = 0; i < threadCount; i++) {
executor.submit(() -> {
try {
// Wait for all threads to be ready
startLatch.await();

// Call both methods to test concurrent initialization
long pageSize = room.loadPageSize();
long totalSize = room.totalSize();

synchronized (pageSizes) {
pageSizes.add(pageSize);
totalSizes.add(totalSize);
}
} catch (Exception e) {
errorCount.incrementAndGet();
e.printStackTrace();
} finally {
doneLatch.countDown();
}
});
}

// Start all threads simultaneously
startLatch.countDown();

// Wait for all threads to complete
doneLatch.await();
} finally {
// Ensure executor is properly shut down
executor.shutdown();
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
}

// Verify no errors occurred
assertEquals("No errors should occur during concurrent access", 0, errorCount.get());

// Verify all threads got results
assertEquals("All threads should complete", threadCount, pageSizes.size());
assertEquals("All threads should complete", threadCount, totalSizes.size());

// Verify all threads got the same page size (no race condition)
long firstPageSize = pageSizes.get(0);
assertThat("Page size should be valid", firstPageSize, greaterThan(0L));
assertThat("Page size should be a power of 2", firstPageSize & (firstPageSize - 1), is(0L));

for (long pageSize : pageSizes) {
assertEquals("All threads should get the same page size", firstPageSize, pageSize);
}

// Verify all threads got a valid total size
for (long totalSize : totalSizes) {
assertThat("Total size should be valid", totalSize, greaterThan(0L));
}

room.deleteAllRecords();
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ public void resumingAlsoEnds() {
@Test
public void runNativeTests() {
System.loadLibrary("native-lib");
System.loadLibrary("maesdk");

Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
HttpClient client = new HttpClient(appContext);
Expand Down
9 changes: 4 additions & 5 deletions lib/android_build/app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

string(REPLACE "/lib/android_build/app/src/main/cpp" "" SDK_ROOT ${CMAKE_SOURCE_DIR})

Expand Down Expand Up @@ -81,10 +82,8 @@ include_directories(

find_library(zlib-path z)

add_library(maesdk SHARED IMPORTED)
set_target_properties(maesdk PROPERTIES
IMPORTED_LOCATION "${SDK_ROOT}/lib/android_build/maesdk/build/intermediates/cmake/debug/obj/${CMAKE_ANDROID_ARCH_ABI}/libmaesdk.so"
IMPORTED_LOCATION_Release "${SDK_ROOT}/lib/android_build/maesdk/build/intermediates/cmake/debug/obj/${CMAKE_ANDROID_ARCH_ABI}/libmaesdk.so")
#Add maesdk as a dependency
add_subdirectory(../../../../maesdk/src/main/cpp maesdk)
Copy link
Contributor

@lalitb lalitb Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will create the maesdk library, is this intended ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will build maesdk as part of test app
Currently running test app fails because maesdk library wasn't built when evaluating CmakeLists.
This avoids need to build it separately


# include the other flavor of database: if maesdk builds with Room include sqlite
# if maesdk builds with native sqlite, include Room
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ void log_failure(String filename, int line, String summary) {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
System.loadLibrary("maesdk");
}

HttpClient m_client;
Expand Down
2 changes: 1 addition & 1 deletion lib/android_build/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath 'com.android.tools.build:gradle:8.2.2'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Expand Down
Binary file modified lib/android_build/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 3 additions & 2 deletions lib/android_build/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#Wed Feb 01 08:36:33 EET 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
41 changes: 28 additions & 13 deletions lib/android_build/gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 9 additions & 6 deletions lib/android_build/gradlew.bat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions lib/android_build/maesdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ android {
arguments = [
"room.schemaLocation":"$projectDir/schemas".toString(),
"room.incremental":"true",
"room.expandProjection":"true"]
"room.expandProjection":"true",
"room.generateKotlin":"false"]
}
}
}
Expand Down Expand Up @@ -72,14 +73,14 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

def room_version = '2.4.3'
def room_version = '2.8.4'

implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"

testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:5.13.0'
testImplementation 'org.mockito:mockito-core:5.17.0'
testImplementation "androidx.room:room-testing:$room_version"
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test.ext:junit:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'
}
3 changes: 2 additions & 1 deletion lib/android_build/maesdk/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.10.2)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Enable Azure Monitor / Application Insights end-point support
option(BUILD_AZMON "Build for Azure Monitor" YES)
Expand Down
Loading
Loading