Skip to content
Closed
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: 2 additions & 0 deletions app/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ kt_android_library(
"//third_party:androidx_databinding_databinding-common",
"//third_party:androidx_databinding_databinding-runtime",
"//utility",
"//utility/src/main/java/org/oppia/android/util/enumfilter:enum_filter_util",
"//utility/src/main/java/org/oppia/android/util/extensions:context_extensions",
"//utility/src/main/java/org/oppia/android/util/logging/firebase:debug_module",
"//utility/src/main/java/org/oppia/android/util/math:fraction_parser",
Expand Down Expand Up @@ -677,6 +678,7 @@ kt_android_library(
"//third_party:org_jetbrains_kotlin_kotlin-stdlib-jdk8_jar",
"//utility",
"//utility/src/main/java/org/oppia/android/util/extensions:bundle_extensions",
"//utility/src/main/java/org/oppia/android/util/logging:current_app_screen_name_intent_decorator",
"//utility/src/main/java/org/oppia/android/util/parser/image:image_loader",
"//utility/src/main/java/org/oppia/android/util/parser/image:image_parsing_annonations",
"//utility/src/main/java/org/oppia/android/util/profile:current_user_profile_id_intent_decorator",
Expand Down
13 changes: 9 additions & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/OppiaTheme">
<!-- NOTE TO DEVELOPER: You can enable debug logs for fast upload & better inspection in Firebase console using https://support.google.com/analytics/answer/7201382. -->
<!-- NOTE TO DEVELOPER: You can enable debug logs for fast upload & better inspection in Firebase console by using this command: adb shell setprop debug.firebase.analytics.app org.oppia.android -->
<meta-data android:name="firebase_analytics_collection_deactivated" android:value="true" />
<meta-data android:name="firebase_crashlytics_collection_enabled" android:value="false" />
<meta-data
Expand Down Expand Up @@ -370,8 +370,13 @@
android:name=".app.testing.TextInputLayoutBindingAdaptersTestActivity"
android:theme="@style/OppiaThemeWithoutActionBar" />
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,29 @@ import android.app.Application
import androidx.appcompat.app.AppCompatActivity
import androidx.multidex.MultiDexApplication
import androidx.work.Configuration
import androidx.work.WorkManager
import com.google.firebase.FirebaseApp
import com.google.firebase.appcheck.AppCheckProviderFactory
import com.google.firebase.appcheck.FirebaseAppCheck
import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory
import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import org.oppia.android.app.activity.ActivityComponent
import org.oppia.android.app.activity.ActivityComponentFactory
import org.oppia.android.app.model.BuildFlavor
import org.oppia.android.domain.oppialogger.ApplicationStartupListener
import org.oppia.android.util.extensions.safeForEach

/** The root base [Application] of the Oppia app. */
/**
* The root base [Application] of the Oppia app.
*
* @param createComponentBuilder the [ApplicationComponent.Builder] used to construct the root
* Dagger class for the implementation's flavor of the app
* @property firebaseAppCheckProviderFactory the [AppCheckProviderFactory] used when initializing
* FirebaseAppCheck. This is defaulted for production use cases, but implementations may choose
* to provide a different one for improved debugging support.
*/
abstract class AbstractOppiaApplication(
createComponentBuilder: () -> ApplicationComponent.Builder
createComponentBuilder: () -> ApplicationComponent.Builder,
private val firebaseAppCheckProviderFactory: AppCheckProviderFactory =
PlayIntegrityAppCheckProviderFactory.getInstance()
) : MultiDexApplication(),
ActivityComponentFactory,
ApplicationInjectorProvider,
Expand All @@ -42,48 +48,40 @@ abstract class AbstractOppiaApplication(
override fun onCreate() {
super.onCreate()

// Platform parameter initialization must happen very early since even workers can use both
// feature flags and platform parameters.
component.getPlatformParameterController().loadParametersAsync().invokeOnCompletion { e ->
if (e != null) {
throw Exception("Failed to initialize platform parameters.", e)
}
// Allow startup listeners to early initialize.
val startupListeners = component.getApplicationStartupListeners()
startupListeners.forEach(ApplicationStartupListener::onCreateStarted)

// Initialize high-level third-party systems. Note that WorkManager doesn't need to be
// initialized here because it will automatically initialize itself due to the application being
// a Configuration provider.
FirebaseApp.initializeApp(applicationContext)
// FirebaseAppCheck protects our API resources from abuse. It works with Firebase
// services, Google Cloud services, and can also be implemented for our own APIs. See
// https://firebase.google.com/docs/app-check for currently supported Firebase products.
// Note that as of this code being checked in, only the app's Firestore usage is affected
// by App Check (Analytics is NOT affected).
FirebaseAppCheck.getInstance().installAppCheckProviderFactory(firebaseAppCheckProviderFactory)

// Continue initializing the startup state. Due to the asynchronous nature of platform
// parameter initialization, this happens after onCreate() finishes at the application level.
// This can introduce some inconsistencies in SplashActivity, though by the time
// SplashActivity completes the following should be fully initialized.
CoroutineScope(Dispatchers.Main).async {
FirebaseApp.initializeApp(applicationContext)
// FirebaseAppCheck protects our API resources from abuse. It works with Firebase
// services, Google Cloud services, and can also be implemented for our own APIs. See
// https://firebase.google.com/docs/app-check for currently supported Firebase products.
// Note that as of this code being checked in, only the app's Firestore usage is affected
// by App Check (Analytics is NOT affected).
if (component.getCurrentBuildFlavor() == BuildFlavor.DEVELOPER) {
FirebaseAppCheck.getInstance().installAppCheckProviderFactory(
DebugAppCheckProviderFactory.getInstance(),
)
} else {
FirebaseAppCheck.getInstance().installAppCheckProviderFactory(
PlayIntegrityAppCheckProviderFactory.getInstance(),
)
}
WorkManager.initialize(applicationContext, workManagerConfiguration)
val workManager = WorkManager.getInstance(applicationContext)
component.getAnalyticsStartupListenerStartupListeners().safeForEach {
it.onCreate(workManager)
}
component.getApplicationStartupListeners().forEach(ApplicationStartupListener::onCreate)
}.invokeOnCompletion {
if (it != null) {
throw Exception("Failed to continue application initialization.", it)
}
// Kick off a background task to finish startup initialization. Nothing at this stage should be
// startup-state sensitive. It's also fine for parameters to not be fully initialized at this
// point because each app entry point already accounts for potentially uninitialized parameters:
// splash, direct activity recreation, and waking up the app to kick off a worker.
CoroutineScope(component.getBackgroundDispatcher()).async {
// Wait for parameters to load before running any startup routines that may depend on them.
component.getPlatformParameterController().loadParametersAsync().await()
startupListeners.forEach(ApplicationStartupListener::onCompletedInitialization)
}.invokeOnCompletion { e ->
if (e != null) {
// NOTE TO DEVELOPERS: It's normally highly discouraged to throw in invokeOnCompletion
// because it muddies the error propagation state. However this is a case where the app
// cannot safely recover and it should absolutely hard fail because the alternative is a
// potentially inconsistent state.
throw Exception("Failed to finish app initialization.", e)
}
}
}

override fun getWorkManagerConfiguration(): Configuration {
return component.getWorkManagerConfiguration()
}
override fun getWorkManagerConfiguration(): Configuration =
component.getWorkManagerConfiguration()
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import android.app.Application
import androidx.work.Configuration
import dagger.BindsInstance
import org.oppia.android.app.activity.ActivityComponentImpl
import org.oppia.android.app.model.BuildFlavor
import org.oppia.android.domain.oppialogger.ApplicationStartupListener
import org.oppia.android.domain.oppialogger.analytics.AnalyticsStartupListener
import javax.inject.Provider

/**
Expand All @@ -28,9 +26,5 @@ interface ApplicationComponent : ApplicationInjector {

fun getApplicationStartupListeners(): Set<ApplicationStartupListener>

fun getAnalyticsStartupListenerStartupListeners(): Set<AnalyticsStartupListener>

fun getWorkManagerConfiguration(): Configuration

fun getCurrentBuildFlavor(): BuildFlavor
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ android_library(
"//domain/src/main/java/org/oppia/android/domain/oppialogger/logscheduler:metric_log_scheduler_module",
"//domain/src/main/java/org/oppia/android/domain/oppialogger/loguploader:worker_module",
"//domain/src/main/java/org/oppia/android/domain/platformparameter:prod_module",
"//domain/src/main/java/org/oppia/android/domain/workmanager:work_manager_configuration_module",
"//utility/src/main/java/org/oppia/android/util/accessibility:prod_module",
"//utility/src/main/java/org/oppia/android/util/caching:asset_prod_module",
"//utility/src/main/java/org/oppia/android/util/caching:caching_prod_module",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ import org.oppia.android.util.gcsresource.GcsResourceModule
import org.oppia.android.util.locale.LocaleProdModule
import org.oppia.android.util.logging.LoggerModule
import org.oppia.android.util.logging.SyncStatusModule
import org.oppia.android.util.logging.firebase.FirebaseLogUploaderModule
import org.oppia.android.util.logging.firebase.LogReportingModule
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAssessorModule
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsConfigurationsModule
Expand Down Expand Up @@ -85,7 +84,7 @@ import javax.inject.Singleton
RatioInputModule::class, UncaughtExceptionLoggerModule::class,
ApplicationStartupListenerModule::class, LogReportWorkerModule::class,
WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class,
FirebaseLogUploaderModule::class, RetrofitModule::class, RetrofitServiceModule::class,
RetrofitModule::class, RetrofitServiceModule::class,
PlatformParameterModule::class, PlatformParameterSingletonModule::class,
ExplorationStorageModule::class, DeveloperOptionsModule::class,
PlatformParameterSyncUpWorkerModule::class, NetworkConfigProdModule::class, AssetModule::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ import org.oppia.android.util.gcsresource.GcsResourceModule
import org.oppia.android.util.locale.LocaleProdModule
import org.oppia.android.util.logging.LoggerModule
import org.oppia.android.util.logging.SyncStatusModule
import org.oppia.android.util.logging.firebase.FirebaseLogUploaderModule
import org.oppia.android.util.logging.firebase.LogReportingModule
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAssessorModule
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsConfigurationsModule
Expand Down Expand Up @@ -85,7 +84,7 @@ import javax.inject.Singleton
RatioInputModule::class, UncaughtExceptionLoggerModule::class,
ApplicationStartupListenerModule::class, LogReportWorkerModule::class,
WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class,
FirebaseLogUploaderModule::class, RetrofitModule::class, RetrofitServiceModule::class,
RetrofitModule::class, RetrofitServiceModule::class,
PlatformParameterModule::class, PlatformParameterSingletonModule::class,
ExplorationStorageModule::class, DeveloperOptionsModule::class,
PlatformParameterSyncUpWorkerModule::class, NetworkConfigProdModule::class, AssetModule::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ kt_android_library(
"//app/src/main/java/org/oppia/android/app/application:common_application_modules",
"//domain/src/main/java/org/oppia/android/domain/auth:auth_module",
"//domain/src/main/java/org/oppia/android/domain/platformparameter:debug_module",
"//domain/src/main/java/org/oppia/android/domain/workmanager/debug:debug_module",
"//third_party:com_google_firebase_firebase-common",
"//utility/src/main/java/org/oppia/android/util/logging/firebase:debug_module",
"//utility/src/main/java/org/oppia/android/util/networking:debug_module",
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import org.oppia.android.domain.platformparameter.PlatformParameterSingletonModu
import org.oppia.android.domain.platformparameter.syncup.PlatformParameterSyncUpWorkerModule
import org.oppia.android.domain.question.QuestionModule
import org.oppia.android.domain.workmanager.WorkManagerConfigurationModule
import org.oppia.android.domain.workmanager.debug.DebugWorkerDebugModule
import org.oppia.android.util.accessibility.AccessibilityProdModule
import org.oppia.android.util.caching.AssetModule
import org.oppia.android.util.caching.CachingModule
Expand All @@ -54,7 +55,6 @@ import org.oppia.android.util.locale.LocaleProdModule
import org.oppia.android.util.logging.LoggerModule
import org.oppia.android.util.logging.SyncStatusModule
import org.oppia.android.util.logging.firebase.DebugLogReportingModule
import org.oppia.android.util.logging.firebase.FirebaseLogUploaderModule
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAssessorModule
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsConfigurationsModule
import org.oppia.android.util.networking.NetworkConnectionDebugUtilModule
Expand Down Expand Up @@ -87,7 +87,7 @@ import javax.inject.Singleton
UncaughtExceptionLoggerModule::class, ApplicationStartupListenerModule::class,
LogReportWorkerModule::class, WorkManagerConfigurationModule::class,
HintsAndSolutionConfigModule::class, HintsAndSolutionDebugModule::class,
FirebaseLogUploaderModule::class, RetrofitModule::class, RetrofitServiceModule::class,
RetrofitModule::class, RetrofitServiceModule::class,
PlatformParameterSingletonModule::class, PlatformParameterDebugModule::class,
ExplorationStorageModule::class, DeveloperOptionsStarterModule::class,
DeveloperOptionsModule::class, PlatformParameterSyncUpWorkerModule::class,
Expand All @@ -101,7 +101,7 @@ import javax.inject.Singleton
PerformanceMetricsAssessorModule::class, PerformanceMetricsConfigurationsModule::class,
DeveloperBuildFlavorModule::class,
CpuPerformanceSnapshotterModule::class, ExplorationProgressModule::class,
AuthenticationModule::class
AuthenticationModule::class, DebugWorkerDebugModule::class
]
)
interface DeveloperApplicationComponent : ApplicationComponent {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.oppia.android.app.application.dev

import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory
import org.oppia.android.app.application.AbstractOppiaApplication

/** The root [AbstractOppiaApplication] for developer builds of the Oppia app. */
class DeveloperOppiaApplication : AbstractOppiaApplication(
DaggerDeveloperApplicationComponent::builder
DaggerDeveloperApplicationComponent::builder,
firebaseAppCheckProviderFactory = DebugAppCheckProviderFactory.getInstance()
)
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ import org.oppia.android.util.gcsresource.GcsResourceModule
import org.oppia.android.util.locale.LocaleProdModule
import org.oppia.android.util.logging.LoggerModule
import org.oppia.android.util.logging.SyncStatusModule
import org.oppia.android.util.logging.firebase.FirebaseLogUploaderModule
import org.oppia.android.util.logging.firebase.LogReportingModule
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsAssessorModule
import org.oppia.android.util.logging.performancemetrics.PerformanceMetricsConfigurationsModule
Expand Down Expand Up @@ -85,7 +84,7 @@ import javax.inject.Singleton
RatioInputModule::class, UncaughtExceptionLoggerModule::class,
ApplicationStartupListenerModule::class, LogReportWorkerModule::class,
WorkManagerConfigurationModule::class, HintsAndSolutionConfigModule::class,
FirebaseLogUploaderModule::class, RetrofitModule::class, RetrofitServiceModule::class,
RetrofitModule::class, RetrofitServiceModule::class,
PlatformParameterModule::class, PlatformParameterSingletonModule::class,
ExplorationStorageModule::class, DeveloperOptionsModule::class,
PlatformParameterSyncUpWorkerModule::class, NetworkConfigProdModule::class, AssetModule::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ import org.oppia.android.domain.hintsandsolution.HintsAndSolutionProdModule
import org.oppia.android.domain.onboarding.ExpirationMetaDataRetrieverModule
import org.oppia.android.domain.oppialogger.LogStorageModule
import org.oppia.android.domain.oppialogger.LoggingIdentifierModule
import org.oppia.android.domain.oppialogger.analytics.AnalyticsStartupListener
import org.oppia.android.domain.oppialogger.analytics.ApplicationLifecycleModule
import org.oppia.android.domain.oppialogger.analytics.CpuPerformanceSnapshotterModule
import org.oppia.android.domain.platformparameter.PlatformParameterSingletonModule
import org.oppia.android.domain.question.QuestionModule
import org.oppia.android.domain.workmanager.StartupWorkerScheduleReadinessListener
import org.oppia.android.domain.workmanager.WorkManagerConfigurationModule
import org.oppia.android.testing.TestLogReportingModule
import org.oppia.android.testing.firebase.TestAuthenticationModule
Expand Down Expand Up @@ -206,9 +206,9 @@ class DateTimeUtilTest {
}

@Module
interface AnalyticsStartupListenerTestModule {
interface StartupWorkerScheduleReadinessListenerTestModule {
@Multibinds
fun provideAnalyticsListenerSet(): Set<AnalyticsStartupListener>
fun provideAnalyticsListenerSet(): Set<StartupWorkerScheduleReadinessListener>
}

// TODO(#89): Move this to a common test application component.
Expand All @@ -219,7 +219,7 @@ class DateTimeUtilTest {
ActivityRecreatorTestModule::class,
ActivityRouterModule::class,
AlgebraicExpressionInputModule::class,
AnalyticsStartupListenerTestModule::class,
StartupWorkerScheduleReadinessListenerTestModule::class,
ApplicationLifecycleModule::class,
ApplicationModule::class,
ApplicationStartupListenerModule::class,
Expand Down
Loading
Loading