Skip to content

Commit

Permalink
Bump version to 7.26.0
Browse files Browse the repository at this point in the history
Fix mark registration complete flag.

Add extra catch to adding system contact links.

Update translations and other static files.

Bump version to 7.25.1

Fix bad active state check for subscriptions.

Bump version to 7.25.2

Remove old donation jobs.

Update libsignal-net integration to match libsignal v0.62.0.

Add MediaTTL to subscriptions configuration and wire in.

Normalize receipt labeling.

Add a .tool-versions to indicate which version of java should be used.

Add backup specific strings for token redemption error.

Add copy for paid-tier-pending dialog.

Update to actions/upload-artifact v4.

Include unregistered users in blocked sync message.

Detect storage space issues during restore.

Hardcode auto-provisioning in Gradle to off.

Fix restore/transfer string typos.

Resolve some gradle 8 deprecations.

Resolves signalapp#13788

Remove unreachable dependencies from verification-metadata.xml

I did this by clearing the components entries:

perl -i -0777 -pe 's/<components>.*?<\/components>//gs'  gradle/verification-metadata.xml

And then regenerating them:

./gradlew --write-verification-metadata sha256 qa --rerun-tasks

Resolves signalapp#13791

Convert some Java tests to Kotlin.

Resolves signalapp#13792

Switch to using toml version catalogs.

Resolves signalapp#13792

Prevent displaying AppSettings content until self is non-null.

Display proper error when call link deletion fails due to call link being in use.

Convert InternalValues to kotlin.

Implement checkin job for backups.

Change the JobDatabase to use a different error handler.

Relates to signalapp#13762

Remove redundant zkcCredential=true

Add deletion method to ArchiveApi.

Sync the MediaRootBackupKey during linking.

Fix link+sync uploads.

Update link+sync ui.

Remove mockito usage from android tests.

Rotate the link+sync flag.

Update bug_report.yaml

Resolves signalapp#13803

Remove junit.framework

Resolves signalapp#13805

Remove BaseUnitTest.java

Resolves signalapp#13804

Make LibSignalChatConnection Only Use Each ChatService Once

Introduce AEP and SSRE2.

Added a Storage Service Playground screen.

Update backup string (digit -> character).

Utilize fixed test address for mockwebserver.

Improve error reporting in storage service playground.

Allow stories to be embedded with link previews that do not have titles.

Update translations and other static files.
  • Loading branch information
cody-signal authored and AbandonedCart committed Jan 31, 2025
1 parent 09b58d0 commit b35597d
Show file tree
Hide file tree
Showing 301 changed files with 8,723 additions and 10,985 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ body:
id: guidelines
attributes:
label: "Guidelines"
description: "Search issues here: https://github.com/signalapp/Signal-Android/issues"
description: "Search issues here: https://github.com/signalapp/Signal-Android/issues/?q=is%3Aissue+"
options:
- label: I have searched searched open and closed issues for duplicates
required: true
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ on:
push:
branches:
- 'main'
- '4.**'
- '5.**'
- '7.**'

permissions:
contents: read # to fetch code (actions/checkout)
Expand Down Expand Up @@ -36,7 +35,7 @@ jobs:

