Merge pull request #6300 from vector-im/feature/bma/flipper

Setup Flipper
This commit is contained in:
Benoit Marty 2022-06-16 16:44:05 +02:00 committed by GitHub
commit fe7515761a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 380 additions and 36 deletions

1
changelog.d/6300.misc Normal file
View file

@ -0,0 +1 @@
Setup [Flipper](https://fbflipper.com/)

View file

@ -32,6 +32,7 @@ ext.groups = [
], ],
group: [ group: [
'com.android', 'com.android',
'com.android.ndk.thirdparty',
'com.android.tools', 'com.android.tools',
'com.google.firebase', 'com.google.firebase',
'com.google.testing.platform', 'com.google.testing.platform',
@ -53,6 +54,7 @@ ext.groups = [
'com.dropbox.core', 'com.dropbox.core',
'com.soywiz.korlibs.korte', 'com.soywiz.korlibs.korte',
'com.facebook.fbjni', 'com.facebook.fbjni',
'com.facebook.flipper',
'com.facebook.fresco', 'com.facebook.fresco',
'com.facebook.infer.annotation', 'com.facebook.infer.annotation',
'com.facebook.soloader', 'com.facebook.soloader',
@ -94,6 +96,7 @@ ext.groups = [
'com.ibm.icu', 'com.ibm.icu',
'com.jakewharton.android.repackaged', 'com.jakewharton.android.repackaged',
'com.jakewharton.timber', 'com.jakewharton.timber',
'com.kgurgul.flipper',
'com.linkedin.dexmaker', 'com.linkedin.dexmaker',
'com.mapbox.mapboxsdk', 'com.mapbox.mapboxsdk',
'com.nulab-inc', 'com.nulab-inc',
@ -169,6 +172,7 @@ ext.groups = [
'org.glassfish.jaxb', 'org.glassfish.jaxb',
'org.hamcrest', 'org.hamcrest',
'org.jacoco', 'org.jacoco',
'org.java-websocket',
'org.jetbrains', 'org.jetbrains',
'org.jetbrains.dokka', 'org.jetbrains.dokka',
'org.jetbrains.intellij.deps', 'org.jetbrains.intellij.deps',

57
docs/flipper.md Normal file
View file

@ -0,0 +1,57 @@
# Flipper
<!--- TOC -->
* [Introduction](#introduction)
* [Setup](#setup)
* [Troubleshoot](#troubleshoot)
* [No device found issue](#no-device-found-issue)
* [Diagnostic Activity](#diagnostic-activity)
* [Other](#other)
* [Links](#links)
<!--- END -->
## Introduction
[Flipper](https://fbflipper.com) is a powerful tool from Meta, which allow to inspect the running application details and states from your computer.
Flipper is configured in the Element Android project to let the developers be able to:
- inspect all the Realm databases content;
- do layout inspection;
- see the crash logs;
- see the logcat;
- see all the network requests;
- see all the SharedPreferences;
- take screenshots and record videos of the device;
- and more!
## Setup
- Install Flipper on your computer. Follow instructions here: https://fbflipper.com/docs/getting-started/index/
- Run the debug version of Element on an emulator or on a real device.
### Troubleshoot
#### No device found issue
The configuration of the Flipper application has to be updated. The issue has been asked and answered here: https://stackoverflow.com/questions/71744103/android-emulator-unable-to-connect-to-flipper/72608113#72608113
#### Diagnostic Activity
Flipper comes with a Diagnostic Activity that you can start from command line using:
```shell
adb shell am start -n im.vector.app.debug/com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity
```
It provides some log which can help to figure out what's going on client side.
#### Other
https://fbflipper.com/docs/getting-started/troubleshooting/android/ may help.
## Links
- https://fbflipper.com
- Realm Plugin for Flipper: https://github.com/kamgurgul/Flipper-Realm

View file

@ -21,6 +21,7 @@ import dagger.BindsInstance
import dagger.Component import dagger.Component
import org.matrix.android.sdk.api.MatrixConfiguration import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.internal.auth.AuthModule import org.matrix.android.sdk.internal.auth.AuthModule
import org.matrix.android.sdk.internal.debug.DebugModule
import org.matrix.android.sdk.internal.di.MatrixComponent import org.matrix.android.sdk.internal.di.MatrixComponent
import org.matrix.android.sdk.internal.di.MatrixModule import org.matrix.android.sdk.internal.di.MatrixModule
import org.matrix.android.sdk.internal.di.MatrixScope import org.matrix.android.sdk.internal.di.MatrixScope
@ -36,6 +37,7 @@ import org.matrix.android.sdk.internal.util.system.SystemModule
NetworkModule::class, NetworkModule::class,
AuthModule::class, AuthModule::class,
RawModule::class, RawModule::class,
DebugModule::class,
SettingsModule::class, SettingsModule::class,
SystemModule::class SystemModule::class
] ]

View file

@ -25,6 +25,7 @@ import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.BuildConfig import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.debug.DebugService
import org.matrix.android.sdk.api.legacy.LegacySessionImporter import org.matrix.android.sdk.api.legacy.LegacySessionImporter
import org.matrix.android.sdk.api.network.ApiInterceptorListener import org.matrix.android.sdk.api.network.ApiInterceptorListener
import org.matrix.android.sdk.api.network.ApiPath import org.matrix.android.sdk.api.network.ApiPath
@ -54,6 +55,7 @@ class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
@Inject internal lateinit var legacySessionImporter: LegacySessionImporter @Inject internal lateinit var legacySessionImporter: LegacySessionImporter
@Inject internal lateinit var authenticationService: AuthenticationService @Inject internal lateinit var authenticationService: AuthenticationService
@Inject internal lateinit var rawService: RawService @Inject internal lateinit var rawService: RawService
@Inject internal lateinit var debugService: DebugService
@Inject internal lateinit var userAgentHolder: UserAgentHolder @Inject internal lateinit var userAgentHolder: UserAgentHolder
@Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver @Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver
@Inject internal lateinit var olmManager: OlmManager @Inject internal lateinit var olmManager: OlmManager
@ -93,6 +95,11 @@ class Matrix(context: Context, matrixConfiguration: MatrixConfiguration) {
*/ */
fun rawService() = rawService fun rawService() = rawService
/**
* Return the DebugService.
*/
fun debugService() = debugService
/** /**
* Return the LightweightSettingsStorage. * Return the LightweightSettingsStorage.
*/ */

View file

@ -17,6 +17,7 @@
package org.matrix.android.sdk.api package org.matrix.android.sdk.api
import okhttp3.ConnectionSpec import okhttp3.ConnectionSpec
import okhttp3.Interceptor
import org.matrix.android.sdk.api.crypto.MXCryptoConfig import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import java.net.Proxy import java.net.Proxy
@ -65,4 +66,8 @@ data class MatrixConfiguration(
* Thread messages default enable/disabled value. * Thread messages default enable/disabled value.
*/ */
val threadMessagesEnabledDefault: Boolean = false, val threadMessagesEnabledDefault: Boolean = false,
/**
* List of network interceptors, they will be added when building an OkHttp client.
*/
val networkInterceptors: List<Interceptor> = emptyList(),
) )

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
*
* Licensed 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 CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.api.debug
import io.realm.RealmConfiguration
/**
* Useful methods to access to some private data managed by the SDK.
*/
interface DebugService {
/**
* Get all the available Realm Configuration.
*/
fun getAllRealmConfigurations(): List<RealmConfiguration>
/**
* Prints out info on DB size to logcat.
*/
fun logDbUsageInfo()
}

View file

@ -17,6 +17,7 @@
package org.matrix.android.sdk.api.session package org.matrix.android.sdk.api.session
import androidx.annotation.MainThread import androidx.annotation.MainThread
import io.realm.RealmConfiguration
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.auth.data.SessionParams import org.matrix.android.sdk.api.auth.data.SessionParams
@ -334,7 +335,12 @@ interface Session {
fun getUiaSsoFallbackUrl(authenticationSessionId: String): String fun getUiaSsoFallbackUrl(authenticationSessionId: String): String
/** /**
* Maintenance API, allows to print outs info on DB size to logcat. * Debug API, will print out info on DB size to logcat.
*/ */
fun logDbUsageInfo() fun logDbUsageInfo()
/**
* Debug API, return the list of all RealmConfiguration used by this session.
*/
fun getRealmConfigurations(): List<RealmConfiguration>
} }

View file

@ -171,8 +171,6 @@ interface CryptoService {
fun getSharedWithInfo(roomId: String?, sessionId: String): MXUsersDevicesMap<Int> fun getSharedWithInfo(roomId: String?, sessionId: String): MXUsersDevicesMap<Int>
fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent? fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent?
fun logDbUsageInfo()
/** /**
* Perform any background tasks that can be done before a message is ready to * Perform any background tasks that can be done before a message is ready to
* send, in order to speed up sending of the message. * send, in order to speed up sending of the message.

View file

@ -40,6 +40,13 @@ internal class SessionManager @Inject constructor(
return getOrCreateSessionComponent(sessionParams) return getOrCreateSessionComponent(sessionParams)
} }
fun getLastSession(): Session? {
val sessionParams = sessionParamsStore.getLast()
return sessionParams?.let {
getOrCreateSession(it)
}
}
fun getOrCreateSession(sessionParams: SessionParams): Session { fun getOrCreateSession(sessionParams: SessionParams): Session {
return getOrCreateSessionComponent(sessionParams).session() return getOrCreateSessionComponent(sessionParams).session()
} }

View file

@ -73,10 +73,7 @@ internal class DefaultAuthenticationService @Inject constructor(
} }
override fun getLastAuthenticatedSession(): Session? { override fun getLastAuthenticatedSession(): Session? {
val sessionParams = sessionParamsStore.getLast() return sessionManager.getLastSession()
return sessionParams?.let {
sessionManager.getOrCreateSession(it)
}
} }
override suspend fun getLoginFlowOfSession(sessionId: String): LoginFlowResult { override suspend fun getLoginFlowOfSession(sessionId: String): LoginFlowResult {

View file

@ -1298,10 +1298,6 @@ internal class DefaultCryptoService @Inject constructor(
return cryptoStore.getWithHeldMegolmSession(roomId, sessionId) return cryptoStore.getWithHeldMegolmSession(roomId, sessionId)
} }
override fun logDbUsageInfo() {
cryptoStore.logDbUsageInfo()
}
override fun prepareToEncrypt(roomId: String, callback: MatrixCallback<Unit>) { override fun prepareToEncrypt(roomId: String, callback: MatrixCallback<Unit>) {
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
Timber.tag(loggerTag.value).d("prepareToEncrypt() roomId:$roomId Check room members up to date") Timber.tag(loggerTag.value).d("prepareToEncrypt() roomId:$roomId Check room members up to date")

View file

@ -513,6 +513,5 @@ internal interface IMXCryptoStore {
fun setDeviceKeysUploaded(uploaded: Boolean) fun setDeviceKeysUploaded(uploaded: Boolean)
fun areDeviceKeysUploaded(): Boolean fun areDeviceKeysUploaded(): Boolean
fun tidyUpDataBase() fun tidyUpDataBase()
fun logDbUsageInfo()
fun getOutgoingRoomKeyRequests(inStates: Set<OutgoingRoomKeyRequestState>): List<OutgoingKeyRequest> fun getOutgoingRoomKeyRequests(inStates: Set<OutgoingRoomKeyRequestState>): List<OutgoingKeyRequest>
} }

View file

@ -88,7 +88,6 @@ import org.matrix.android.sdk.internal.crypto.store.db.query.get
import org.matrix.android.sdk.internal.crypto.store.db.query.getById import org.matrix.android.sdk.internal.crypto.store.db.query.getById
import org.matrix.android.sdk.internal.crypto.store.db.query.getOrCreate import org.matrix.android.sdk.internal.crypto.store.db.query.getOrCreate
import org.matrix.android.sdk.internal.crypto.util.RequestIdHelper import org.matrix.android.sdk.internal.crypto.util.RequestIdHelper
import org.matrix.android.sdk.internal.database.tools.RealmDebugTools
import org.matrix.android.sdk.internal.di.CryptoDatabase import org.matrix.android.sdk.internal.di.CryptoDatabase
import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.di.DeviceId
import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.MoshiProvider
@ -1709,11 +1708,4 @@ internal class RealmCryptoStore @Inject constructor(
// Can we do something for WithHeldSessionEntity? // Can we do something for WithHeldSessionEntity?
} }
} }
/**
* Prints out database info.
*/
override fun logDbUsageInfo() {
RealmDebugTools(realmConfiguration).logInfo("Crypto")
}
} }

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
*
* Licensed 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 CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.matrix.android.sdk.internal.debug
import dagger.Binds
import dagger.Module
import org.matrix.android.sdk.api.debug.DebugService
@Module
internal abstract class DebugModule {
@Binds
abstract fun bindDebugService(service: DefaultDebugService): DebugService
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
*
* Licensed 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 CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.debug
import io.realm.RealmConfiguration
import org.matrix.android.sdk.api.debug.DebugService
import org.matrix.android.sdk.internal.SessionManager
import org.matrix.android.sdk.internal.database.tools.RealmDebugTools
import org.matrix.android.sdk.internal.di.AuthDatabase
import org.matrix.android.sdk.internal.di.GlobalDatabase
import javax.inject.Inject
internal class DefaultDebugService @Inject constructor(
@AuthDatabase private val realmConfigurationAuth: RealmConfiguration,
@GlobalDatabase private val realmConfigurationGlobal: RealmConfiguration,
private val sessionManager: SessionManager,
) : DebugService {
override fun getAllRealmConfigurations(): List<RealmConfiguration> {
return sessionManager.getLastSession()?.getRealmConfigurations().orEmpty() +
realmConfigurationAuth +
realmConfigurationGlobal
}
override fun logDbUsageInfo() {
RealmDebugTools(realmConfigurationAuth).logInfo("Auth")
RealmDebugTools(realmConfigurationGlobal).logInfo("Global")
sessionManager.getLastSession()?.logDbUsageInfo()
}
}

View file

@ -32,6 +32,7 @@ import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.SessionManager
import org.matrix.android.sdk.internal.auth.AuthModule import org.matrix.android.sdk.internal.auth.AuthModule
import org.matrix.android.sdk.internal.auth.SessionParamsStore import org.matrix.android.sdk.internal.auth.SessionParamsStore
import org.matrix.android.sdk.internal.debug.DebugModule
import org.matrix.android.sdk.internal.raw.RawModule import org.matrix.android.sdk.internal.raw.RawModule
import org.matrix.android.sdk.internal.session.MockHttpInterceptor import org.matrix.android.sdk.internal.session.MockHttpInterceptor
import org.matrix.android.sdk.internal.session.TestInterceptor import org.matrix.android.sdk.internal.session.TestInterceptor
@ -49,6 +50,7 @@ import java.io.File
NetworkModule::class, NetworkModule::class,
AuthModule::class, AuthModule::class,
RawModule::class, RawModule::class,
DebugModule::class,
SettingsModule::class, SettingsModule::class,
SystemModule::class, SystemModule::class,
NoOpTestModule::class NoOpTestModule::class

View file

@ -29,6 +29,7 @@ import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.internal.network.ApiInterceptor import org.matrix.android.sdk.internal.network.ApiInterceptor
import org.matrix.android.sdk.internal.network.TimeOutInterceptor import org.matrix.android.sdk.internal.network.TimeOutInterceptor
import org.matrix.android.sdk.internal.network.UserAgentInterceptor import org.matrix.android.sdk.internal.network.UserAgentInterceptor
import org.matrix.android.sdk.internal.network.httpclient.applyMatrixConfiguration
import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor
import org.matrix.android.sdk.internal.network.interceptors.FormattedJsonHttpLogger import org.matrix.android.sdk.internal.network.interceptors.FormattedJsonHttpLogger
import java.util.Collections import java.util.Collections
@ -92,11 +93,9 @@ internal object NetworkModule {
if (BuildConfig.LOG_PRIVATE_DATA) { if (BuildConfig.LOG_PRIVATE_DATA) {
addInterceptor(curlLoggingInterceptor) addInterceptor(curlLoggingInterceptor)
} }
matrixConfiguration.proxy?.let {
proxy(it)
}
} }
.connectionSpecs(Collections.singletonList(spec)) .connectionSpecs(Collections.singletonList(spec))
.applyMatrixConfiguration(matrixConfiguration)
.build() .build()
} }

View file

@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.network.httpclient package org.matrix.android.sdk.internal.network.httpclient
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.internal.network.AccessTokenInterceptor import org.matrix.android.sdk.internal.network.AccessTokenInterceptor
import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor
@ -51,3 +52,17 @@ internal fun OkHttpClient.Builder.addSocketFactory(homeServerConnectionConfig: H
return this return this
} }
internal fun OkHttpClient.Builder.applyMatrixConfiguration(matrixConfiguration: MatrixConfiguration): OkHttpClient.Builder {
matrixConfiguration.proxy?.let {
proxy(it)
}
// Move networkInterceptors provided in the configuration after all the others
interceptors().removeAll(matrixConfiguration.networkInterceptors)
matrixConfiguration.networkInterceptors.forEach {
addInterceptor(it)
}
return this
}

View file

@ -71,6 +71,9 @@ import org.matrix.android.sdk.internal.auth.SSO_UIA_FALLBACK_PATH
import org.matrix.android.sdk.internal.auth.SessionParamsStore import org.matrix.android.sdk.internal.auth.SessionParamsStore
import org.matrix.android.sdk.internal.crypto.DefaultCryptoService import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
import org.matrix.android.sdk.internal.database.tools.RealmDebugTools import org.matrix.android.sdk.internal.database.tools.RealmDebugTools
import org.matrix.android.sdk.internal.di.ContentScannerDatabase
import org.matrix.android.sdk.internal.di.CryptoDatabase
import org.matrix.android.sdk.internal.di.IdentityDatabase
import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.SessionId
import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate
@ -88,6 +91,9 @@ internal class DefaultSession @Inject constructor(
override val sessionId: String, override val sessionId: String,
override val coroutineDispatchers: MatrixCoroutineDispatchers, override val coroutineDispatchers: MatrixCoroutineDispatchers,
@SessionDatabase private val realmConfiguration: RealmConfiguration, @SessionDatabase private val realmConfiguration: RealmConfiguration,
@CryptoDatabase private val realmConfigurationCrypto: RealmConfiguration,
@IdentityDatabase private val realmConfigurationIdentity: RealmConfiguration,
@ContentScannerDatabase private val realmConfigurationContentScanner: RealmConfiguration,
private val lifecycleObservers: Set<@JvmSuppressWildcards SessionLifecycleObserver>, private val lifecycleObservers: Set<@JvmSuppressWildcards SessionLifecycleObserver>,
private val sessionListeners: SessionListeners, private val sessionListeners: SessionListeners,
private val roomService: Lazy<RoomService>, private val roomService: Lazy<RoomService>,
@ -265,5 +271,17 @@ internal class DefaultSession @Inject constructor(
override fun logDbUsageInfo() { override fun logDbUsageInfo() {
RealmDebugTools(realmConfiguration).logInfo("Session") RealmDebugTools(realmConfiguration).logInfo("Session")
RealmDebugTools(realmConfigurationCrypto).logInfo("Crypto")
RealmDebugTools(realmConfigurationIdentity).logInfo("Identity")
RealmDebugTools(realmConfigurationContentScanner).logInfo("ContentScanner")
}
override fun getRealmConfigurations(): List<RealmConfiguration> {
return listOf(
realmConfiguration,
realmConfigurationCrypto,
realmConfigurationIdentity,
realmConfigurationContentScanner,
)
} }
} }

View file

@ -73,6 +73,7 @@ import org.matrix.android.sdk.internal.network.PreferredNetworkCallbackStrategy
import org.matrix.android.sdk.internal.network.RetrofitFactory import org.matrix.android.sdk.internal.network.RetrofitFactory
import org.matrix.android.sdk.internal.network.httpclient.addAccessTokenInterceptor import org.matrix.android.sdk.internal.network.httpclient.addAccessTokenInterceptor
import org.matrix.android.sdk.internal.network.httpclient.addSocketFactory import org.matrix.android.sdk.internal.network.httpclient.addSocketFactory
import org.matrix.android.sdk.internal.network.httpclient.applyMatrixConfiguration
import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor
import org.matrix.android.sdk.internal.network.token.AccessTokenProvider import org.matrix.android.sdk.internal.network.token.AccessTokenProvider
import org.matrix.android.sdk.internal.network.token.HomeserverAccessTokenProvider import org.matrix.android.sdk.internal.network.token.HomeserverAccessTokenProvider
@ -212,7 +213,7 @@ internal abstract class SessionModule {
@UnauthenticatedWithCertificate @UnauthenticatedWithCertificate
fun providesOkHttpClientWithCertificate( fun providesOkHttpClientWithCertificate(
@Unauthenticated okHttpClient: OkHttpClient, @Unauthenticated okHttpClient: OkHttpClient,
homeServerConnectionConfig: HomeServerConnectionConfig homeServerConnectionConfig: HomeServerConnectionConfig,
): OkHttpClient { ): OkHttpClient {
return okHttpClient return okHttpClient
.newBuilder() .newBuilder()
@ -228,7 +229,8 @@ internal abstract class SessionModule {
@UnauthenticatedWithCertificate okHttpClient: OkHttpClient, @UnauthenticatedWithCertificate okHttpClient: OkHttpClient,
@Authenticated accessTokenProvider: AccessTokenProvider, @Authenticated accessTokenProvider: AccessTokenProvider,
@SessionId sessionId: String, @SessionId sessionId: String,
@MockHttpInterceptor testInterceptor: TestInterceptor? @MockHttpInterceptor testInterceptor: TestInterceptor?,
matrixConfiguration: MatrixConfiguration,
): OkHttpClient { ): OkHttpClient {
return okHttpClient return okHttpClient
.newBuilder() .newBuilder()
@ -239,6 +241,7 @@ internal abstract class SessionModule {
addInterceptor(testInterceptor) addInterceptor(testInterceptor)
} }
} }
.applyMatrixConfiguration(matrixConfiguration)
.build() .build()
} }
@ -248,11 +251,13 @@ internal abstract class SessionModule {
@UnauthenticatedWithCertificateWithProgress @UnauthenticatedWithCertificateWithProgress
fun providesProgressOkHttpClient( fun providesProgressOkHttpClient(
@UnauthenticatedWithCertificate okHttpClient: OkHttpClient, @UnauthenticatedWithCertificate okHttpClient: OkHttpClient,
downloadProgressInterceptor: DownloadProgressInterceptor downloadProgressInterceptor: DownloadProgressInterceptor,
matrixConfiguration: MatrixConfiguration,
): OkHttpClient { ): OkHttpClient {
return okHttpClient.newBuilder() return okHttpClient
.newBuilder()
.apply { .apply {
// Remove the previous CurlLoggingInterceptor, to add it after the accessTokenInterceptor // Remove the previous CurlLoggingInterceptor, to add it after the downloadProgressInterceptor
val existingCurlInterceptors = interceptors().filterIsInstance<CurlLoggingInterceptor>() val existingCurlInterceptors = interceptors().filterIsInstance<CurlLoggingInterceptor>()
interceptors().removeAll(existingCurlInterceptors) interceptors().removeAll(existingCurlInterceptors)
@ -262,7 +267,9 @@ internal abstract class SessionModule {
existingCurlInterceptors.forEach { existingCurlInterceptors.forEach {
addInterceptor(it) addInterceptor(it)
} }
}.build() }
.applyMatrixConfiguration(matrixConfiguration)
.build()
} }
@JvmStatic @JvmStatic

View file

@ -21,6 +21,7 @@ import dagger.Module
import dagger.Provides import dagger.Provides
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.session.identity.IdentityService import org.matrix.android.sdk.api.session.identity.IdentityService
import org.matrix.android.sdk.internal.database.RealmKeysUtils import org.matrix.android.sdk.internal.database.RealmKeysUtils
import org.matrix.android.sdk.internal.di.AuthenticatedIdentity import org.matrix.android.sdk.internal.di.AuthenticatedIdentity
@ -29,6 +30,7 @@ import org.matrix.android.sdk.internal.di.SessionFilesDirectory
import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate
import org.matrix.android.sdk.internal.di.UserMd5 import org.matrix.android.sdk.internal.di.UserMd5
import org.matrix.android.sdk.internal.network.httpclient.addAccessTokenInterceptor import org.matrix.android.sdk.internal.network.httpclient.addAccessTokenInterceptor
import org.matrix.android.sdk.internal.network.httpclient.applyMatrixConfiguration
import org.matrix.android.sdk.internal.network.token.AccessTokenProvider import org.matrix.android.sdk.internal.network.token.AccessTokenProvider
import org.matrix.android.sdk.internal.session.SessionModule import org.matrix.android.sdk.internal.session.SessionModule
import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.SessionScope
@ -49,11 +51,13 @@ internal abstract class IdentityModule {
@AuthenticatedIdentity @AuthenticatedIdentity
fun providesOkHttpClient( fun providesOkHttpClient(
@UnauthenticatedWithCertificate okHttpClient: OkHttpClient, @UnauthenticatedWithCertificate okHttpClient: OkHttpClient,
@AuthenticatedIdentity accessTokenProvider: AccessTokenProvider @AuthenticatedIdentity accessTokenProvider: AccessTokenProvider,
matrixConfiguration: MatrixConfiguration,
): OkHttpClient { ): OkHttpClient {
return okHttpClient return okHttpClient
.newBuilder() .newBuilder()
.addAccessTokenInterceptor(accessTokenProvider) .addAccessTokenInterceptor(accessTokenProvider)
.applyMatrixConfiguration(matrixConfiguration)
.build() .build()
} }

View file

@ -528,6 +528,16 @@ dependencies {
exclude group: "org.jetbrains.kotlinx", module: "kotlinx-coroutines-debug" exclude group: "org.jetbrains.kotlinx", module: "kotlinx-coroutines-debug"
} }
// Flipper, debug builds only
debugImplementation('com.facebook.flipper:flipper:0.149.0') {
exclude group: 'com.facebook.fbjni', module: 'fbjni'
}
debugImplementation('com.facebook.flipper:flipper-network-plugin:0.149.0') {
exclude group: 'com.facebook.fbjni', module: 'fbjni'
}
debugImplementation 'com.facebook.soloader:soloader:0.10.3'
debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.1.0"
// Activate when you want to check for leaks, from time to time. // Activate when you want to check for leaks, from time to time.
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3' //debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'

View file

@ -9,6 +9,10 @@
<activity android:name=".features.debug.settings.DebugPrivateSettingsActivity" /> <activity android:name=".features.debug.settings.DebugPrivateSettingsActivity" />
<activity android:name=".features.debug.sas.DebugSasEmojiActivity" /> <activity android:name=".features.debug.sas.DebugSasEmojiActivity" />
<activity android:name=".features.debug.features.DebugFeaturesSettingsActivity" /> <activity android:name=".features.debug.features.DebugFeaturesSettingsActivity" />
<activity
android:name="com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity"
android:exported="true" />
</application> </application>
</manifest> </manifest>

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed 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 CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.flipper
import android.content.Context
import com.facebook.flipper.android.AndroidFlipperClient
import com.facebook.flipper.android.utils.FlipperUtils
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin
import com.facebook.flipper.plugins.inspector.DescriptorMapping
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin
import com.facebook.soloader.SoLoader
import com.kgurgul.flipper.RealmDatabaseDriver
import com.kgurgul.flipper.RealmDatabaseProvider
import io.realm.RealmConfiguration
import okhttp3.Interceptor
import org.matrix.android.sdk.api.Matrix
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class FlipperProxy @Inject constructor(
private val context: Context,
) {
private val networkFlipperPlugin = NetworkFlipperPlugin()
fun init(matrix: Matrix) {
SoLoader.init(context, false)
if (FlipperUtils.shouldEnableFlipper(context)) {
val client = AndroidFlipperClient.getInstance(context)
client.addPlugin(CrashReporterPlugin.getInstance())
client.addPlugin(SharedPreferencesFlipperPlugin(context))
client.addPlugin(InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()))
client.addPlugin(networkFlipperPlugin)
client.addPlugin(
DatabasesFlipperPlugin(
RealmDatabaseDriver(
context = context,
realmDatabaseProvider = object : RealmDatabaseProvider {
override fun getRealmConfigurations(): List<RealmConfiguration> {
return matrix.debugService().getAllRealmConfigurations()
}
})
)
)
client.start()
}
}
@Suppress("RedundantNullableReturnType")
fun getNetworkInterceptor(): Interceptor? {
return FlipperOkhttpInterceptor(networkFlipperPlugin)
}
}

View file

@ -59,6 +59,7 @@ import im.vector.app.features.settings.VectorLocale
import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.version.VersionProvider import im.vector.app.features.version.VersionProvider
import im.vector.app.flipper.FlipperProxy
import im.vector.app.push.fcm.FcmHelper import im.vector.app.push.fcm.FcmHelper
import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler
import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.Matrix
@ -97,6 +98,7 @@ class VectorApplication :
@Inject lateinit var autoRageShaker: AutoRageShaker @Inject lateinit var autoRageShaker: AutoRageShaker
@Inject lateinit var vectorFileLogger: VectorFileLogger @Inject lateinit var vectorFileLogger: VectorFileLogger
@Inject lateinit var vectorAnalytics: VectorAnalytics @Inject lateinit var vectorAnalytics: VectorAnalytics
@Inject lateinit var flipperProxy: FlipperProxy
@Inject lateinit var matrix: Matrix @Inject lateinit var matrix: Matrix
@Inject lateinit var fcmHelper: FcmHelper @Inject lateinit var fcmHelper: FcmHelper
@ -116,6 +118,7 @@ class VectorApplication :
enableStrictModeIfNeeded() enableStrictModeIfNeeded()
super.onCreate() super.onCreate()
appContext = this appContext = this
flipperProxy.init(matrix)
vectorAnalytics.init() vectorAnalytics.init()
invitesAcceptor.initialize() invitesAcceptor.initialize()
autoRageShaker.initialize() autoRageShaker.initialize()

View file

@ -50,6 +50,7 @@ import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider
import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.ui.SharedPreferencesUiStateRepository import im.vector.app.features.ui.SharedPreferencesUiStateRepository
import im.vector.app.features.ui.UiStateRepository import im.vector.app.features.ui.UiStateRepository
import im.vector.app.flipper.FlipperProxy
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -119,12 +120,16 @@ object VectorStaticModule {
@Provides @Provides
fun providesMatrixConfiguration( fun providesMatrixConfiguration(
vectorPreferences: VectorPreferences, vectorPreferences: VectorPreferences,
vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider,
flipperProxy: FlipperProxy,
): MatrixConfiguration { ): MatrixConfiguration {
return MatrixConfiguration( return MatrixConfiguration(
applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION, applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION,
roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider, roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider,
threadMessagesEnabledDefault = vectorPreferences.areThreadMessagesEnabled(), threadMessagesEnabledDefault = vectorPreferences.areThreadMessagesEnabled(),
networkInterceptors = listOfNotNull(
flipperProxy.getNetworkInterceptor(),
)
) )
} }

View file

@ -492,11 +492,7 @@ class BugReporter @Inject constructor(
*/ */
fun openBugReportScreen(activity: FragmentActivity, reportType: ReportType = ReportType.BUG_REPORT) { fun openBugReportScreen(activity: FragmentActivity, reportType: ReportType = ReportType.BUG_REPORT) {
screenshot = takeScreenshot(activity) screenshot = takeScreenshot(activity)
activeSessionHolder.getSafeActiveSession()?.let { matrix.debugService().logDbUsageInfo()
it.logDbUsageInfo()
it.cryptoService().logDbUsageInfo()
}
activity.startActivity(BugReportActivity.intent(activity, reportType)) activity.startActivity(BugReportActivity.intent(activity, reportType))
} }

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed 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 CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.flipper
import okhttp3.Interceptor
import org.matrix.android.sdk.api.Matrix
import javax.inject.Inject
/**
* No op version.
*/
@Suppress("UNUSED_PARAMETER")
class FlipperProxy @Inject constructor() {
fun init(matrix: Matrix) {}
fun getNetworkInterceptor(): Interceptor? = null
}