Toggle theme

Software rants

2023-03-07: Android reorders buttons in incoming call notification

When I receive an incoming call, Android 13 displays a notification with "Decline" and "Answer" buttons:

Notification with "Decline" and "Answer" buttons

About one second later, the "Answer" button moves to the right and a "Screen call" button is inserted in its place:

Notification with "Decline", "Screen call", and "Answer" buttons

What could possibly go wrong?

2023-03-07: Android gesture navigation app switching

Android 10's gesture navigation lets the user swipe horizontally along the bottom of the screen to switch quickly between open apps.

If you swipe left-to-right, the last-used app slides onscreen from the left. If you then swipe right-to-left, the original app comes back in from the right, as you'd expect… unless you wait more than five or so seconds, at which point you instead need to swipe left-to-right to get back to the original app.

Android doesn't provide any indication of whether it's been long enough that the original app is on the left instead of the right, so the end result is that I rarely know which direction I need to swipe or which app I'm going to get.

2022-11-19: Gmail "Skip Inbox" filter vs. "Never send it to Spam" filter

If an email message is matched by one Gmail filter with the "Skip Inbox" action and a second filter with the "Never send it to Spam" action, it apparently always ends up in the inbox.

2022-11-09: YouTube Android playback controls

The YouTube Android app displays a dimming overlay with playback controls (pause, progress bar, fullscreen, etc.) when you start watching a video. After a few seconds, the overlay fades away automatically. You can tap the video to make the controls fade away immediately, and tap it again to make them fade back in.

The YouTube team completely botched the implementation of the tapping behavior, though: if you tap the video a bit before the overlay starts to fade away, it fades away but then immediately fades back in afterward. This has been broken for years.

The right approach would be to decide what to do based on the overlay's opacity at the time of the tap. If the opacity is above 50%, hide the overlay. If it's below, show the overlay. It's hard for me to even imagine what the code is doing to produce the current behavior.

2022-11-01: YouTube Android task stack

Android maintains a task stack:

  • When the user starts a new task (e.g. by launching an app from the home screen, or tapping on a link in an already-open app to launch a web browser) it's pushed onto the top of the stack.
  • When they press the back button (or perform the back gesture), the current task is popped off the stack and the previous task becomes active again.

The YouTube app goes out of its way to break this model:

  • When I tap a link in the Gmail app, YouTube opens and starts playing the video (after a brief detour through Chrome, which is weird, but whatever).
  • When I perform the back gesture, instead of returning to Gmail as I would expect, YouTube navigates to its home screen and continues playing the video in a "miniplayer" across the bottom of the screen.

This is infuriating. I'm trying to make the video stop playing and go back to the place I was before I tapped the YouTube link, but the app makes me perform the back gesture a second time to do that.

Unsurprisingly, the Android task stack documentation warns developers not to do what YouTube does:

Caution: Most apps should not interrupt the default behavior for activities and tasks. If you determine that it's necessary for your activity to modify the default behaviors, use caution and be sure to test the usability of the activity during launch and when navigating back to it from other activities and tasks with the Back button or gesture. Be sure to test for navigation behaviors that might conflict with the user's expected behavior.

2022-10-31: Google Chat read status

Google Chat notifies me about unread messages in multiple ways:

  • Phone notifications from Google Chat Android app
  • Desktop notifications from Gmail website
  • Chat widget titlebar color in Gmail website (blue if unread)

Unfortunately, it's completely unable to consistently remove those notifications after I've read the messages:

  • After opening my laptop just now, the Gmail chat widget had a blue titlebar even as it showed that I had sent the latest message in the conversation from my phone.
  • After I've read all the messages in a conversation on my computer, my locked phone's always-on display often continues displaying a Google Chat notification until I unlock the screen, at which point it immediately disappears. (The Gmail app has this problem too.)
  • The Gmail website often continues displaying stale desktop notifications even while I'm actively chatting in the conversation in Gmail. It also annoyingly creates a new notification for every new message in the conversation. The web Notifications API supports replacing notifications and closing notifications, so I don't know why Gmail has so much trouble getting this right.

With regard to the last point, the "Replacing existing notifications" section on MDN's Using the Notifications API page even describes what Gmail is doing as an example of what not to do!

It is usually undesirable for a user to receive a lot of notifications in a short space of time — for example, what if a messenger application notified a user for each incoming message, and they were being sent a lot? To avoid spamming the user with too many notifications, it's possible to modify the pending notifications queue, replacing single or multiple pending notifications with a new one.

