diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 760a4491d7e9cfc545b2719359defa09711bc934..753b2e3da48589c6e536f16c08564ee4c49d72ed 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -122,6 +122,18 @@ lintRelease:
- app/build/reports/
- build/reports/
+
+publish-authdatalib:
+ stage: publish
+ needs: ["buildRelease"]
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+ when: manual
+ script:
+ - ./gradlew :auth-data-lib:build
+ - ./gradlew :auth-data-lib:publish
+
+
pushToPrebuilt:
stage: publish
needs: ["buildRelease"]
@@ -169,4 +181,4 @@ publish-contracts:
when: always
script:
- ./gradlew :parental-control-data:build
- - ./gradlew :parental-control-data:publish
\ No newline at end of file
+ - ./gradlew :parental-control-data:publish
diff --git a/app/build.gradle b/app/build.gradle
index 1a99d04ac271b2397b4e1609220a6888311ce89d..55fbbbe80f6fb0c6baf0f57975d50bb199e8c4b3 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -159,8 +159,10 @@ allOpen {
dependencies {
+ implementation project(':auth-data-lib')
implementation project(':parental-control-data')
-// TODO: Add splitinstall-lib to a repo https://gitlab.e.foundation/e/os/backlog/-/issues/628
+
+ // TODO: Add splitinstall-lib to a repo https://gitlab.e.foundation/e/os/backlog/-/issues/628
api files('libs/splitinstall-lib.jar')
implementation 'foundation.e.lib:telemetry:0.0.11-alpha'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8042f9d891b9111886d9f9659dece38ed61623ae..fd674630d836a58d3b258ccacbfc0c7df0031867 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -20,6 +20,10 @@
+
+
@@ -167,6 +171,13 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/foundation/e/apps/microg/AuthDataProvider.kt b/app/src/main/java/foundation/e/apps/microg/AuthDataProvider.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0e914479ffc7cc4e1feea1c0f318c70570d8b070
--- /dev/null
+++ b/app/src/main/java/foundation/e/apps/microg/AuthDataProvider.kt
@@ -0,0 +1,119 @@
+/*
+ * Apps Quickly and easily install Android apps onto your device!
+ * Copyright (C) 2024 E FOUNDATION
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package foundation.e.apps.microg
+
+import android.content.ContentProvider
+import android.content.ContentValues
+import android.content.pm.PackageManager
+import android.database.Cursor
+import android.database.MatrixCursor
+import android.net.Uri
+import dagger.hilt.EntryPoint
+import dagger.hilt.InstallIn
+import dagger.hilt.android.EntryPointAccessors
+import dagger.hilt.components.SingletonComponent
+import foundation.e.apps.authdata.AuthDataContract
+import foundation.e.apps.data.preference.DataStoreManager
+
+/**
+ * Content provider dedicated to share the Google auth data with
+ * other applications. Other applications need to own the following permission:
+ * `foundation.e.apps.permission.AUTH_DATA_PROVIDER`
+ */
+class AuthDataProvider : ContentProvider() {
+
+ @EntryPoint
+ @InstallIn(SingletonComponent::class)
+ interface DataStoreManagerEntryPoint {
+ fun provideDataStoreManager(): DataStoreManager
+ }
+
+ private lateinit var dataStoreManager: DataStoreManager
+
+ override fun onCreate(): Boolean {
+ val context = context ?: return false
+
+ val dataStoreEntryPoint = EntryPointAccessors.fromApplication(
+ context.applicationContext,
+ DataStoreManagerEntryPoint::class.java
+ )
+
+ dataStoreManager = dataStoreEntryPoint.provideDataStoreManager()
+ return true
+ }
+
+ override fun query(uri: Uri, projection: Array?, selection: String?,
+ selectionArgs: Array?, sortOrder: String?): Cursor {
+
+ if (context?.checkCallingOrSelfPermission(
+ AUTH_DATA_PROVIDER_PERMISSION
+ ) != PackageManager.PERMISSION_GRANTED) {
+ throw SecurityException("Permission denied: $AUTH_DATA_PROVIDER_PERMISSION required")
+ }
+
+ val cursor = MatrixCursor(
+ arrayOf(
+ AuthDataContract.EMAIL_KEY,
+ AuthDataContract.AUTH_TOKEN_KEY,
+ AuthDataContract.GSF_ID_KEY,
+ AuthDataContract.CONSISTENCY_TOKEN_KEY,
+ AuthDataContract.DEVICE_CONFIG_TOKEN_KEY,
+ AuthDataContract.EXPERIMENTS_CONFIG_TOKEN_KEY,
+ AuthDataContract.DFE_COOKIE_KEY
+ )
+ )
+
+ val row = cursor.newRow()
+ dataStoreManager.getAuthData().let {
+ row.add(AuthDataContract.EMAIL_KEY, it.email)
+ row.add(AuthDataContract.AUTH_TOKEN_KEY, it.authToken)
+ row.add(AuthDataContract.GSF_ID_KEY, it.gsfId)
+ row.add(AuthDataContract.CONSISTENCY_TOKEN_KEY, it.deviceCheckInConsistencyToken)
+ row.add(AuthDataContract.DEVICE_CONFIG_TOKEN_KEY, it.deviceConfigToken)
+ row.add(AuthDataContract.EXPERIMENTS_CONFIG_TOKEN_KEY, it.experimentsConfigToken)
+ row.add(AuthDataContract.DFE_COOKIE_KEY, it.dfeCookie)
+ }
+
+ cursor.setNotificationUri(context?.contentResolver, uri)
+
+ return cursor
+ }
+
+ override fun update(uri: Uri, values: ContentValues?, selection: String?,
+ selectionArgs: Array?): Int {
+ throw UnsupportedOperationException("Update operation is not supported by the provider")
+ }
+
+ override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int {
+ throw UnsupportedOperationException("Delete operation is not supported by the provider")
+ }
+
+ override fun getType(uri: Uri): String? {
+ return "vnd.android.cursor.dir/vnd.foundation.e.apps.authdata.provider.strings";
+ }
+
+ override fun insert(uri: Uri, values: ContentValues?): Uri {
+ throw UnsupportedOperationException("Insert operation is not supported by the provider")
+ }
+
+ companion object {
+ const val AUTH_DATA_PROVIDER_PERMISSION = "foundation.e.apps.permission.AUTH_DATA_PROVIDER"
+ }
+}
+
diff --git a/auth-data-lib/.gitignore b/auth-data-lib/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..42afabfd2abebf31384ca7797186a27a4b7dbee8
--- /dev/null
+++ b/auth-data-lib/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/auth-data-lib/build.gradle b/auth-data-lib/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..3d3319ef19df61e5b7ec985628e74fa000a7aa2e
--- /dev/null
+++ b/auth-data-lib/build.gradle
@@ -0,0 +1,48 @@
+plugins {
+ id 'java-library'
+ id 'org.jetbrains.kotlin.jvm'
+ id 'maven-publish'
+}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+}
+
+publishing {
+ publications {
+ jar(MavenPublication) {
+ groupId = 'foundation.e.apps'
+ artifactId = 'auth-data-lib'
+ version = '1.0.0'
+
+ artifact("$buildDir/libs/${project.name}.jar")
+
+ pom {
+ name = 'AuthDataLib'
+ description = 'Library providing AuthData through a content provider'
+
+ licenses {
+ license {
+ name = 'The Apache Software License, Version 2.0'
+ url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+ }
+ }
+ }
+ }
+ }
+
+ repositories {
+ maven {
+ name = "GitLab"
+ url = uri("https://gitlab.e.foundation/api/v4/projects/355/packages/maven")
+ credentials(HttpHeaderCredentials) {
+ name = "Job-Token"
+ value = System.getenv("CI_JOB_TOKEN")
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/auth-data-lib/src/main/java/foundation/e/apps/authdata/AuthDataContract.kt b/auth-data-lib/src/main/java/foundation/e/apps/authdata/AuthDataContract.kt
new file mode 100644
index 0000000000000000000000000000000000000000..af0bc115db4c5a2d9fa4db4bf831a2031e52488f
--- /dev/null
+++ b/auth-data-lib/src/main/java/foundation/e/apps/authdata/AuthDataContract.kt
@@ -0,0 +1,11 @@
+package foundation.e.apps.authdata
+
+object AuthDataContract {
+ const val EMAIL_KEY = "email"
+ const val AUTH_TOKEN_KEY = "authToken"
+ const val GSF_ID_KEY = "gsfId"
+ const val CONSISTENCY_TOKEN_KEY = "consistencyToken"
+ const val DEVICE_CONFIG_TOKEN_KEY = "deviceConfigToken"
+ const val EXPERIMENTS_CONFIG_TOKEN_KEY = "experimentsConfigToken"
+ const val DFE_COOKIE_KEY = "dfeCookie"
+}
diff --git a/settings.gradle b/settings.gradle
index 31d7da316f152118ee57fb4f44be9ec551b02f5a..d222ecead54060f5591fbd36ce0d55b64a402b2e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -63,3 +63,4 @@ dependencyResolutionManagement {
rootProject.name = "App Lounge"
include ':app'
include ':parental-control-data'
+include ':auth-data-lib'