Discreet Log #27: Cwtch Android Improvements

25 Mar 2022

Welcome to Discreet Log! A fortnightly technical development update providing a look into the research, projects and tools that we work on at Open Privacy. For our twenty-seventh post Dan Ballard talks about the ongoing Android improvements we've been working on and potential future plans for mobile

We have kicked off Open Privacy’s 2022 fundraising drive! We’ve gotten some wonderful new supporters, but currently not enough to support all our staff continuing on through the year. We’re still looking at how we can keep pursuing our goals with reduced capacity.

Please consider donating or volunteering to help us continue our research and development of surveillance resistant software.

Android Stabilization Work

Mobile Problems

Cwtch on Android has always been a more challenging platform for us to support. Unlike a desktop app, where we can assume that once the app has been started it will stay running until the user turns it off, the Android kernel likes to kill apps when they are not being used (in the name of battery life).

The suggested approach to mobile app designs is to have state managed by a server/cloud service somewhere else, and the mobile app is just a thin client pulling remotely stored state and displaying it locally. That approach obviously doesn’t work for Cwtch, being a decentralized messaging app where each app is a fully fledged peer with no remote services needed (or wanted). Cwtch has always been a standalone app that needs to be online to work.

To attempt to tackle this on Android we started with trying to make use of Android services, which allow you to define some part of your program that can keep running in the background, permanently, even if the frontend UI is killed. This means splitting the app in half internally, and defining a “frontend” and “backend”.

Thankfully our Cwtch library, being written in Go, and our UI, being written in Flutter and Dart, meant we had an obvious logical point for this in libcwtch-go. On Android, rather than directly accessing the api we wrap it in a Worker which keeps running - meaning that user profiles will stay loaded, online and receiving messages - in theory at least.

Additionally, on Android, there was another big factor contributing to performance problems. By design, when loading a conversation, we load only as many messages as we need to display, and so our code loads them one by one. On the desktop this is no problem, it’s a normal function call. On Android however, we had built it so each request into the backend got a new Worker, and so there could easily be a second of delay per request, and on loading a message pane with 10-20 messages this could be a pretty noticeable slowdown.

On desktop, as this cost little in terms of performance because there was no frontend/backend distinction, when you changed to a new message pane, the UI threw away those messages and fetched the new ones from the backend every time. On Android, this was much more noticeable and could result in seconds of slowly loading messages.

Android Improvements

Screenshot of Cwtch chat on Android

To address these problems we’ve been slowly building out frontend message caching. The first version launched in 1.5 and cached all new messages coming into the app, so when you changed conversations, any new messages would be displayed right away. With 1.6 we built out the cache further to cache all fetched messages, so if you loaded a conversation, went to another, and came back, the Android version wouldn’t have to re-fetch any of the previously displayed messages.

With the 1.7 development cycle I’ve been extending the cache and libcwtch-go API to support a few new features, the first and biggest being bulk message fetching (this set of features is landing in the nightlies this week if you would like to preview it). We now only have to do one slow back end request, once. The message cache was a prerequisite for this feature as we needed somewhere to track what messages were being fetched for the UI, and a place to store them when the conversation wasn’t being displayed. With this work Android message loading should be much snappier.

We haven’t stopped there. During this work we also discovered we can move a few message-related backend requests out of our Android Worker and into our MainActivity, since they don’t all need to be slow individual workers. This should result in many small speed improvements as we continue this work further into the 1.7 release cycle.

These changes should also have an impact on other small issues with how our UI attempted to render sent messages that were noticeable on Android due to the inherent slowness of the original process (this could cause message duplicates to display, or most recently sent messages vanishing on Android). We’ve been able to rework how that behaves in this recent set of improvements so that it’s now much more reliable.

Planned Mobile Improvements and the Future of Cwtch on Mobile

There is also other work in the pipeline that may help Android. The original Cwtch Alpha featured some connection health check code we haven’t been using in the latest Betas, and we are investigating plugging it back in to detect if Tor Onion circuits have become stale and, if detected, automatically restart them. This again is a situation more often seen on mobile where network connections can be more turbulent. Detecting this sooner, and automatically reacting, should improve the user experience.

Right now we prevent the user from sending messages to an offline contact or group. A feature we will be considering for a future release is giving Cwtch the ability to queue messages for delivery while a contact is offline. This may also help smooth over the mobile experience for users.

Future thoughts we’ve had have included the ability for the mobile app to use another desktop app as a profile host and proxy. This would be a larger project and need design and a lot of development. It does somewhat follow from the preferred direction mobile OSs seem to wish apps to be designed in, with state stored “in the cloud” or on another service, and the mobile app just a thin client.

Somewhere down this road it also may become feasible for us to start thinking about an iOS port, however there are a lot of hurdles and work before we’d be able to realistically plan that work. One of the biggest is funding. We’re currently facing a funding crisis, with our steady and regular donations from Patreon and Paypal only covering the salary of one of our developers. If we aren’t able to raise more funding soon, one or more of our developers may need to find new jobs which would almost assuredly postpone big mobile plans like iOS indefinitely. If you’ve enjoyed the pace at with which we’ve been developing Cwtch and adding features, or even want us to go faster, please donate.

Stickers and T-shirts!

Donations of $5 or more receive stickers as a thank-you gift, and $25 or more gets you one of our new sticker sheets! To celebrate our 4th anniversary, we’ll even count cumulative pledges since November 2021 to our Patreon.

Donations of $50 or more can claim a limited edition Privacy is Consent t-shirt as a thank-you gift! By popular request, these black tshirts use high quality screen-printing done locally in Vancouver. Available in both unisex and fitted sizes.

For more information about donating to Open Privacy and claiming a thank you gift please visit our Donate page.

Dan Ballard,
Director of Engineering,
Open Privacy Research Society

Donate to Open Privacy


Donations of $5 or more receive stickers as a thank-you gift, and $25 or more gets you one of our new sticker sheets! To celebrate our 4th anniversary, we'll even count cumulative pledges since November 2021 to our Patreon.

Open Privacy is an incorporated non-profit society in British Columbia, Canada. Donations are not tax deductible. You can Donate Once via Bitcoin, Monero, Zcash, and Paypal, or you can Donate Monthly via Patreon or Paypal. Please contact us to arrange a donation by other methods.

What is Discreet Log?

Discreet Log is a technical development blog to give a more in-depth look at the research, projects and tools that we work on at Open Privacy.

More Discreet Logs