This will stop instances of the following from occuring in the logs
on SMS migration:
W/SQLiteCompiledSql: Releasing statement in a finalizer. Please ensure
that you explicitly call close() on your cursor: INSERT INTO sms
(address, person, date_sent, date, protocol, read, status, type,
reply_path_present,
net.sqlcipher.database.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
at net.sqlcipher.database.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:62)
at net.sqlcipher.database.SQLiteProgram.<init>(SQLiteProgram.java:109)
at net.sqlcipher.database.SQLiteStatement.<init>(SQLiteStatement.java:39)
at net.sqlcipher.database.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1647)
at org.thoughtcrime.securesms.database.SmsDatabase.createInsertStatement(SmsDatabase.java:767)
at org.thoughtcrime.securesms.database.SmsMigrator.migrateConversation(SmsMigrator.java:166)
at org.thoughtcrime.securesms.database.SmsMigrator.migrateDatabase(SmsMigrator.java:210)
at org.thoughtcrime.securesms.service.ApplicationMigrationService$ImportRunnable.run(ApplicationMigrationService.java:159)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
We aren't closing Statement objects before the finalizer on those
objects runs. When the GC runs, we'll get warnings like the above
which alert us to the fact that these objects are being automatically
closed for us in the finalizer, but that this is suboptimal behavior.
If we leave too many Statement (or Cursor) objects to be closed in
their finalizers, when the GC runs, it'll take longer than 10 seconds
to close them all and Android will kill the app. This 10 second limit
is hardcoded and we can only try to avoid it. A crash will look like:
java.util.concurrent.TimeoutException: net.sqlcipher.database.SQLiteCompiledSql.finalize() timed out after 10 seconds
at java.lang.Object.wait(Native Method)
at java.lang.Thread.parkFor$(Thread.java:1220)
at sun.misc.Unsafe.park(Unsafe.java:299)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:810)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:844)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1173)
at java.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:196)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:257)
at net.sqlcipher.database.SQLiteDatabase.lock(SQLiteDatabase.java:553)
at net.sqlcipher.database.SQLiteCompiledSql.releaseSqlStatement(SQLiteCompiledSql.java:106)
at net.sqlcipher.database.SQLiteCompiledSql.finalize(SQLiteCompiledSql.java:152)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:202)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:185)
at java.lang.Thread.run(Thread.java:818)
I was able to replicate the above crash consistently on a
Samsung Galaxy S7 edge when importing well over 100k SMS messages.
But as soon as I attached a debugger the crash did not persist. I
assume this is because of some VM-level interactions between the two
and did not investigate further after fixing it.
I do not have access to the stack trace for issue #7953 but this
could potentially resolve it. The crash is identical to that in #7477
but this patch is for SMS migration not restoring from a backup. I
was not able to replicate the crash on restoring a >100k message
backup.
It used to be that we let Android do the default behavior of
full-screening the EditText when in landscape, but honestly I
don't know who prefers that. So I've turned it off.
Fixes#8769
The new JobManager stuff created a table that had an
auto-incrementing ID, which was incorrectly being backed
up and restored, causing a crash. Now we skip it on both
import and export.
Some devices have a limit of 100 unique JobScheduler jobs.
Previously we allowed up to 1,000. Given that we just need
_some_ job running, I lowered the limit to 75 to give us
some head room.
- Eliminate the explicit spongycastle dependency. All access to
primitives is done through the JCE interfaces now, which allows
us to use a secure native-backed provider like conscrypt.
- Use conscrypt for our default security provider. This gives us
fast TLS 1.2 and 1.3 support on all devices, even before they
had platform support (like 4.4).
- Update minSdk to 18. Unfortunately the JCE interfaces for GCM
primitives are JDK 7+ (!) only, which became supported by Android
at 18.
We'll be updating minSdk to 19 in 4.37. This lets these users continue
to use the app, but they'll be warned with a persistent banner saying
that they can't receive updates.
If you navigated to the ConversationActivity again via some action (like
a shared contact invite) while searching, we don't get the toolbar close
event, and therefore the search nav would stay open. Now we just reset
it on newIntent() to be safe.
The way the highlight was done could get screwed up if you had multiple
whitespaces in a row. This particularly came up with messages with
multiple newlines.
There were situations where adding/removing members from a group
would update the group member list, but the short string (the little
text listing the first couple members of the group) wouldn't be updated
until you left the screen and came back.
1. Due to ShareActivity having noHistory=true, it will already be
ditched when you leave the activity.
2. We only need to truly finish() here if we've dropped the underlying
media.
Fixes#8591
Prevent users from trying to send videos that exceed the size limit.
Also, this commit properly populates height/width on media shared into
the app.
Fixes#8573
It didn't re-measure when pulling an item from the cache, screwing stuff
up after a phone rotation. Had a workaround for it for specific screens,
but this fixes the problem at the source.
Fixes#8583
There's odd corner cases where channels can be duplicated. This commit
adds some hard checks where we trim any dead channels, and unset any
notification channels from recipients whose notification channel isn't
present in the system settings.
`DEFAULT_CHANNEL_ID` is a String, but `channel` is a NotificationChannel. Equals will therefore always return `false`. I think my fix (using `getId()`) is what was intended.
TreeSets are annoying. contains() is calculated with the comparator,
which can lead to some weird bugs. Made sure the comparator didn't think
two items with the same date were identical.
Also fixed stableId generation to avoid any potential weirdness there.
Update our media send flow to allow users to send multiple images/videos
at once. This change includes:
- New in-app media picker flow.
- Ability to caption images and videos.
- Image editing tools are made more prominent in the flow.
- Some fixes to the image editing tools.
On some devices, pausing+resuming (or seeking) would restart playback
from the beginning, but show a progress bar further up. This seems to
have been caused by same race condition-y thing where we were seeking
multiple times in rapid succession. Now we'll only play once, and things
seem to be fine now.
Also removed usage of some deprecated methods.
Fixes#8432
The Android animators were getting out of sync when frames were dropped
(despite my best efforts), so now we just manually render each animation
frame as a function of time, so it never gets screwed up.
Fixes#8388
There are several (popular) phone models out there that have bugs in
their MediaPlayer implementation that cause them to be unable to play
voice notes. By moving to ExoPlayer, an application-level media player,
we should avoid most of these headaches and stardardize playback.
Fixes#7748
In the case where we add new fields to a Job's InputData, we want to
make sure that initialize() is called in the try block so that if it
fails, it simply fails the job (allowing the user to retry with the new
field) instead of crashing.
This is to guard against behavior WorkManager has where it may
re-enqueue a job that has already been completed (if, for instance, it
was preempted).
Fixes#8268
The aim of this is to help performance by breaking up the single massive
spritesheet into smaller ones. This will limit the amount of data that
needs to be kept in memory to render emoji.
(Hopefully) Fixes#8357
Because SMS sending is split over two jobs, there's no max retry limit
respected if we find out about the failure in SmsSentJob -- it's
requeued as a new job with a fresh attempt counter.
This commit carries a retry count between the two jobs. It also verifies
that we have service before attempting to send a message at all.
Relates to #8268
There are rare corner cases where a Job could be preempted by the
JobScheduler and then be rescheduled before the preempted job finished
running. This could create weird race conditions with bad consequences.
To fix this, we create a fun locking system that prevents two jobs with
the same UUID from running at the same time.
Includes display support for more genders, and more notably, skin tones.
These are not currently selectable in the UI, but they will be rendered
properly when other clients send them.
There's some ANRs, not many, that are likely caused by us riding the
5-second ANR timeout a little too closely. Giving us a little buffer to
see if that helps.
Some phones, notably the Pixel 3, had some problems with scaling after
taking photos. This fixes it by using the takePicture API instead of
pulling the bitmap from the TextureView.
Fixes#8292
Android P's new ringtone selector is a whole new activity that can cause
RecipientPreferenceActivity to go through the full onCreate() flow after
the ringtone selection. This could cause a race between setting the
preference and reading the preference from the notification channel.
Just threw them on a serial executor to guarantee ordering.