Zygote
Hands-on labsbeginner

Lab 0 — Set up

Get a device or emulator, a working adb, and the habits that keep a lab safe: know what you are connecting to, what state it is in, and how to get back to normal.

5 minAPI 1–37 · 17verified 2026-10-27

Every lab in this module assumes one thing: you have a device you are allowed to poke at, and adb can see it. This page gets you there and establishes the safety habits that make the rest of the labs non-destructive.

TL;DR#

  • One device at a time. adb devices lists what is connected; -s <serial> targets one.
  • Developer options and USB debugging must be enabled before adb can talk to a phone.
  • An emulator is a fine lab device and is easier to reset than a phone.
  • Read before you write. Start with commands that only print state.
  • Know the undo. A setting you changed with settings put can be changed back; a package you disabled can be re-enabled.

Mental model#

Think of adb as a remote control with a shell attached.

The remote control part talks to a daemon on the device, which is why the device has to permit it: USB debugging is the permission, and the RSA key prompt is the authentication.

The shell part runs commands as the shell user on the device. That user has more access than an app but less than root, which is why some commands in these labs work and others do not.

Where the analogy breaks#

A remote control has a fixed set of buttons. adb shell gives you a shell, so the set of things you can do is limited by the device's permissions rather than by the tool. That is why the labs teach commands rather than features: the same adb binary runs every one of them.

Deep dive#

Connecting#

Over USB. Enable developer options (tap Build number seven times in About phone), then enable USB debugging in developer options. Connect the cable and accept the RSA fingerprint prompt on the device.

Over the network. Android supports wireless debugging on modern devices through a pairing flow in developer options. The adb pair command pairs with the device using a code the device displays, and adb connect then connects to the debugging port.1

The first thing to run in every session:

adb devices -l

The -l adds model and device information, which is how you tell two connected devices apart. If the list shows unauthorized, the device has not accepted your key; if it shows offline, the connection is not established.

The shell user#

adb shell runs as the shell UID on the device. That is a privileged user: it can read many system files, call most system services, and change settings. It is not root, and it is not the system UID, so some operations will be refused.

Three consequences worth knowing before the labs:

  • dumpsys is available to shell for most services. That is why it is the backbone of these labs.
  • settings can read and write the settings database for the namespaces shell is allowed to touch.
  • Package commands can change state — disabling, granting, revoking — and those changes persist until you undo them.

The safety habits#

Read the current value before changing it. For any setting, run settings get first, and keep the output. That is your undo.

Prefer reversible commands. pm disable-user can be undone with pm enable. pm uninstall cannot, unless you reinstall.

Do not disable system packages you depend on. Disabling the launcher or SystemUI will leave you with a device that is hard to use. The labs avoid this, but the command exists.

Know how to recover. A device stuck in a strange state usually recovers with a reboot. An emulator can be wiped and restarted.

The commands you will use most#

CommandWhat it does
adb devices -lList connected devices with details
adb shellOpen a shell as the shell user
adb shell getpropRead system properties
adb shell dumpsys <service>Print a system service's state
adb shell pm list packagesList installed packages
adb shell am start -WStart an activity and wait for the result
adb shell cmd <service> <command>Call a service's command interface
adb logcatRead the log buffers
adb pull <path>Copy a file from the device

A first session#

  1. Confirm the device

    Run adb devices -l. If the state is unauthorized, unlock the phone and accept the prompt. If it is offline, reconnect the cable or restart the adb server.

    You should seeOne line per connected device, with a serial and a state of device.
  2. Read the build identity

    Run the four getprop commands below. Note the API level; several labs choose behaviour based on it.

    You should seeFour lines, each a value.
  3. List the services

    Run adb shell dumpsys -l. This is the map for every dumpsys lab. Look for activity, package, window, meminfo and batterystats.

    You should seeA long list of service names, one per line.
  4. Open a shell

    Run adb shell. Try id to see which user you are, then exit.

    You should seeA shell prompt on the device.
First contact
adb devices -l
adb shell getprop ro.build.version.release
adb shell getprop ro.build.version.sdk
adb shell getprop ro.product.model
adb shell getprop ro.build.version.security_patch
adb shell dumpsys -l
adb shell id
Example output
Illustrative output — your device will differ.

Challenges#

Challenge 1 — Identify the device#

Without looking at the phone, determine its model, its Android version and its API level.

Reveal the answer
adb shell getprop ro.product.model
adb shell getprop ro.build.version.release
adb shell getprop ro.build.version.sdk

ro.product.model is the marketing model; ro.build.version.release is the Android version; ro.build.version.sdk is the API level. If several devices are attached, add -s <serial> or set ANDROID_SERIAL.

Challenge 2 — Find the service that owns the status bar#

dumpsys -l lists service names, not descriptions. Which service would you dump to learn about the status bar and notification shade?

Reveal the answer

The statusbar service. Try:

adb shell dumpsys statusbar

The service is managed by SystemUI rather than system_server, which is why it has its own dump implementation. Related services include notification and window.

Challenge 3 — Prove you are not root#

Show that the shell user cannot read another app's private data directory.

Reveal the answer
adb shell id
adb shell ls /data/data

id reports uid=2000(shell), not root. Listing /data/data is refused for most entries because each app's directory is protected by its UID and by SELinux. This is the sandbox in action; the security module explains the mechanism.

What you learned#

You have a device, a shell, and a map of its services. Every later lab starts from here. If you want the background on why the shell user is privileged but not root, read The app sandbox.

Next#

Lab 1 — Processes starts with the process table, which is the single most useful view of a running Android system.

Sources#

Sources

Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.

  1. docsadb over Wi-Fideveloper.android.comaccessed 2026-10-27↩
  2. docsdumpsysdeveloper.android.comaccessed 2026-10-27↩
  3. docsAndroid Debug Bridge (adb)developer.android.comaccessed 2026-10-27↩
  4. docsBuild Androidsource.android.comaccessed 2026-10-27↩