2022-11-19: With the Gmail web redesign, I get chat notifications in yet another place! Unread conversations appear in my Gmail inbox, even with the "Receive an email if you haven't read a message" setting set to "Off".

2022-10-26: Google Fit heart point calculation

The Google Fit Android app tracks "heart points", a nebulous measure of exercise. Google gives the following explanation of how steps are mapped to heart points:

  • One minute of brisk walking (100 steps or more per minute) = One Heart Point
  • One minute of running (130 steps or more per minute) = 2 Heart Points

In practice, it seems like the programmers were lazy and wrote code that just checks the total step count once per minute. If you added 100-129 steps since the last check, you get one point. If you added 99 steps, you get zero.

This means that if you walk at a brisk pace but stop frequently, you can end up with almost no heart points even after covering several miles:

Google Fit screenshot showing 10,008 steps but only a single heart point

I am not a cardiologist but this is obviously not how exercise works.

A better implementation would define a curve mapping steps to fractional heart points, and then maintain a fractional total count behind the scenes.

(Since Google Fit doesn't seem to track elevation changes, I also frequently get just two or three heart points after a vigorous uphill hike while carrying a heavy pack.)

2022-10-19: Gmail spam filter false positives

Gmail does a great job of preventing spam from reaching my inbox, but it does an almost equally-bad job of keeping legitimate mail from being incorrectly flagged as spam. It's gotten to the point where I've created a dedicated "Never send it to Spam" filter for almost every mailing list that I'm subscribed to, and I still manually scan through everything labeled as spam every few days to rescue false positives.

This is especially frustrating since many of the incorrectly-flagged messages seem trivial to detect: they're from mailing lists that I've read for years without any manual spam reports, or in some cases even from people to whom I've sent email in the past.

I suspect that the filter's poor performance here is due to the huge number of users that Gmail has and the astounding volume of incoming mail that it handles: the team probably doesn't have sufficient resources to run a personalized classifier for each user, so they rely on the "wisdom" of the crowd: when bozos subscribe to a mailing list and later report it as spam instead of unsubscribing, all the other subscribers suffer.

2022-10-19: Gmail SPF checks for forwarded email

Sender Policy Framework lets domains publish the IP addresses that they use to send email so that mail servers can identify forged return addresses. When Gmail receives a message from an IP address that isn't listed via SPF (and there's no valid DKIM signature), it displays a big yellow banner warning that the message might be spam or a phishing attempt:

Gmail spam/phishing banner

