Android 4.4 ("KitKat", API 19) introduced the screenrecord shell command. This allows a developer to record the device's screen as a .mp4 video file (example).
An updated version, v1.1, was made available as source in AOSP on 11-Dec-2013, but was not shipped in an OS update. Version 1.2 was shipped with the next release, Android 5.0 ("Lollipop").
The features provided by screenrecord are now better provided by the MediaProjection API, which allows ordinary, unprivileged applications to record the screen. screenrecord may still be of some use for bug reports and analysis on development devices, and unlike store-bought recording apps its presence can be assumed.
--output-format
option, which
allows you to output data in a format other than .mp4. Select from raw
H.264, raw frames, and raw frames with headers.adb shell
executionThe combination of these two features means you can "mirror" the device display on your desktop by feeding the output of the screenrecord command into a video player on Linux.
--bugreport
option, which adds an "info page"
to the start of the recording, and a timestamp to every frame.
(sample with Calculator, in landscape)
(sample with Breakout, in portrait)
--bit-rate
option now accepts 'm' as a unit suffix, so
--bit-rate=8m
gets you 8Mbps.
--rotate
option was deprecated.
The "info" page added by --bugreport
shows the current
date and time, and dumps a collection of system properties,
notably ro.build.description
. This makes it easy to tell which
device the recording was made on, what release of the software,
and when it was captured. The per-frame timestamp is (mostly)
consistent with logcat, which should make it easier to match logs
with recorded video. A frame counter is also displayed for easy
reference in bug reports.
The --bugreport
mode does add an additional composition step,
increasing the overhead of recording the screen. Depending on the
circumstances and device capabilities, this may cause a noticeable
slowdown.
adb
doesn't send
stdin
to the device, so you can't write an interactive
command (plain shells get special treatment). There are ways to make
this better, though, which may be implemented in the future.
The screenrecord command is a 100% native shell-interface program. It interacts with the graphics compositor (SurfaceFlinger) and media encoder (mediaserver) through IPC requests. It uses a broad selection of APIs that are not public, and is therefore a terrible example of how to write code for Android. (There are public equivalents of everything used by screenrecord in the Android app framework, they're just not accessible from purely-native code. They also require special permissions.)
screenrecord uses a mirrored virtual display to capture the frames composited by SurfaceFlinger. When the screen is updated, screenrecord gets a frame; when nothing changes, no frames are received. Gaps in time are "recorded" by advancing the presentation time stamp in the video file, not by repeating frames. These time stamps are provided by SurfaceFlinger using the system monotonic clock, and reflect the time when the frame was composed.
Changes to the realtime clock (a/k/a "wall clock") time won't affect
the timing of video frames, but will alter the time shown in logcat
messages. The timestamps shown in the --bugreport
overlay are based off the monotonic clock, so updates to the
realtime clock will skew the times in the video away from the times
in logcat output. This is not expected to be a significant problem.
Note also there can be a couple frames of latency between the time
something happens and the time it appears on screen.
In normal operation, frames from SurfaceFlinger are sent to the video
encoder, which delivers encoded data to screenrecord
(i.e. SurfaceFlinger -> encoder -> screenrecord). With the
frame timestamp display enabled for --bugreport
mode,
the path is SurfaceFlinger ->
screenrecord -> render (frame + timestamp) -> encoder ->
screenrecord. The extra render step -- a full-screen blit plus a
few textured triangles -- taxes the GPU more heavily.
--bugreport
overlay?
The "info" page shows the screenrecord version and a full timestamp,
followed by a dump of interesting system properties (normally
accessible with adb shell getprop <property-name>
).
The last item is OpenGL driver info, obtained with
glGetString()
.
Incidentally, rendering of the "info" page doesn't delay the start of frame capture. The frame is simply drawn with a timestamp set a quarter-second in the past.
Each recorded frame of video has an HH:MM:SS.mmm
timestamp,
followed by a frame counter. The number in parenthesis is the number
of frames that were rendered to the virtual display but dropped by
screenrecord; unless your device is heavily loaded, this should always
be zero.
Screen rotation requires a restart of the foreground activity. While that's going on the activity can't redraw the screen, so the system does a bit of visual trickery: it grabs a screen shot and displays that instead.
The trouble is that the screen shot is displayed in a post-rotation configuration, while the app is still drawing in a pre-rotation configuration. Normally all interested parties (the window manager and SurfaceFlinger) are in sync, so all you see is the screen shot, which is rendered on top. Unfortunately, screenrecord is a bit late getting the memo, and continues to capture what the app is drawing -- but now it's partially overlaid by the rotated screen shot.
It's possible to do this right, but it's a bit of an effort to do it in screenrecord.
Ideally the rotation would also resize the encoded video mid-stream to avoid the letterbox/pillarbox effects.
Bugs and feature requests should be reported on the AOSP bug tracker.