Skip to content
ClipHop
Download
7 min read

What we tested before launching ClipHop: the pre-launch QA pass

Behind-the-scenes look at ClipHop's pre-launch testing — the device matrix, the BLE edge cases, the OEM battery-killer behaviors, the pairing failure modes, and the things we deliberately haven't tested yet.

By

A week before launch is a good moment to be honest about what’s been tested and what hasn’t. This post is a behind-the-scenes look at ClipHop’s pre-launch QA — the device matrix, the BLE edge cases that took the most effort, the OEM-specific battery-killer rabbit holes, and the things we deliberately have not tested yet.

It’s not a marketing post. It’s a checklist of where we did the work and where we know there’s more to do.

The device matrix#

Most clipboard sync bugs aren’t in the code paths we wrote — they’re in the behaviors of specific Android / Mac / BLE combinations that surface only under specific conditions. So most of pre-launch QA was running through a matrix of real hardware:

Android side:

  • Pixel 7, 8, 9 running Android 14 / 15 (stock Android — the easy case).
  • Samsung Galaxy S22, S23, S24 on One UI 6 / 7 (the OEM that breaks more things than any other).
  • OnePlus 11, 12 on OxygenOS 14 / 15 (battery-killer scenarios).
  • Xiaomi 13, 14 on HyperOS / MIUI (different battery-killer scenarios).
  • Nothing Phone (2) as an outlier with a stock-ish Android variant.

macOS side:

  • Apple Silicon MacBook Pro / Air running macOS 13 / 14 / 15.
  • Apple Silicon Mac mini as a desktop reference.
  • Intel MacBook Pro running macOS 13 (the dwindling but still-shipping case).

That’s roughly 20 device pairs tested with the standard pair-and-sync flow, plus narrower coverage on edge cases.

The hardest class of bugs: OEM battery killers#

Stock Android and Pixel devices “just work” with our foreground-service approach. The complications come from OEM skins that ship aggressive battery-management policies on top of stock Android:

  • Samsung One UI has a feature called Sleeping Apps that throttles background activity for any app it deems “unused.” Our foreground service has to work explicitly to stay out of this list. The user has to also flip Battery → Unrestricted (which we surface during onboarding).
  • Xiaomi HyperOS / MIUI has its own Background apps policy that’s separate from Android’s stock one. The user has to whitelist ClipHop in two places — Android Settings, then MIUI’s Security app. Frustrating, but documented in the Android install guide.
  • OnePlus OxygenOS is somewhere between — Battery → Don’t optimize covers it on most models, but specific OS revisions have additional layers.
  • Pixel needs none of this; the stock foreground-service contract is honored.

Each of these required separate test passes to verify that the foreground service survives a full sleep cycle: phone in pocket for an hour, screen off, then take it out and verify the BLE link reconnects within seconds.

A meaningful chunk of our install/android page is built specifically to walk users through these per-OEM permissions. It looks like a lot of steps, but each one is a real and necessary fix for a real OEM behavior.

Pairing edge cases#

Pairing is the highest-stakes UX in the app — get it wrong and users either can’t connect or, worse, accidentally trust a wrong peer. Edge cases we explicitly tested:

  • 6-digit code rotation timing. Codes rotate every UTC minute. We tested code entry just before, exactly at, and just after a rotation tick. The phone-side code parser accepts the previous minute’s code for ~10 seconds after rotation to handle clock skew.
  • QR re-scan after timeout. If you scan a QR more than ~2 minutes after the Mac displays it, the Mac’s ephemeral key state has been recycled. We tested that the phone gets a clean error (“Code expired, ask the Mac to show a new QR”) rather than a confusing low-level failure.
  • Peer offline mid-handshake. What happens if the Mac is closed during the brief handshake window? Tested: phone retries with backoff, then surfaces “Mac is offline — re-open ClipHop on Mac and try again.” No partial-pair state is persisted.
  • Simultaneous pair attempts. Two phones trying to pair with the same Mac at once: Mac rejects the second connection with “Already pairing — finish the current session first.”
  • Re-pair after factory reset. If the user wipes one device and tries to re-pair, the old fingerprint won’t match. Tested that this surfaces as an explicit “fingerprint changed — confirm you trust the new identity” prompt rather than silently accepting.