If you use Google Domains to forward mail from one email address to a Gmail account, Google seems to perform the SPF check a second time when delivering the message internally. This fails (since the check is performed against a Google-owned IP that typically won't be listed in SPF), resulting in the big warning banner being displayed (and maybe an increased likelihood that the message will be marked as spam?).

In the below headers, the first SPF check (on the bottom) passes since is permitted to send mail on behalf of, but Gmail performs a second check (on the top) that fails because (an IP address owned by Google) isn't allowed to send mail for

Received-SPF: softfail ( domain of transitioning [omitted] does not designate as permitted sender) client-ip=;
Received-SPF: pass ( domain of [omitted] designates as permitted sender) client-ip=;

There's something called Sender Rewriting Scheme that exists to handle this case, but Gmail and/or Google Domains apparently don't implement it. The far-simpler fix would be for Google to just skip performing a bound-to-fail SPF check when forwarding a message within its own network.

2022-10-18: Google Fit activity creation

When I press the "Save" button to record an activity in the Google Fit Android app, I don't receive any visual feedback until the form is dismissed, often several seconds later. I have no idea if my press was received, so I often end up tapping the button multiple times.

I suspect that the app is sending an asynchronous request to a server and only updating the UI on completion. When I have a bad (or no) network connection, the form sometimes stays open indefinitely, leaving me to wonder if the activity will still be recorded if I close the form.

For some reason, the developers didn't bother writing a tiny bit of code to disable the button and change its text to "Saving" while the request is in-flight. An even better approach would be to save the activity locally and dismiss the form immediately and then send the data to the server in the background, but that would be more work.

2022-10-18: Google Calendar / Gmail integration

Google Calendar automatically creates events from email messages about flights and hotel bookings. It doesn't seem to make any effort to determine whether the bookings are actually for me, so I end up getting unexpected calendar reminders when family members or friends forward their reservations to me, but whatever.

A few days ago, I was surprised to discover the opposite problem: several automatically-added events about flights had disappeared from my calendar. I checked Google Calendar's "trash" page, found the events there, and restored them. The next day, all of the flights were again gone and in the trash. I restored them again, and luckily it seems to have stuck this time. This was a good reminder to distrust complex systems that try to "magically" do things on my behalf, e.g. I'll never use Google Travel, because it feels inevitable that it'll use the wrong time zone at some point and make me miss a flight.

2022-10-12: Android slider controls

Many Android apps use slider controls for precise input, like entering an activity's intensity in Google Fit or jumping to a point in a movie in Netflix (which I find myself doing a lot lately, since the Netflix app now seems to always restart movies at the beginning instead of resuming them).

After you drag the slider to the exact position that you want, it's nearly impossible to lift your finger off the screen (committing the input) without moving the slider to a different position.

A reasonable way to handle this would be by maintaining a buffer of recent values while the user is dragging the slider. When the user lifts their finger, check to see if the value changed just before the release event. If so, use one of the earlier stable values instead of the last one. In other words, if the sequence of events is this:

20 [press]
30 [release]

then use 27 as the value, not 30. Or, you know, use a control that's actually suited to numeric input instead of a slider.

2022-10-11: Google Chat titlebar buttons in Gmail

The clickable areas of the minimize, fullscreen, and close buttons in Google Chat are tiny and don't extend to the edges of the titlebar. There are also unclickable gaps between the buttons. If you miss a button's clickable area, the titlebar receives the click and the chat widget is minimized instead.

Google Chat titlebar buttons
Only the highlighted area actually closes the widget.

2022-10-11: Google Chat hovercards in Gmail

When I move my mouse pointer over any message in a Google Chat conversation, Gmail displays an annoying menu with "Add reaction", "Mark as unread", and various other actions, none of which I've ever used.

If I'm more unlucky and move the pointer over someone's name or profile photo, Gmail opens a huge hovercard with the user's contact info that blocks the whole conversation. This card is also displayed when I move the pointer over the other person's name in the chat widget's titlebar, and it inexplicably remains visible even after the chat widget is minimized. As a result, I often end up with a hovercard stuck onscreen when I was trying to do exactly the opposite thing and get a chat conversation to go away.

2022-10-11: Android Auto and Google Podcasts

Android Auto sometimes fails to see my music app when I plug my phone into the head unit in my car (I don't know why). When this happens, it decides to launch the Google Podcasts app and resume a podcast that I had briefly listened to more than a month ago. There doesn't seem to be any way to disable this behavior without either removing the Podcasts app from Android Auto or disabling autoplay entirely.

2022-10-09: AWS security

AWS's security-related UX is annoying:

  • The maximum session duration for the AWS Management Console (i.e. the web interface) is 12 hours. You can shorten the duration but apparently not extend it beyond 12 hours. If you try to click a link after 12 hours have passed since you signed in, you get an error telling you to reload the page and sign in again.
  • If you have multifactor authentication enabled, you apparently need to use your second factor every time you sign in, even if you're using the same trusted computer that you used to sign in 12 hours prior.
  • It's 2022 and AWS still only lets you register a single hardware MFA device for each account. (Apparently some people work around this limitation by sharing the same secret across multiple devices.)

2022-10-09: Android forced password authentication

If you have fingerprint authentication enabled on a Pixel phone (or presumably any other device running a stock build of Android), you'll be prompted to type the device's password before you can use it after the device boots, but also periodically when you try to unlock using your fingerprint (maybe once every 36 hours or so?).

I've seen this done elsewhere (e.g. an optional prompt in the Signal app) and suspect that it's more to keep you from forgetting your password than for added security. However, Android's schedule for needing to enter the password seems to be completely independent of your use of the device. The following happens to me frequently:

  • I'm using my phone.
  • I lock the screen by pressing the power button.
  • One minute later, I need to use my phone again and touch the fingerprint sensor.
  • The phone makes me type my (lengthy) password.

This can happen at extremely inconvenient times, e.g. when trying to show a boarding pass in an airport. The password prompt should be deferred until the phone has been idle for a long period of time.

Android has done this since at least 2015. When I first got annoyed by it back then, I filed a bug report that got closed without any justification. I asked someone with a long tenure on the Android Framework team to try to get it changed, but they didn't have any luck convincing the security team either. It's still annoying in 2022.