- name: Archive reports for failed build
if: ${{ failure() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: reports
path: '*/build/reports'
2 changes: 1 addition & 1 deletion .github/workflows/diffuse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ jobs:
issue-number: ${{ github.event.pull_request.number }}
token: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: diffuse-output
path: ${{ steps.diffuse.outputs.diff-file }}
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
java 17.0.2
6 changes: 2 additions & 4 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ plugins {

apply(from = "static-ips.gradle.kts")

val canonicalVersionCode = 1485
val canonicalVersionName = "7.25.0"
val canonicalVersionCode = 1488
val canonicalVersionName = "7.26.0"
val currentHotfixVersion = 0
val maxHotfixVersions = 100

Expand Down Expand Up @@ -616,8 +616,6 @@ dependencies {
androidTestImplementation(testLibs.androidx.test.core)
androidTestImplementation(testLibs.androidx.test.core.ktx)
androidTestImplementation(testLibs.androidx.test.ext.junit.ktx)
androidTestImplementation(testLibs.mockito.android)
androidTestImplementation(testLibs.mockito.kotlin)
androidTestImplementation(testLibs.mockk.android)
androidTestImplementation(testLibs.square.okhttp.mockserver)
androidTestImplementation(testLibs.diff.utils)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.github.difflib.DiffUtils
import com.github.difflib.UnifiedDiffUtils
import junit.framework.Assert.assertTrue
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
package org.thoughtcrime.securesms.database

import androidx.test.ext.junit.runners.AndroidJUnit4
import junit.framework.Assert.assertEquals
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package org.thoughtcrime.securesms.database

import android.app.Application
import androidx.test.ext.junit.runners.AndroidJUnit4
import junit.framework.TestCase.assertTrue
import net.zetetic.database.sqlcipher.SQLiteDatabase
import net.zetetic.database.sqlcipher.SQLiteOpenHelper
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

package org.thoughtcrime.securesms.database

import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertNotNull
import junit.framework.TestCase.assertNull
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Test
import org.signal.core.util.readToSingleObject
import org.signal.core.util.requireLongOrNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

package org.thoughtcrime.securesms.database

import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertNotNull
import junit.framework.TestCase.assertNull
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Test
import org.signal.core.util.readToSingleObject
import org.signal.core.util.requireLongOrNull
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.thoughtcrime.securesms.database

import androidx.test.ext.junit.runners.AndroidJUnit4
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package org.thoughtcrime.securesms.database

import androidx.test.ext.junit.runners.AndroidJUnit4
import junit.framework.TestCase.assertNull
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.containsInAnyOrder
import org.hamcrest.Matchers.hasSize
import org.hamcrest.Matchers.`is`
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.Before
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.thoughtcrime.securesms.dependencies

import android.app.Application
import io.mockk.every
import io.mockk.mockk
import io.mockk.spyk
import okhttp3.ConnectionSpec
import okhttp3.Response
Expand All @@ -11,9 +13,6 @@ import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import okhttp3.mockwebserver.RecordedRequest
import okio.ByteString
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.signal.core.util.Base64
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.BuildConfig
Expand All @@ -35,6 +34,7 @@ import org.whispersystems.signalservice.internal.configuration.SignalServiceUrl
import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl
import org.whispersystems.signalservice.internal.configuration.SignalSvr2Url
import org.whispersystems.signalservice.internal.push.PushServiceSocket
import java.net.InetAddress
import java.util.Optional

/**
Expand All @@ -53,6 +53,8 @@ class InstrumentationApplicationDependencyProvider(val application: Application,
init {
runSync {
webServer = MockWebServer()
webServer.start(InetAddress.getByAddress(byteArrayOf(0x7f, 0x0, 0x0, 0x1)), 8080)

baseUrl = webServer.url("").toString()

addMockWebRequestHandlers(
Expand Down Expand Up @@ -90,14 +92,18 @@ class InstrumentationApplicationDependencyProvider(val application: Application,
signalProxy = Optional.empty(),
zkGroupServerPublicParams = Base64.decode(BuildConfig.ZKGROUP_SERVER_PUBLIC_PARAMS),
genericServerPublicParams = Base64.decode(BuildConfig.GENERIC_SERVER_PUBLIC_PARAMS),
backupServerPublicParams = Base64.decode(BuildConfig.BACKUP_SERVER_PUBLIC_PARAMS)
backupServerPublicParams = Base64.decode(BuildConfig.BACKUP_SERVER_PUBLIC_PARAMS),
censored = false
)

serviceNetworkAccessMock = mock {
on { getConfiguration() } doReturn uncensoredConfiguration
on { getConfiguration(any()) } doReturn uncensoredConfiguration
on { uncensoredConfiguration } doReturn uncensoredConfiguration
}
serviceNetworkAccessMock = mockk()

every { serviceNetworkAccessMock.isCensored() } returns false
every { serviceNetworkAccessMock.isCensored(any()) } returns false
every { serviceNetworkAccessMock.isCountryCodeCensoredByDefault(any()) } returns false
every { serviceNetworkAccessMock.getConfiguration() } returns uncensoredConfiguration
every { serviceNetworkAccessMock.getConfiguration(any()) } returns uncensoredConfiguration
every { serviceNetworkAccessMock.uncensoredConfiguration } returns uncensoredConfiguration

recipientCache = LiveRecipientCache(application) { r -> r.run() }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class SignalActivityRule(private val othersCount: Int = 4, private val createGro
val recipientId = RecipientId.from(SignalServiceAddress(aci, "+15555551%03d".format(i)))
SignalDatabase.recipients.setProfileName(recipientId, ProfileName.fromParts("Buddy", "#$i"))
SignalDatabase.recipients.setProfileKeyIfAbsent(recipientId, ProfileKeyUtil.createNew())
SignalDatabase.recipients.setCapabilities(recipientId, SignalServiceProfile.Capabilities(true, false, true))
SignalDatabase.recipients.setCapabilities(recipientId, SignalServiceProfile.Capabilities(true, false, true, true))
SignalDatabase.recipients.setProfileSharing(recipientId, true)
SignalDatabase.recipients.markRegistered(recipientId, aci)
val otherIdentity = IdentityKeyUtil.generateIdentityKeyPair()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ object AppCapabilities {
* asking if the user has set a Signal PIN or not.
*/
@JvmStatic
fun getCapabilities(storageCapable: Boolean): AccountAttributes.Capabilities {
fun getCapabilities(storageCapable: Boolean, storageServiceEncryptionV2: Boolean): AccountAttributes.Capabilities {
return AccountAttributes.Capabilities(
storage = storageCapable,
deleteSync = true,
versionedExpirationTimer = true
versionedExpirationTimer = true,
storageServiceEncryptionV2 = storageServiceEncryptionV2
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.signal.ringrtc.CallManager;
import org.thoughtcrime.securesms.apkupdate.ApkUpdateRefreshListener;
import org.thoughtcrime.securesms.avatar.AvatarPickerStorage;
import org.thoughtcrime.securesms.backup.v2.BackupRepository;
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
import org.thoughtcrime.securesms.database.LogDatabase;
Expand All @@ -53,6 +54,7 @@
import org.thoughtcrime.securesms.emoji.JumboEmoji;
import org.thoughtcrime.securesms.gcm.FcmFetchManager;
import org.thoughtcrime.securesms.jobs.AccountConsistencyWorkerJob;
import org.thoughtcrime.securesms.jobs.BackupRefreshJob;
import org.thoughtcrime.securesms.jobs.BackupSubscriptionCheckJob;
import org.thoughtcrime.securesms.jobs.BuildExpirationConfirmationJob;
import org.thoughtcrime.securesms.jobs.CheckServiceReachabilityJob;
Expand Down Expand Up @@ -246,13 +248,15 @@ public void onForeground() {
startAnrDetector();

SignalExecutors.BOUNDED.execute(() -> {
BackupRefreshJob.enqueueIfNecessary();
InAppPaymentAuthCheckJob.enqueueIfNeeded();
RemoteConfig.refreshIfNecessary();
RetrieveProfileJob.enqueueRoutineFetchIfNecessary();
executePendingContactSync();
KeyCachingService.onAppForegrounded(this);
AppDependencies.getShakeToReport().enable();
checkBuildExpiration();
checkFreeDiskSpace();
MemoryTracker.start();
BackupSubscriptionCheckJob.enqueueIfAble();

Expand Down Expand Up @@ -289,6 +293,13 @@ public void checkBuildExpiration() {
}
}

public void checkFreeDiskSpace() {
if (RemoteConfig.messageBackups()) {
long availableBytes = BackupRepository.INSTANCE.getFreeStorageSpace().getBytes();
SignalStore.backup().setSpaceAvailableOnDiskBytes(availableBytes);
}
}

/**
* Note: this is purposefully "started" twice -- once during application create, and once during foreground.
* This is so we can capture ANR's that happen on boot before the foreground event.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.groups.GroupId
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob
import org.thoughtcrime.securesms.jobs.RestoreAttachmentJob
import org.thoughtcrime.securesms.keyvalue.KeyValueStore
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.net.SignalNetwork
Expand Down Expand Up @@ -99,6 +100,7 @@ import java.io.OutputStream
import java.time.ZonedDateTime
import java.util.Locale
import java.util.concurrent.atomic.AtomicLong
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds
import org.signal.libsignal.messagebackup.MessageBackupKey as LibSignalMessageBackupKey

Expand Down Expand Up @@ -130,16 +132,56 @@ object BackupRepository {
}
}

/**
* Refreshes backup via server
*/
fun refreshBackup(): NetworkResult<Unit> {
return initBackupAndFetchAuth()
.then { accessPair ->
AppDependencies.archiveApi.refreshBackup(
aci = SignalStore.account.requireAci(),
archiveServiceAccess = accessPair.messageBackupAccess
)
}
}

/**
* Gets the free storage space in the device's data partition.
*/
fun getFreeStorageSpace(): ByteSize {
val statFs = StatFs(Environment.getDataDirectory().absolutePath)
val free = (statFs.availableBlocksLong) * statFs.blockSizeLong

return free.bytes
}

/**
* Checks whether or not we do not have enough storage space for our remaining attachments to be downloaded.
* Caller from the attachment / thumbnail download jobs.
*/
fun checkForOutOfStorageError(tag: String): Boolean {
val availableSpace = getFreeStorageSpace()
val remainingAttachmentSize = SignalDatabase.attachments.getRemainingRestorableAttachmentSize().bytes

return if (availableSpace < remainingAttachmentSize) {
Log.w(tag, "Possibly out of space. ${availableSpace.toUnitString()} available.", true)
SignalStore.backup.spaceAvailableOnDiskBytes = availableSpace.bytes
true
} else {
false
}
}

/**
* Cancels any relevant jobs for media restore
*/
@JvmStatic
fun skipMediaRestore() {
// TODO [backups] -- Clear the error as necessary, cancel anything remaining in the restore
SignalStore.backup.userManuallySkippedMediaRestore = true

AppDependencies.jobManager.cancelAllInQueue(RestoreAttachmentJob.constructQueueString(RestoreAttachmentJob.RestoreOperation.RESTORE_OFFLOADED))
AppDependencies.jobManager.cancelAllInQueue(RestoreAttachmentJob.constructQueueString(RestoreAttachmentJob.RestoreOperation.INITIAL_RESTORE))
AppDependencies.jobManager.cancelAllInQueue(RestoreAttachmentJob.constructQueueString(RestoreAttachmentJob.RestoreOperation.MANUAL))
}

/**
Expand Down Expand Up @@ -1147,10 +1189,12 @@ object BackupRepository {
private suspend fun getPaidType(): MessageBackupsType? {
val config = getSubscriptionsConfiguration()
val product = AppDependencies.billingApi.queryProduct() ?: return null
val backupLevelConfiguration = config.backupConfiguration.backupLevelConfigurationMap[SubscriptionsConfiguration.BACKUPS_LEVEL] ?: return null

return MessageBackupsType.Paid(
pricePerMonth = product.price,
storageAllowanceBytes = config.backupConfiguration.backupLevelConfigurationMap[SubscriptionsConfiguration.BACKUPS_LEVEL]!!.storageAllowanceBytes
storageAllowanceBytes = backupLevelConfiguration.storageAllowanceBytes,
mediaTtl = backupLevelConfiguration.mediaTtlDays.days
)
}

Expand Down
Loading

0 comments on commit b35597d

Please sign in to comment.