The fingerprint-mismatch case in particular got several rounds of testing, because it’s the most security-sensitive UX surface — see How ClipHop encrypts your clipboard for why fingerprint verification matters.

What happens when one device walks out of range, then comes back? This turned out to be more nuanced than expected:

  • Brief disconnect (< 30 s): Both devices’ BLE stacks notice the link drop and re-establish quickly. We tested with the phone in another room behind a wall, then walking back. Reconnection takes ~3–8 seconds.
  • Longer disconnect (~5 min): On Android, the foreground service stays alive but the BLE link is gone. The service watches for the peer’s advertisement and reconnects when seen. Tested — works as designed.
  • Phone restart: Foreground service has to be re-launched (Android does not restart it on boot unless you’ve granted Auto-start permission, which is OEM-specific). The next time you open ClipHop, the pair re-establishes on its own. Tested across Pixel, Samsung, OnePlus.
  • Mac sleep / wake: Mac BLE stack drops connections during sleep. On wake, the menu-bar app reconnects within 2–5 seconds. Tested with both lid-close sleep and System Settings → Sleep.
  • Bluetooth toggled off and on: Tested explicitly. Both sides re-discover and reconnect.

The fundamental design choice that makes this all work is: identity keys are persistent, session keys are ephemeral. A reconnect doesn’t require re-pairing; it just requires both devices to find each other and run a fresh ECDH handshake against the stored identity keys. Users never see this happen — they just see the “Connected” indicator come back.

Power and battery impact#

A clipboard sync app that drains battery is a clipboard sync app you uninstall. We’ve measured:

  • Android foreground service idle: ~0.3–0.7% battery per hour on a Pixel 8. Indistinguishable from background services like the OS keyboard. Higher on OEM skins that mismanage BLE radio time.
  • Mac menu-bar app idle: negligible. CPU is essentially zero when no clipboard activity.
  • Active sync session: a brief radio wake per clip (~10–50 ms). For typical usage (10–50 clips/day) it’s well under 1% additional battery.

The pre-launch numbers are good. Real-world numbers from launch users will be the better signal.

What we have NOT tested#

This is the section we want to be most explicit about, because shipping with unknowns we haven’t named is worse than shipping with named limits:

  • Third-party security audit. The cryptographic design has been documented and self-reviewed, but it has not been independently audited. This is on our roadmap before 1.0. See How ClipHop encrypts your clipboard for the design we want audited.
  • iOS / iPad. Not implemented at all. Same protocol, but a different CoreBluetooth peripheral implementation than Android. On the post-1.0 roadmap.
  • Clipboard content beyond plain text and URLs. Rich text, images, files all deferred. v0.1.0 covers the overwhelming majority of clipboard traffic by frequency, but there are clear use cases we don’t address yet.
  • Multi-device pairs. v0.1.0 supports one active pair at a time as an intentional privacy default. Multi-pair UX (which peer receives this clip?) is a real product question we want to get right before shipping.
  • Localization. English only at launch.
  • Accessibility audit. We’ve followed reasonable practice (alt text, semantic HTML, keyboard nav on the menu-bar panel) but haven’t done a full screen-reader walkthrough yet.
  • Sustained heavy use over weeks. The longest continuous test pair we’ve run is ~5 days. No reason to expect drift, but we haven’t proven absence either.

This is the part we expect feedback on, both from launch users and from anyone with stronger threat models than we’ve designed for. Bug reports go to [email protected] and they go straight to the builder’s phone.

What this means for launch#

Pre-launch testing isn’t “we found everything.” It’s “we found and fixed the things our test matrix surfaces, and we know what we don’t know yet.” Real users will find bugs we didn’t anticipate; that’s a normal part of shipping software.

What pre-launch testing does give us confidence about:

  • The pair flow works on every device combination we have on hand.
  • BLE link-loss recovery is robust across the conditions phones and Macs actually encounter.
  • The OEM battery-killer scenarios that caused the most pre-launch pain have explicit user-facing fixes.
  • The cryptographic protocol is correct as specified (we’ve cross-tested signed handshakes and AEAD wrappers against test vectors).
  • Resource usage is within reason on every measured device.

Launch day is July 3 on Product Hunt. If you’ve found this post pre-launch, thanks for reading the boring side of building software.