{"slug": "my-phone-broke-and-gemini-fixed-it", "title": "My Phone Broke, and Gemini Fixed It", "summary": "A developer whose OnePlus phone displayed unexplained red text and lag after ADB testing used Google's Gemini AI to diagnose the issue. Gemini queried the device's runtime settings and UI hierarchy via ADB, identifying the cause where standard troubleshooting failed.", "body_md": "It is early morning. You’ve just pulled an all-nighter tinkering with an Android project over ADB. The sun is already creeping through the window, tests finally pass, and you unplug the USB cable from your OnePlus to finally go to bed.\n\nYou unlock your screen, swipe down to open Settings, and freeze.\n\nRight across your menus is a block of bright-red monospace text:\n\n```\nisOverScrolling: false\nX: FlingVX: 0.0, ClickVX: 0.0\nY: FlingVY: 15435.0, ClickVY: 0.0\nAbortVX:0.0, AbortVY:15435.0\n```\n\nYou stare at it, then touch the screen again. The numbers immediately jump, recalculating in real time with every movement of your thumb. You swipe fast, and `FlingVY` shoots into the tens of thousands. \n\nThen you notice something even worse: the phone is lagging badly.\n\nWhen you swipe from the screen edge to go back, the gesture stutters. Pulling out the OnePlus Smart Sidebar hesitates and drops frames. The smooth 120Hz display suddenly feels like a cheap phone struggling to keep up.\n\nYour developer reflexes kick in immediately. You jump straight into **Developer Options**:\n\nEverything is disabled.\n\nFine. You hold down the power button and reboot. The phone restarts, you unlock it, open Settings, scroll down—and the red numbers are still right there.\n\nThat's when you start to panic. You open your browser and start searching:\n\n`\"red text on android screen\"`: `\"OnePlus red text on screen\"`: `\"OnePlus red text error\"`: `\"isOverScrolling: false\" OnePlus`: `\"AbortVX\"` / `\"ClickVX\"`: Zero results. Not a single thread on XDA Forums, not a mention on Reddit, and nothing on the OnePlus Community.\n\nIf you've worked with Android long enough, you know what this silence means: when an issue has zero documentation in AOSP and zero community threads, you're usually looking at a full factory reset.\n\nAt that point, the morning sun was already up. I had stayed up all night, I was running on zero sleep, completely exhausted, and my brain felt like an OutOfMemory error. I stared at the red numbers on my screen and made the most mature engineering decision possible:\n\nI decided to go to sleep.\n\n*\"You know what? This is future me's problem.\"*\n\nI put the phone face-down on the nightstand, closed my eyes, and hoped it would just magically disappear by the time I woke up.\n\nFast forward to later that afternoon: I woke up, tapped the screen, and nope—the red velocity numbers were still right there, tracking every single swipe while I was still half-asleep.\n\nNow awake and ready to deal with it, I decided it was time to bring in serious backup.\n\nI plugged the USB cable back into my laptop. I opened my Antigravity IDE where I had been pair-programming with **Gemini**, and typed out of pure frustration:\n\n*\"Hey, you ran some ADB commands on my phone earlier for some app testing and now there's this weird red text on my screen and the edges are lagging. I plugged it in—fix it.\"*\n\nIf this were a standard chatbot, you already know what its first response would be:\n\n*\"Go to Settings > Developer Options and disable 'Pointer Location', 'Show Layout Bounds', or 'Strict Mode'. If those are already off, try backing up your data and performing a factory reset.\"*\n\nEvery standard LLM defaults to that exact script because it assumes you're dealing with standard Android toggles. And when you tell it they're already off, it hits a complete dead end.\n\nInstead, Gemini took the wheel. What happened on my terminal over the next few minutes was impressive: rather than giving boilerplate advice, Gemini started systematically diagnosing the operating system from the inside out.\n\nGemini didn't guess. It queried the device's runtime settings via ADB:\n\n```\nadb shell settings get system pointer_location\nadb shell settings get system show_touches\n```\n\nBoth came back `0`. Standard Android touch telemetry was definitively off.\n\nThen Gemini dumped the entire live UI hierarchy of the Settings app:\n\n```\nadb shell uiautomator dump /sdcard/window_dump.xml\n```\n\nIt grepped the XML tree for `isOverScrolling`. The result? **Empty.**\n\nThat silence told Gemini everything:\n\n*\"This text does not exist as a TextView or a system overlay window. It is being painted directly onto the hardware Canvas buffer during draw passes by an internal UI component.\"*\n\nBecause the text appeared during scrolling in OnePlus system menus, Gemini formed an immediate hypothesis: the code belonged to OnePlus/OPPO’s proprietary UI toolkit—**COUI** (ColorOS UI).\n\nBecause these OEM classes are completely proprietary and unreleased, Gemini couldn't look up documentation. It had to read the machine code directly from the phone.\n\nTo inspect the COUI framework without needing root access, Gemini pulled a built-in pre-installed app that uses the same UI components:\n\n```\nadb pull /product/app/Calculator2/Calculator2.apk ./calc.apk\n```\n\nThen, right inside my terminal, Gemini wrote and executed Python scripts to parse the raw binary DEX (Dalvik Executable) structures of the APK.\n\nGemini parsed the DEX string pool inside `calc.apk` and found the exact IDs:\n\n`#2600` = `'AbortVX:'`\n`#37919` = `'isOverScrolling: '`\nIt mapped those string IDs across every class definition in the binary. In seconds, Gemini had the exact location:\n\n`androidx.recyclerview.widget.COUIRecyclerView` (OnePlus’s internal extension of the Jetpack RecyclerView)`dispatchDraw(Canvas canvas)` at bytecode offset `0x1fbea0`\nGemini disassembled the opcodes at that offset. The bytecode showed exactly what was going on under the hood:\n\n``` php\n0x1fbea0: invoke-virtual View->dispatchDraw\n0x1fbea6: sget COUIRecyclerView->COUI_DEBUG:Z   // Check static boolean flag\n0x1fbeaa: if-eqz -> 0x1fc03c                   // If false, skip entirely!\n0x1fbeae: iget COUIRecyclerView->mDebugPaint   // Get Paint object\n0x1fbec4: invoke-virtual Paint->setColor       // Set paint color to RED\n0x1fbed4: const-string 'isOverScrolling: '     // Format velocity strings\n0x1fbf2a: const-string 'X: FlingVX: '\n0x1fbf86: const-string 'Y: FlingVY: '\n0x1fbfe4: const-string 'AbortVX:'\n0x1fc036: invoke-virtual Canvas->drawText      // Draw directly on screen!\n```\n\nThere it was: an undocumented, internal scroll-physics debugger built by OEM engineers to measure fling velocities during ROM development.\n\nGemini now knew *what* was painting the screen, but why had `COUI_DEBUG` suddenly turned `true` across my entire phone?\n\nGemini inspected the class initializer `<clinit>` of `COUIRecyclerView`:\n\n``` php\n0x1fb9bc: const-string 'COUIRecyclerView'\n0x1fb9c2: invoke-static COUILog->isLoggable(\"COUIRecyclerView\", Log.DEBUG)\n0x1fb9d6: sput COUIRecyclerView->COUI_DEBUG:Z\n```\n\n`COUILog.isLoggable()` simply calls Android's built-in `android.util.Log.isLoggable(tag, level)`.\n\nIn Android, `Log.isLoggable()` first checks for a tag-specific system property (`log.tag.<TAG>`). If that doesn't exist, it checks the global fallback property:\n\n### 🎯 The Culprit:\n\n`persist.log.tag`\n\nGemini queried the phone:\n\n```\nadb shell getprop persist.log.tag\n```\n\nThe terminal printed one character:\n\n```\nV\n```\n\nHours earlier, while debugging an audio service over ADB, a command had set `persist.log.tag` to `V` (Verbose) to inspect background audio logs. \n\nThat one command triggered an unexpected chain reaction:\n\n`persist.` are saved directly to flash storage (`/data/property`). A reboot does not wipe them.` COUIRecyclerView` checked if debug logging was enabled. Because `persist.log.tag` was set globally to `V`, Android replied that everything was in verbose mode. `COUI_DEBUG` became `true`, and the red velocity overlay activated.\nOnce Gemini identified the exact root cause, the fix was quick and clean:\n\nGemini reset the dangerous persistent global log property to empty:\n\n```\nadb shell setprop persist.log.tag \"\"\n```\n\nTo make sure `COUIRecyclerView` could never wake up its debug drawing again—even if global verbose logging were accidentally enabled in a future project—Gemini injected a permanent tag-level suppression rule:\n\n```\nadb shell setprop persist.log.tag.COUIRecyclerView SUPPRESS\n```\n\nGemini killed the Settings process to immediately test the fix on the current window:\n\n```\nadb shell am force-stop com.android.settings\n```\n\nGemini triggered an automated swipe gesture through ADB, captured a live screenshot, and verified that the red text had vanished from Settings.\n\nWhile Settings was fixed immediately, Gemini pointed out a crucial Android runtime mechanic:\n\nIn the Dalvik/ART virtual machine, static initializers (`<clinit>`) run **only once** when a class is first loaded into a process. That meant any app or system service already running in RAM (like the Launcher, SystemUI, or Contacts) still held `COUI_DEBUG = true` cached in memory.\n\nTo guarantee that every background process, system daemon, and service reloaded cleanly from scratch with the new suppressed properties, we performed a fresh device reboot:\n\n```\nadb reboot\n```\n\nOnce the phone rebooted, I picked it up, unlocked it, and scrolled through every corner of the system:\n\nAs a Computer & Systems Engineering student, I usually take AI hype with a grain of salt. I understand how systems work under the hood, and I know how complex and messy OEM Android frameworks get when low-level state gets corrupted.\n\nIf I had posted this on a forum or asked a standard chatbot, the advice would have been the same generic response: back up your data and factory reset.\n\nWatching Gemini handle this live in my terminal was genuinely impressive. It didn't guess, and it didn't give generic tips. It followed a solid systems debugging process:\n\n`sget` instruction controlling the overlay.\nWatching an AI autonomously reverse-engineer compiled bytecode on a live device—and solve an undocumented framework issue in minutes without touching a single byte of my personal data—was amazing to see.\n\nThis isn't just about autocompleting syntax or generating boilerplate code anymore. This is a real glimpse into the future of systems engineering—and as an engineering student, it completely blew me away.", "url": "https://wpnews.pro/news/my-phone-broke-and-gemini-fixed-it", "canonical_source": "https://dev.to/omarafifi/my-phone-broke-and-gemini-fixed-it-329l", "published_at": "2026-09-09 22:26:48+00:00", "updated_at": "2026-09-09 22:44:59.778997+00:00", "lang": "en", "topics": ["artificial-intelligence", "developer-tools"], "entities": ["Gemini", "OnePlus", "Android", "ADB"], "alternates": {"html": "https://wpnews.pro/news/my-phone-broke-and-gemini-fixed-it", "markdown": "https://wpnews.pro/news/my-phone-broke-and-gemini-fixed-it.md", "text": "https://wpnews.pro/news/my-phone-broke-and-gemini-fixed-it.txt", "jsonld": "https://wpnews.pro/news/my-phone-broke-and-gemini-fixed-it.jsonld"}}