B01a: Setting up the build machine

For the AOSP and AAOS training there are two options:

  • Either use a provided cloud instances, then continue on the subpage cloud
  • or use a local linux machines, e.g. a Laptop or workstation, then continue on the subpage local.

Additional notes

General information for the build requirements can be found on the website Try Android development. We already bundled these requirements in the Dockerfile and installed them on the cloud server.

Using a provided cloud instance

We are providing 12 cloud environments (VMs/virtual machines) for the training at hand. The machine configuration is

  • 24 VCPUs
  • 128 GB RAM
  • 500 GB disk storage

running Ubuntu 24.04.

These VMs have already been provisioned with an AOSP source tree based on Android 15 and the source code has already been built for the target “aosp_cf_x86_64_auto-trunk_staging-userdebug”. Furthermore, the cuttlefish emulator has been installed.

Note

To use the cloud instances you need an SSH client. On a modern Windows installation, the OpenSSH client is available as part of the operating system. If that is not the case, please click the above link for further instructions. We do not recommend using Putty, because we will need to forward many network ports later on. We provide an OpenSSH client configuration file that accomplishes that.

Coordinate the IP Address assignment with the trainers. Each participant will receive a slip of paper with a unique IP address of a cloud instance. You will also receive a password. Sharing an AOSP build tree will not work.

Note

The VMs will be decommissioned once the training is over. Therefore, feel free to customize them to suit your needs.

Note

The necessary tools like repo and the required configuration, such as the one for git, has already been performed on the server.

Working without VS Code

  1. Configure your SSH client to connect to the IP address using the username ubuntu. SSH is configured to use the default port 22. A Linux shell example is

    ssh ubuntu@185.113.125.XXX
    
  2. After you connect successfully, execute a ls command and look at the files in the home folder.

Terminal multiplexing

To have multiple shells in a single SSH session, you can use screen or tmux. Both are already installed.

Tips & Tricks

ssh public key

To avoid retyping the password on every login, you can also add one of your personal public ssh keys to the server. We will delete the virtual machine after the training.

(Public) IP Address

You can find the IPv4 address of this server in the file ip_address.txt. Use cat to display the file contents:

cat ip_address.txt

Using a local linux machine

Info

This step is only relevant if you are not using the remote server but a local build environment (your own one or the one provided by inovex on SSDs).

For this training we provide a Dockerfile that installs the necessary tools and packages.

The Dockerfile can be found in the github repository for this training.

# Build the container
docker build -t aosp .

# Run it and change into the interactive environment with:
docker run --rm -it --user=ubuntu aosp

Tip

You can also use podman instead of docker, just replace docker ... commands with podman ....

For the podman run command, you need to add an additional option --userns=keep-id. This assigns the local user's uid to the user inside the container, and allows that user to access /src/aosp from inside the container.

Setup git

In case you have not done so already, set up git with your personal information:

git config --global user.mail your_mailaddress@example.com
git config --global user.name "Your Name"

Install repo

To download the Android source code, you must install the command repo first. It's a tool developed by Google to maintain the Android source tree.

export REPO=$(mktemp /tmp/repo.XXXXXXXXX)
curl -o ${REPO} https://storage.googleapis.com/git-repo-downloads/repo
gpg --recv-keys 8BB9AD793E8E6153AF0F9A4416530D5E920F5C65
curl -s https://storage.googleapis.com/git-repo-downloads/repo.asc | gpg --verify - ${REPO} && install -m 755 ${REPO} ~/bin/repo

This will install the repo command into your home directory in the folder ~/bin/`. You may also have to add this path to your ``PATH environment variable.

Info

We also already installed repo in the docker container if you don't want to install it in your system.

B01b: Download the source code

Download Source Code

Info

Execute the commands only if are are not using a cloud instance and not using a prepared SSD. We have already downloaded and build the source code once for you. Execute these only if you are really want to start from scratch.

Create a directory for the code and development environment. In this tutorial, we will simply call this directory android.

# Create a new directory and use it as root of your build environment
mkdir android
cd android

Warning

Downloading takes quite a while and consumes > 200GB of storage capacity.

From this point on, all other commands should be executed from within your sources directory, unless stated otherwise.

# Initialize the repository
repo init --partial-clone -b android-automotiveos-15.0.0_lts4 -u https://android.googlesource.com/platform/manifest

# Actually download the source tree
repo sync -c -j8

B01c: Setup AOSP Build Environment

Info

You will have to re-run the following command each time you leave your build environment, e.g. by closing/changing your shell or restarting your system.

Ensure you are in the ~/android directory, then run the following commands:

source build/envsetup.sh

# Always run *lunch* afterwards! See next step!

In case you encounter the following error, please ignore it:

Build sandboxing disabled due to nsjail error.

Try out Repo Commands

The AOSP source tree is managed by a python tool called repo that utilizes git to manage and download a huge number of git repositories. repo also helps to automate parts of the development workflow.

Repo has several sub commands. Here's a selection of commands to try. You can look up their description using repo help:

cd android

repo status

repo diff

repo forall -c git remote -v

repo help

Warning

If you use the cloud instances, repo might notify you about a newer version being available upstream. Please do not upgrade because this training has only been tested with the currently installed version.

Choose the Target Device

To list all build targets (aka. lunch targets) you can execute

lunch

Since Android 14 this will print an empty list by default because some internal cache has not been generated yet. Please execute

# Available releases are: ap2a next staging trunk trunk_food trunk_staging.
export TARGET_RELEASE=trunk_staging
build_build_var_cache

And then lunch again. Now you should see a very long list of targets.

To select a lunch target at once, without selecting it by typing the number on the console, execute

lunch aosp_cf_x86_64_auto-trunk_staging-userdebug

Here we use the lunch target aosp_cf_x86_64_auto-trunk_staging-userdebug. cf_x86_64_auto is the AAOS Virtualization reference design based on cuttlefish.

userdebug is the build variant. See the documenation Choose a target for more information about it.

B02a: Fix your First Build Issue

Try to Build the Source Code

Navigate to the ~/android directory. This task assumes you're in the same shell environment you have configured in B01c: Setup AOSP Build Environment.

Now start building the source with

m -j24

Don't worry about the argument -j24 for now. It will be explained in a later exercise.

Under normal circumstances, this command would take several hours to complete. However, for the source code release *_lts4 and the selected build target aosp_cf_x86_64_auto it quickly fails with an error.

The error you should see is:

platform_testing/build/tasks/tests/native_test_list.mk: error: continuous_native_tests: Unknown installed file for module 'sv_2d_session_tests'
platform_testing/build/tasks/tests/native_test_list.mk: error: continuous_native_tests: Unknown installed file for module 'sv_3d_session_tests'
In file included from build/make/core/main.mk:1469:
In file included from build/make/core/Makefile:7667:
In file included from platform_testing/build/tasks/continuous_native_tests.mk:27:
build/make/core/tasks/tools/package-modules.mk:93: error: done.
18:01:37 ckati failed with: exit status 1

#### failed to build some targets (01:10 (mm:ss)) ####

That is bad. The source code does not built. But it’s often the case for large projects, like the AOSP, that some build configurations are broken.

The next sections walk you trough the process of debugging and fixing this build issue.

Note

The next sections will guide you through the exercise and provide the solutions, too. Don't just read passively. Instead, try to perform the steps on the command line yourself and invest the effort of solving the issue at hand!

Selecting a Search Term

Find a string or symbol name to search for. In our case you may use name of the failing modules, e.g., sv_2d_session_tests and sv_3d_session_tests.

Using this search term you can find the right place in the source code and learn more about it.

Let's go with sv_2d_session_tests for now.

Searching the AOSP Code Base

There are some special grepping tools in the AOSP environment. Here just use mgrep to search in Android.mk and Android.bp files. It will be explained in more detail later.

When you type in the command mgrep sv_2d_session_tests, you get the output:

./platform_testing/build/tasks/tests/native_test_list.mk:240:    sv_2d_session_tests \

There is only one result for the search term sv_2d_session_tests. The match is found in one file in a subdirectory of platform_testing.

When you look into the file

platform_testing/build/tasks/tests/native_test_list.mk

you see that two modules, sv_2d_session_tests and sv_3d_session_tests are added to native-tests, a variable that combines a lot of targets that are built together.

Also, you can see that this line is the only line/file that contains the string sv_2d_session_tests. There is no Android.bp file that is defining the module, e.g. adding some C/C++ sources to build something.

This is strange. Where is the source code of that sv_2d_session_tests tests?

Tip

See also some other tips in the blog post AOSP: Advanced Development Tricks under the topic “grep faster”.

Search Online on cs.android.com

Let’s search the entire AOSP tree and all versions on cs.android.com for the string sv_2d_session_tests:

Warning

There's currently a known and reported issue with cs.android.com.

The search won't show any results.

The code is still there. Use the direct links below.

There is only a single file where the string is found. See https://cs.android.com/android/platform/superproject/+/android14-qpr3-release:platform_testing/build/tasks/tests/native_test_list.mk?q=sv_2d_session_tests&ss=android

This is super strange. There is no source code for that module sv_2d_session_tests. It seems that it’s a tool that was not released as open source by Google. It’s used in the AOSP source code internally at Google, but wasn't published.

When you do a git blame, on the line for sv_2d_session_tests, you will find the commit b6975bd

See the link: https://cs.android.com/android/platform/superproject/+/android14-qpr3-release:platform_testing/build/tasks/tests/native_test_list.mk;bpv=1;bpt=0

It just adds the two lines sv_2d_session_tests and sv_3d_session_tests.

The Fix

Since there is no released source code for these two build modules and it exists only for testing, it is most likely safe to just remove the whole lines. These modules were removed a couple of releases ago. We just sneakily added them back in to give you a problem to work on.

At the moment th output of repo diff should look similar to this:

project platform_testing/
diff --git a/build/tasks/tests/native_test_list.mk b/build/tasks/tests/native_test_list.mk
index bf671731f..64e1e9584 100644
--- a/build/tasks/tests/native_test_list.mk
+++ b/build/tasks/tests/native_test_list.mk
@@ -236,7 +236,9 @@ native_tests := \
 ifeq ($(BOARD_IS_AUTOMOTIVE), true)
 native_tests += \
     libwatchdog_test \
-    evsmanagerd_test
+    evsmanagerd_test \
+    sv_2d_session_tests \
+    sv_3d_session_tests
 endif

ifneq ($(strip $(BOARD_PERFSETUP_SCRIPT)),)

You can now either edit and remove these two lines by hand using your favorite editor:

nano platform_testing/build/tasks/tests/native_test_list.mk

Or enter the platform_testing folder, and run git reset --hard which will revert to a working setup.

The output of repo diff should now be empty.

Testing the Fix

To test if the fix is sufficient, continue compiling the AOSP source code. E.g.

m -j24

Since your tree has not been built before, the above command will take a while to complete.

When the built has finished successfully, the following output will be shown:

#### build completed successfully (XX seconds) ####

Great. The fix was sufficient and the build is successful.

Note

The build does not need a lot of time to exit successfully. We have pre-built it to speed up the exercise.

B02b: Explore Build Commands and Tooling

Build an Image for our Target Device

If you are using a build environment already prepared by the trainers (VM, external SSD drive), the following command will unexpectedly complete very quickly. We have done the heavy lifting for you already 🙂.

# After 'source/envsetup.sh' and 'lunch'!
m -j$(nproc)

Note

On many POSIX-compatible systems, the nproc command prints the number of currently online processors. In case you are using one of our provided cloud instances, the nproc command will return 24, since the virtual machines have 24 cores. E.g., you can also just use

m -j24

Explore Build Commands, Options and Tooling

Useful commands for building parts of Android include:

# Trigger a full build for a target, starting at the top of the tree:
m
make     # make only works from the top of tree!

# Build and install all modules from the current directory as well as their dependencies:
mm
mma

# Build and install all of the modules in the supplied directories as well as their dependencies:
mmm dir1, dir2, ..
mmma dir1, dir2, ..

The m command also offers ways to clean up an already existing out directory. Make sure to read the following commands and understand their consequences, before entering them on your development machine:

# Clean the out/target/product/<productname>/*.img files.
m installclean
# Important:
#   After 'm installclean', the cuttlefish virtual device will not work anymore,
#   because its bootable image has just been deleted. You will need to re-generate
#   the deleted files by using 'm'.

# Clean build artifacts
# DO NOT EXECUTE THESE NOW, a clean build needs several hours to complete!
# m clean
# m clobber

More detailed help output and an explanation of the different command line tools and arguments can be obtained as follows:

# Help for tools and commands like lunch, mm, Android-specific grep tools, etc.:
hmm

# Help for build targets like clean, sync, snod:
m help

A selection of tools you might find useful:

# Go back to top of tree
croot

# Specific grep variants
cgrep        # C/C++
ggrep        # Gradle
gogrep       # Go
jgrep        # Java
jsongrep     # JSON
ktgrep       # Kotlin
mangrep      # AndroidManifest.xml
mgrep        # Makefiles and *.bp
owngrep      # OWNERS
rsgrep       # Rust
sepgrep      # sepolicy
sgrep        # Source files
tomlgrep     # TOML
pygrep       # Python

# more?

Build a Software Bill of Materials (SBoM) and Explore the out Directory

m sbom

# Output
ls out/<dist>/sbom*

# If you've used the aosp_cf_x86_64 target from above, replace <dist> accordingly:
ls out/soong/sbom/aosp_cf_x86_64_auto/sbom*

B03: Running cuttlefish

Running the device, cuttlefish emulator, is different wether you are working on one of the cloud instances or locally. Please continue either

Using one of the Provided Cloud Instances

ssh config

You have to configure 51 port forwarding configurations in your SSH config to connect to cuttlefish's web-based UI.

You need to forward port 8443 and the port range 15550–15599 from your localhost to the VM. We have provided an example configuration for the OpenSSH SSH client.

Copy the following ssh config file into our ~/.ssh/config configuration (%USERPROFILE%\.ssh\config for Windows) or use a separate file with ssh -F:

# Forward https and webrtc ports for cuttlefish in the cloud.
Match host="185.113.125.*"
    user ubuntu
    #LocalForward 5038 localhost:5037 # for adb
    LocalForward 8443 localhost:8443
    LocalForward 15550 localhost:15550
    LocalForward 15551 localhost:15551
    LocalForward 15552 localhost:15552
    LocalForward 15553 localhost:15553
    LocalForward 15554 localhost:15554
    LocalForward 15555 localhost:15555
    LocalForward 15556 localhost:15556
    LocalForward 15557 localhost:15557
    LocalForward 15558 localhost:15558
    LocalForward 15559 localhost:15559
    LocalForward 15560 localhost:15560
    LocalForward 15561 localhost:15561
    LocalForward 15562 localhost:15562
    LocalForward 15563 localhost:15563
    LocalForward 15564 localhost:15564
    LocalForward 15565 localhost:15565
    LocalForward 15566 localhost:15566
    LocalForward 15567 localhost:15567
    LocalForward 15568 localhost:15568
    LocalForward 15569 localhost:15569
    LocalForward 15570 localhost:15570
    LocalForward 15571 localhost:15571
    LocalForward 15572 localhost:15572
    LocalForward 15573 localhost:15573
    LocalForward 15574 localhost:15574
    LocalForward 15575 localhost:15575
    LocalForward 15576 localhost:15576
    LocalForward 15577 localhost:15577
    LocalForward 15578 localhost:15578
    LocalForward 15579 localhost:15579
    LocalForward 15580 localhost:15580
    LocalForward 15581 localhost:15581
    LocalForward 15582 localhost:15582
    LocalForward 15583 localhost:15583
    LocalForward 15584 localhost:15584
    LocalForward 15585 localhost:15585
    LocalForward 15586 localhost:15586
    LocalForward 15587 localhost:15587
    LocalForward 15588 localhost:15588
    LocalForward 15589 localhost:15589
    LocalForward 15590 localhost:15590
    LocalForward 15591 localhost:15591
    LocalForward 15592 localhost:15592
    LocalForward 15593 localhost:15593
    LocalForward 15594 localhost:15594
    LocalForward 15595 localhost:15595
    LocalForward 15596 localhost:15596
    LocalForward 15597 localhost:15597
    LocalForward 15598 localhost:15598
    LocalForward 15599 localhost:15599

After you added these port forward configurations into your local SSH config, you have to restart your SSH session.

Start the cuttlefish emulator

Tip

Remember to change to the android directory and to run . build/envsetup.sh and lunch aosp_cf_x86_64_auto-trunk_staging-userdebug if you are using a fresh SSH session.

Start the cuttlefish emulator with

launch_cvd --gpu_mode=guest_swiftshader \
    --start_webrtc=true \
    -report_anonymous_usage_stats=n \
    --enable-sandbox=false \
    --cpus=8 \
    --display0=width=1920,height=1080,dpi=140

This will start the emulator and boot the OS.

Now, open a Chromium-based browser, e.g., Chrome, and go to the locally-hosted website https://localhost:8443. You should see the web UI of the cuttlefish emulator.

Note

You cannot use Firefox for the web UI of the emulator. The WebRTC connection will not work.

Note

When you start a second SSH connection to the VM, you may see the following errors:

bind [127.0.0.1]:15599: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 15599
Could not request local forwarding.

on the console. These can be ignored. They just indicate that the second SSH connection cannot set up the port-forward configurations, because the ports are already used by the first SSH connection.

Using a Local Linux Machine

Execute the following commands to run Cuttlefish on your machine:

launch_cvd --gpu_mode=guest_swiftshader \
    --start_webrtc=true \
    -report_anonymous_usage_stats=n \
    --enable-sandbox=false \
    --cpus=8 \
    --display0=width=1920,height=1080,dpi=140


adb devices

# Browser
https://localhost:8443/
/images/cuttlefish_webrtc.png

Cuttlefish in Docker

It is possible to run Cuttlefish virtual devices inside of a docker container (e.g., the one provided for the training) under certain preconditions. For instance, your host machine needs to be running a Linux distribution with KVM installed and usable.

Info

The following command intentionally removes some of the container isolation between software running inside the container and the host’s kernel. As different (versions of) Linux distributions have different security features enabled or your machine might be subject to security hardening measures, your mileage may vary.

The adb commands and the --publish=127.0.0.1:5037:5037 parameter for Docker in the code block below are optional. These allow you to use adb from outside of the container to interact with Cuttlefish inside the container.

docker run --rm -ti -v ./android:/src/aosp  --user=ubuntu -w /src/aosp \
    --device /dev/kvm                                                             \
    --device /dev/vhost-vsock                                                     \
    --publish=127.0.0.1:8443:8443                                                 \
    --publish=127.0.0.1:5037:5037                                                 \
    --privileged                                                                  \
    --ulimit nofile=262144:262144                                                 \
    aosp
adb kill-server              # make sure no server is running
adb -a -P 5037 start-server  # restart listening on all interfaces

launch_cvd --gpu_mode=guest_swiftshader \
    --start_webrtc=true \
    -report_anonymous_usage_stats=n \
    --enable-sandbox=false \
    --cpus=8 \
    --display0=width=1920,height=1080,dpi=140

Tip

In case adb devices shows no devices connected even though the adb commands were run and the Cuttlefish virtual device is running, using adb connect localhost:6520 may help.

Tip

When using podman instead of docker, remember to add the --userns=keep-id option so that the /src/aosp files are readable by the user inside of the container.

B04a: ADB and Accessing Logs

adb (the Android Debug Bridge) is the tool for interacting with an Android device. It provides numerous helpful commands. The most important ones are listed below:

# List available devices:
adb devices

# Access a local device' shell:
adb shell

# Connect to a remote device:
adb connect <HOST>[:PORT]
adb disconnect [HOST[:PORT]]

# Push & Pull -> Copy files:
adb push [--sync] [-z <ALGORITHM>] [-Z] <LOCAL...> <REMOTE>
adb pull [-a] [-z <ALGORITHM>] [-Z] <REMOTE...> <LOCAL>

# Sync a local build from $ANDROID_PRODUCT_OUT to the device (default all):
adb sync
# Sync only a single partition, e.g., /system
adb sync <PARTITION>
# Throw in some -l if you're curious what _would_ actually be transfered (dry-run)
adb sync -l [<PARTITION>]

# App installation
adb install app.apk

# Bug report
# https://developer.android.com/studio/debug/bug-report
adb bugreport report.zip

# More
adb help

Accessing Logs

# Access logs:
adb logcat

# Dump the current state of the log but do not continue to follow it:
adb logcat -d

adb logcat --help

# Inspect individual logcat buffers
# See also https://developer.android.google.cn/tools/logcat?hl=en
adb logcat -b radio
adb logcat -b main
adb logcat -b all

Logcat alternatives:

Getting kernel log messages:

# root-enabled device ('su' may help as well):
adb shell
$ dmesg

Development workflow, e.g., for Pixel devices, the boot loader needs to be unlocked

source build/envsetup.sh
lunch <option>
m -j$(nproc)
adb reboot bootloader
fastboot flashall

Hot Syncing

Syncing a source tree with a running (virtual) device can be done easily using sync commands but requires some preliminary steps, including disabling verified boot features and making the target partitions writable.

# Prepare
adb root
adb disable-verity
adb reboot
adb root
adb remount

# Afterwards
m sync

adb sync

adb shell "stop && start"

Debugging Services

Dumpsys

adb shell dumpsys -l

adb shell dumpsys

# For additional parameters for specific services see
adb shell dumpsys <servicename> help

# Car Services
adb shell dumpsys car_service

adb shell dumpsys car_service --list
adb shell dumpsys car_service --services [service-name]

# Your own services
adb shell dumpsys activity service com.example.yourapp

cmd

A command line interface for several system services. Not all services provide such an interface. Examples:

adb shell cmd -l                                    # lists all available services
adb shell cmd wifi connect-network VirtWifi open    # connects to SSID VirtWifi with no security
adb shell cmd car_service garage-mode on            # Puts car into garage mode
adb shell cmd window                                # lists all commands of the window manager

am, pm, ...

The Activity Manager am

adb shell am            # print all options and the help text
adb shell cmd activity  # same as adb shell am
adb shell am force-stop <PACKAGE>
adb shell am stop-service <INTENT>
adb shell am start-service <INTENT>

The Package Manager pm

adb shell pm                 # print help & all options
adb shell cmd package        # same as adb shell pm
adb shell pm list packages   # list all installed apps
adb shell pm uninstall       # uninstall an app
adb shell pm grant           # grant a runtime permission

fastboot

Apart from adb there is also the fastboot tool in the Android platform tools. We do not cover it in this training, but it's nevertheless important. It's the tool to flash the initial partition images onto the device or for recovering a bricked device. See Flash with Fastboot for more information.

B04b: Exercise: Build Your First App

In this exercise you are going to build and deploy our first app.

Download and Build

Download the git repository of the training to your local computer:

git clone https://github.com/inovexAcademy/aosp-aaos-training

The Android application is in the sub-directory app.

Now start Android Studio and open the project in app. Downloading the necessary dependencies and indexing the project may take some time.

After that you should see the following screen:

/images/android-studio.png

Let the instructor show you the core elements of the UI:

  • Editor Window
  • Toolbar to build and run the Application
  • Sidebar to navigate the source files
  • Bottom window with logcat

Now just build the application to get the apk file. Once the build has finished you will find the file in the build directory

find -name "*.apk"

There are multiple files, but the final apk will be ./app/app/build/outputs/apk/debug/app-debug.apk.

Install and Run

In case your Android device is attached locally, e.g., a phone in Developer Mode, you can deploy directly from the Android Studio UI.

When using the cuttlefish device in the virtual machine, as in this training, that is not possible. Therefore, we will install the application by hand.

First, copy the apk to virtual machine

scp ./app/app/build/outputs/apk/debug/app-debug.apk ubuntu@185.113.125.XXX:

Now switch back to a shell on the virtual machine. First check that the (cuttlefish) device is running:

adb devices

Then install the application in the apk file with

adb install app-debug.apk

This loads the apk file in the current directory and installs it on the device. You can check whether the application has been installed successfully with

adb shell pm list packages | grep aosptraining
adb shell pm dump de.inovex.aosptraining | less

The first command just prints a list of installed packages. The second command instructs the PackageManager to print out all the information of an application.

Then switch to the UI of the device and search for the new Launcher Activity/Icon on the Home screen. Click on it to start the application. The application should start.

/images/app-icon.png

To see the logcat output of the Activity, you can do

adb shell logcat -s 'MainActivity:*'

To see the logcat output of the entire application, you can use external tools like alogview:

alogview de.inovex.aosptraining

Additional Command-Line Tools

You can also control applications on the command line. For example, to stop an application, remove all Activity, Services and kill the Unix process, you can use

adb shell am force-stop de.inovex.aosptraining

After executing this command, the Activity on cuttlefish should disappear.

To start an Activity on the command line, you can execute

adb shell am start -n de.inovex.aosptraining/.MainActivity

am is the command-line interface to the ActivityManager. The first part (de.inovex.aosptraining) is the package name. The second part (.MainActivity) the name of the Activity.

After executing the command, you should see the Activity reappearing on the UI.

Bonus Task

Add a new log statement, e.g.,

Log.i(TAG, "hello world!");

in the onCreate() function, rebuild, redeploy and see it logcat's output.

B06a: Exercise: HAL

Go to the topic assigned to your group to access the resources for you topic.

Group 1: Generic Kernel Image (GKI)

Resources

Look at the following resources to get started. Hint: Follow links and also look at releated sections in the documentation hierarchy.

Questions

  • Why did Google introduce the GKI?
  • Where is the GKI used?
  • Are device vendors still allowed to use custom kernels?

Group 2: Project Treble

Resources

Look at the following resources to get started. Hint: Follow links and also look at releated sections in the documentation hierarchy.

Questions

  • What is Project Treble?
  • What was the motivation for Project Treble?
  • What further changes were made after the initial implementation in Android 8?

Group 3: Generic System Image (GSI) and Shared System Image (SSI)

Resources

Look at the following resources to get started. Hint: Follow links and also look at releated sections in the documentation hierarchy.

Questions

  • Where is the GSI used?
  • Who benefits from SSI?
  • What is the point of AOSP having so many partitions (system, system_ext, product, vendor, odm)?

B06b: Exercise: Write Your Own Service

In this exercise, you will create and launch your own service on the (virtual) device and interact with it.

The required code to get you started can be found in the Github repository accompanying this training.

The instructions and individual tasks of the assignment can be found in the README.md in the hands-on_native-service/ folder.

B06c: Kernel modules

In this exercise, we will build our own kernel module for the kernel running on the CVD, and integrate that module into the AOSP build process.

We will be working with the cuttlefish emulator device again in this exercise. When working with the kernel and kernel builds, it is important to first understand what kernel we are working with before actually modifying anything.

Inspect the Cuttlefish kernel

  1. Start a new session on the training VM and read the output of the lunch command carefully and note down the TARGET_ARCH value.

  2. Open an adb shell and try to figure out what kernel is running (cf. uname(1)). There are multiple ways to do this.

    Take note of the kernel name, then use the Documentation to parse the kernel version string.

  3. Find the kernel in the AOSP source tree. Start with the kernel sub directory in the root directory. Use the information you have collected in the previous steps.

  4. Take a look at the following resources for more information about the running kernel:

    Tip

    Upstream trims these pages down from time to time, so in case you cannot find the exact kernel version on the respective sub pages for the kernel version in use, just try the next link.

    Tip

    This page contains information on the build variant you will be using in the next steps.

Build a kernel module

In this step, coding is not required. Simply build the kernel module "as is" from the branch mentioned in the instructions below.

A kernel build environment has been prepared for you on the training VMs in the kernel-gki-android15-6.6 directory.

For reference, the steps to create this environment are as follows:

KERNEL_BUILD_DIR=${HOME}/kernel-gki-android15-6.6
mkdir -p "${KERNEL_BUILD_DIR}"
cd "${KERNEL_BUILD_DIR}"
repo init -u https://android.googlesource.com/kernel/manifest -c -b common-android15-6.6
repo sync -c -j6
# Check out the kernel sources matching the kernel running in cvd
git -c common checkout 02f25b80c91cf5abf216b99ded16570c8cc87dd4
  1. Enter the kernel build directory in a fresh shell session on the training VM. Do not run lunch or build/envsetup.sh in this session.

    cd kernel-gki-android15-6.6
    
  2. The kernel build environment contains the kleaf and bazel wrappers. To use these in the following steps, add them to your $PATH environment variable:

    KERNEL_BUILD_DIR=${HOME}/kernel-gki-android15-6.6
    export PATH="${KERNEL_BUILD_DIR}/tools:${PATH}"
    

    Info

    You will have to do this every time you open a new shell. In a more persistent setup, you would either set the $PATH variable in your shell configuration files or install bazel with your operating system's package manager.

    For this training exercise, that kind of overhead is not required.

  3. Before we can build the kernel, we need to identify the bazel build target (similar to a make target). bazel has a query feature that allows listing kernels. The target notation syntax might seem odd at first: it is not 100% accurate to think of the part between "//" and ":" as a directory path relative to the project root "//" but this simplification helps a lot in understanding what is going on. Check out the respective directories in the kernel source tree when running the query commands below. There are a lot of build files used to configure the individual variants:

    # Get help regarding the target syntax:
    bazel help target-syntax
    
    # List all common kernel targets
    bazel query "kind('py_binary', //common:*)"
    
    # List all virtual device targets
    bazel query "kind('py_binary', //common-modules/virtual-device:*)"
    
  4. Now, let's finally build some kernels!

    bazel build //common:kernel_x86_64
    
  5. Integrate our kernel modules into the source tree

    With Android 15, we use in-tree builds:

    git clone https://github.com/inovexAcademy/aosp-aaos-training.git vendor/inovex
    
  6. Read and understand the BUILD.bazel file in ${KERNEL_BUILD_DIR}/vendor/inovex/kernel-module.

  7. Build the kernel module:

    bazel build //vendor/inovex/kernel-module:all
    

After having completed the above steps successfully, you will find your kernel module files in ${KERNEL_BUILD_DIR}/bazel-bin/vendor/inovex/kernel-module/. There are multiple sub-directories, per target and per build type/mode.

In the following steps we will be using the *.ko files found in the main directories. You can inspect them using the following commands:

ls -lh  bazel-bin/vendor/inovex/kernel-module/training_mod/*.ko
modinfo bazel-bin/vendor/inovex/kernel-module/training_mod/*.ko

Deploy a kernel module

Manually deploy kernel module

In order to quickly test your kernel module, push it onto the running Cuttlefish device and load it. This approach is insufficient for building an actual product, however, it is very useful for quick development iterations.

# We need root privileges to load kernel modules. Do this first:
adb root

# Push the module:
adb push bazel-bin/vendor/inovex/kernel-module/training_mod/aosp_training_sysfs.ko /tmp/

# Load the module
adb shell insmod /tmp/aosp_training_sysfs.ko

# Let's check if our module has actually been loaded. Pay attention to the usage numbers:
adb shell lsmod | grep training

# Let's see if our module is actually providing the expected information in sysfs:
adb shell cat /sys/kernel/aosp_training/read_me

# Unload the kernel module again
adb shell rmmod aosp_training_sysfs

Integrate kernel module into AOSP source tree

To include your kernel modules in the AOSP build for the cuttlefish device, we need to tell the build system about them. First, we want to copy the modules to the AOSP tree, to the vendor/inovex folder:

cd ~/android
mkdir -p vendor/inovex
cp ~/kernel-gki-android15-6.6/bazel-bin/vendor/inovex/kernel-module/training_mod/aosp_training*.ko vendor/inovex

In the next step, the build system needs to be told to include these modules. For the cuttlefish device, this is controlled by the device/google/cuttlefish/shared/BoardConfig.mk file. Here we can add our module to be included for cuttlefish.

Looking at the documentation by Google we see that a variable named BOARD_VENDOR_KERNEL_MODULES is used.

So at the end of device/google/cuttlefish/shared/BoardConfig.mk add:

BOARD_VENDOR_KERNEL_MODULES += \
    vendor/inovex/aosp_training_sysfs.ko

and run m. After building the system, restart the CVD. The modules should then be available and loaded automatically:

adb root

# Let's see if our modules are actually providing the expected information in sysfs:
adb shell cat /sys/kernel/aosp_training/read_me

B07a: Inspect the Package Manager

Inspect the output of the package manager for the installed packages. Use the following commands to answer some questions.

adb shell pm list packages
adb shell pm dump <package name> | less

Questions:

  • Where is the apk of preinstalled packages stored?
  • Where is the apk of your application that is installed later via adb install?
  • What does the SYSTEM flag mean?
  • How do you know which applications are privileged?

B07b: Inspect SELinux Actions During Runtime

SELinux error messages are rate-limited after boot complete to avoid swamping the logs.

To make sure you see all the relevant messages you can disable this by running:

adb shell auditctl -r 0

https://source.android.com/docs/security/features/selinux/validate

logcat | grep avc

adb shell su root dmesg | grep 'avc: '

Info

AVC stands for Access Vector Cache in SELinux context. It contains cached decisions to increase performance by not re-evaluating the policy rules for every call.

Note

If the output of the above command is empty, restart your device. When your device runs without activity for a long time, there are no SELinux errors.

# Switch adb to root powers
adb root

# Switch to permissive mode
adb shell setenforce 0

# Get current mode
adb shell getenforce

# Use audit2allow
adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy

# To use audit2allow you may have to install it first:
apt install policycoreutils-python-utils

SELinux and Native Service

In case you attempted the optional step 5 of the native service exercise, you may have encountered this error message:

Control message: Could not ctl.start for 'demo_service' from pid: 2592 (start demo_service): File /system/bin/demo(labeled "u:object_r:system_file:s0") has incorrect label or no domain transition from u:r:init:s0 to another SELinux domain defined. Have you configured your service correctly? https://source.android.com/security/selinux/device-policy#label_new_services_and_address_denials. Note: this error shows up even in permissive mode in order to make auditing denials possible.

As the error message suggests, setenforce 0 will not save us here. So let's add some rules to allow the service to run with SELinux in enforcing mode. Add or alter the following files in this directory: device/google/cuttlefish/shared/sepolicy/system_ext/private

demo.te contains the rules for our service:

type demo_service_server, domain;
type demo_service_server_exec, system_file_type, exec_type, file_type;

# Service on system partition:
typeattribute demo_service_server coredomain;

init_daemon_domain(demo_service_server)

# Allow it to add itself as the system service:
add_service(demo_service_server, demo_service);

# Register the system service with the service manager:
type demo_service, app_api_service, ephemeral_app_api_service, service_manager_type;

# Allow it to be a binder service:
binder_use(demo_service_server)
binder_service(demo_service_server)

file_contexts tells SELinux which context the executable we install for our service belongs to. Add the following line to the already existing file:

/system_ext/bin/demo u:object_r:demo_service_server_exec:s0

And service_contexts maps the service name our demo service provides to a context. Add the following line to the already existing file:

demoservice u:object_r:demo_service:s0

If you have not added it previously in the optional Step 5 of the native service exercise, also add the line PRODUCT_PACKAGES += demo demo-client.

If you have not attempted Step 5, here is a demo.rc init file for our service:

service demo_service /system_ext/bin/demo
     interface aidl demoservice
     class main
     user root

And to include it in the build, add the line init_rc: [ "demo.rc" ], in the cc_binary section for the demo executable in Android.bp

Then rebuild the system images and reboot. The demo service should now be started automatically and you can use demo-client hello without having to start it manually.

B08a: Inspect VHAL

Where's the VHAL?

Try to find it with lshal:

adb shell lshal

# Commonly found command isn't working?!
adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle

Small note in the docs: The above command is for HIDL VHAL.

Let's try the AIDL service version:

adb shell \
    dumpsys android.hardware.automotive.vehicle.IVehicle/default
    [--help]
    [--get <PROP_ID>]
    []

Works!

Using the HAL service

To see all options, use

adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/default --help

Let's check some common property values, like the VIN. The property ID of the VIN can be found in the file: hardware/interfaces/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl

To dump a single property, use

adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/default --get <id>

and replace <id> with the property id.

Is there an easier way to find out property ids?

Also try to set a property. Read the output of --help to find out the argument syntax.

Using the car_service

The car_service offers lots of commands that also can be invoked through dumpsys. You can get a list of commands via:

adb shell dumpsys car_service help

For instance, to get the same VIN information as in the previous step, you could also use:

adb shell dumpsys car_service get-property-value INFO_VIN

To see a full list of outputs use

adb shell dumpsys car_service

Check how you can interact with it using dumpsys!

B08b: Try Monitor App

In this example you try out the User Switch Monitor App described in the AAOS slides.

Install

First build the application

m -j24 UserSwitchMonitorApp

Then see the output on the console. It's built and put into the directory

out/target/product/vsoc_x86_64_only/system/priv-app/UserSwitchMonitorApp/UserSwitchMonitorApp.apk

Install the application and grant the necessary runtime permission:

adb install --user 0 $OUT/system/priv-app/UserSwitchMonitorApp/UserSwitchMonitorApp.apk
adb shell pm grant --user 0 com.google.android.car.userswitchmonitor android.permission.INTERACT_ACROSS_USERS

Run

Start the (foreground) service

adb shell am start-foreground-service --user 0 com.google.android.car.userswitchmonitor/.UserSwitchMonitorService

Now the app is running and the service within the application has started. See the tag mentioned in the logcat output

adb logcat -s UserSwitchMonitor

Also, see the dumpsys output of the service.

adb shell dumpsys activity service com.google.android.car.userswitchmonitor/.UserSwitchMonitorService

Try it Out

Next, try a user switch in the running Android system. In the top right corner you can switch between the Driver and the Guest user.

Do this now and re-execute the logcat and dumpsys commands. You should see additional log messages and events.

Extra Tasks

Locate the source code of the application in the source tree. E.g., the function that prints the output seen in the dumpsys command. Use both: cs.android.com and the local source tree.

Tip

Use a string that is printed on the console as a search term.

Also, try to use the mgrep and godir commands in the AOSP build environment.

Also, locate the AndroidManifest.xml and review the (foreground) service definition used for am start-foreground-service.

And question: What is the difference between the folder /system/priv-app and /system/app/ in the system partition?

Note

If you write your own native or (foreground) service, add a dumpsys debug interface. It's super useful to query the internal state of our service on the command line adb.

B08c: Exercise: Use Vehicle Properties

In this exercise you are going to access vehicle properties from an Android application.

In case you have not done so already, clone the example repository to your local machine:

git clone https://github.com/inovexAcademy/aosp-aaos-training

In the folder app-automotive/, an Android example application is prepared.

Attach Android Studio to Cuttlefish

In the previous exercise you've built and copied the apk to the virtual machine and installed the application by hand on the command line. To speed up your development cycle, you can attach Android Studio to the cuttlefish device via adb over an additional ssh forward.

To do so, open the ssh configuration file and add/edit the following line

LocalForward 5038 localhost:5037 # for adb

Note

Please take attention to the different port numbers. The remote port 5037 is forwarded to the local port 5038.

Then restart your ssh connection to the cloud instance.

Now reconfigure Android Studio:

  • Click on File -> Settings
  • Search for adb
  • In Adb Server lifecylce management enable Use existing manually managed server and use the port 5038.
/images/android-studio-adb-settings.png

Note

When using forwarded ADB ports, sometimes installation of an App fails or hangs in Android Studio and cannot be recovered without a restart of Android Studio.

ADB and the port forwarding usually still work correctly and Android Studio's logcat viewer is functional as well.

You could also use the forwarded ADB port manually in a Terminal (including the one built-in into Android Studio). Simply add the port argument to the adb commands you are already familiar with or set an environment variable:

# Either add -P 5038 to all adb calls, for instance:
adb -P 5038 install myapp.apk

# or set the environment variable and skipp the port argument:
export ANDROID_ADB_SERVER_PORT=5038
adb install myapp.apk

Preface

The Automotive APIs of Android are not part of core Android APIs for applications. They are located in additional libraries.

When developing a production-ready Android Application, you will be using the Car API provided by Android Jetpack. See Car App.

Info

Previously these libraries were also called Android Support Libraries. Nowadays they are called Jetpack and the Java methods and classes reside in the androidx namespace.

Android App developers use these libraries to abstract over different versions of Android.

In this exercise you use the Car API that is exposed in the Android SDK directly. On the page developer.android.com: android.car your find the API reference.

How do the Jetpack library and the Car API relate?

For example the two Java classes

do roughly the same thing. They can connect to the service on the device and return the CarManagers/CarServices. And the CarContext Java class is using the Car API internally.

Build the Application

Open the application in the folder app-automotive/ with Android Studio.

Take a look at the app-automotive/app/build.gradle.kts. That file contains the line

useLibrary("android.car")

This means that the uses-library XML tag is added to the Android Manifest file. When the application starts on the device, the Car Java library is loaded into the application and the Car API is available.

Navigate into the file MainActivity.java and look for the function setupUI(). Here you should add your code.

First let the instructor show you the basics of the code setup.

Use Our First Vehicle Property

In this section you should add the necessary code to query the vehicle property INFO_MODEL.

Every vehicle property is protected by an Android permission. Search in AOSP sources in the folders

  • packages/services/Car/ and
  • hardware/interfaces/automotive/

and find out which permission is needed.

Add this permission in a uses-permission XML tag to the AndroidManifest.xml. An example code line:

<uses-permission android:name="<permission name>" />

<application [...]

Furthermore, every vehicle property has an area type. Search the two directories again and find out what the correct area type is.

Then find out the type of the property. E.g., whether it's an integer, float or string.

After that use the CarPropertyManager to retrieve the value of the property and set it in the TextView.

Code template for setupUI():

variable = [Add the code for the CarPropertyManager here]
textViewModel.setText("Model: " + <variable>);

Rebuild and rerun the application and see the results.

Debugging tips:

  • Use logcat -c to clear the log cat buffer. This avoids seeing older and unrelated log messages from a previous instance of your application.
  • Use alogview to only see the logcat buffer of your application.

Changing the Vehicle Property

The previous chapter already mentioned that you can query and set vehicle properties in the car service and in the VHAL.

adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/default --set 0x11100102 -s new-model

If you see the error

Error with service 'android.hardware.automotive.vehicle.IVehicle/default' while dumping: FAILED_TRANSACTION

execute adb root to restart the adb daemon on the device with root privileges.

Note

using adb root only works in userdebug and eng build variants.

After that you should be able to set the property successfully.

You can query the value of the property that is saved in the VHAL with

adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/default --get 0x11100102

The INFO_MODEL vehicle property is a static property. Therefore, the car services does not get notified when this property is changed in the VHAL. The car service even implements a caching layer for the static properties. See the file and code packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java.

To see the new value of INFO_MODEL in the application, you have to restart the car sevice. Use

adb shell pkill com.android.car

Since the application has implemented the onLifecycleChanged() listener, the application will auto reconnect to the car service. If you start logcat with adb shell logcat -s MainActivity:*, you will see the following output

I MainActivity: onLifecycleChanged: ready=false
I MainActivity: onLifecycleChanged: ready=true
D MainActivity: model=new-model
D MainActivity: currentGear=4
D MainActivity: onChangeEvent: gear=4

Also look at the Activity of your application. It also shows the new model string now.

Changing a Non-Static Vehicle Property

In the previous chapter a static vehicle property was used. Now add the dynamic property CURRENT_GEAR to the application.

Again search for the permission, the area type and the type of the value.

Since the property is non-static, use CarPropertyManager to register a callback that listens for events with property changes.

Note

There are three different "categories" of functions that allow registering callbacks. Some are complicated and use lists of property requests, some are deprecated. Stick to the most simple variant.

There are multiple ways to implement the solution. You could either follow the pattern already present in the implementation or use a more idiomatic approach. If you're stuck, don't hesitate to ask for help.

Remember, that updating the view should happen on the UI thread. You may use the following line in your callback code:

runOnUiThread(() -> textViewGear.setText("Gear: " + <variable>));

To inject a new value for the property, use the following command

adb shell dumpsys car_service inject-vhal-event 0x11400401 0 0x10
adb shell dumpsys car_service inject-vhal-event 0x11400401 0 0x20
adb shell dumpsys car_service inject-vhal-event 0x11400401 0 0x40

You should observe how the value on the screen is changing while the app is running.

Further reading

On the page Vehicle hardware abstraction layer you can read more about the hardware abstraction layer.

B10: Exercise: Create your own product

In this exercise you will create your own product and lunch target.

Add product

Create a new device tree directory

mkdir -p device/mycompany
cd device/mycompany

In this directory create a AndroidProducts.mk file with the content

PRODUCT_MAKEFILES := \
    aosp_my_x86_64:$(LOCAL_DIR)/aosp_my_x86_64.mk

COMMON_LUNCH_CHOICES := \
    aosp_my_x86_64-trunk_staging-userdebug

Create a aosp_my_x86_64.mk file with the content

# Base this product on "aosp_cf_x86_64_auto"
$(call inherit-product, device/google/cuttlefish/vsoc_x86_64_only/auto/aosp_cf.mk)

PRODUCT_MANUFACTURER := MyCompany
PRODUCT_NAME := aosp_my_x86_64
PRODUCT_MODEL := My Device Model
# This must match a existing BoardConfig.mk within the boards/$(PRODUCT_DEVICE) subfolder.
PRODUCT_DEVICE := my_aosp_auto

Create a BoardConfig.mk within the board\my_aosp_auto subfolder, with the content:

-include device/google/cuttlefish/vsoc_x86_64_only/BoardConfig.mk

Now you can already build your new product.

Execute lunch. Your new device should appear.

Select and build it with:

lunch aosp_my_x86_64-trunk_staging-userdebug
m -j24

After building it, run the cuttlefish emulator again.

Check that your new product is running with

adb shell getprop | grep model
adb shell getprop | grep aosp_my

Check also the Settings application. Under System -> About your Model name should appear.

Add a system property

To add a custom system property to our product, add the following code to your product makefile called aosp_my_x86_64.mk:

PRODUCT_PRODUCT_PROPERTIES += \
     ro.mycompany.test=hello

Rebuild, rerun and test with

adb shell getprop ro.mycompany.test

Add a prebuilt application

In the directory device/mycompany/, next to aosp_my_x86_64.mk, file create a file called Android.bp with the content

android_app_import {
    name: "MyApp",
    presigned: true,
    preprocessed: true,
    apk: "app-debug.apk",
}

Upload the app-debug.apk into the same directory.

Info

The Soong API reference can be found here.

Be aware that this is for a specific Soong release. If you need the reference for your local AOSP build, checkout the Soong README file that is usually found in the build/soong folder of the AOSP tree.

Add the following code to your product makefile called aosp_my_x86_64.mk:

PRODUCT_PACKAGES += \
    MyApp

Rebuild, rerun and test with

adb shell find /system -name MyApp.apk
adb shell pm dump de.inovex.aosptraining | less

The SYSTEM flag should be set now and the apk location on the system partition.

M: Media/Graphics Exercises

This page contains subpchages for the graphics exercises.

Using perfetto

Create a virtual device in Android Studio. In this training you should use a Medium Phone with a x86_64 image and API level 35. See the image

/images/virtual-device.png

Clone the example repository:

git clone https://github.com/inovexAcademy/aosp-aaos-training

Open the Android Application in the subfolder app-graphics in Android Studio.

Start the virtual device and build and deploy the SimpleUIUpdateActivity to the device.

Open https://ui.perfetto.dev/.

  • For Linux use ADB + Websocket proxy.
  • For Windows see the instructions at the end of the page.

Select the following trace sources

  • CPU -> Scheduling Details
  • Android apps & svcs -> Atrace userspace annotations (select all and Record events from all Android apps and Services)
  • Android apps & svcs -> Frame timeline
  • Advanced Settings -> Advanced ftrace config
  • Advanced Settings -> Process<>thread association

Then trace for a few seconds.

Inspect the results for the example application.

See

  • the different lanes for the different threads
  • the thread states (running, runnable, sleeping)
  • the existing atrace tags
  • the search bar on top
  • a binder flow event
  • the pin feature

Now enable the two predefined atrace tags in the SimpleUIUpdateActivity of the example application. Rebuild and rerun the application and trace again. You should see the new atrace tags in the trace.

Special Instructions for Windows

ADB + Websocket does not support Windows and the emulator is not connected via USB to your computer (like a normal phone). So the option WebUSB also does not work. Instead you must start perfetto manually with the following instructions:

  • Select the perfetto tracing options as described above.

  • Go to Cmdline instructions in the Perfetto UI.

  • Copy the configuration named config.pbtx.

  • Go into the platform-tools directory that contains the adb program.

  • Create a file called perfetto.txt there. Paste the configuration content into it and save the file.

  • Now start a shell window. It can be the traditional cmd or a Windows PowerShell.

  • Change directory into the platform-tools directory.

  • Execute the command was shown into Perfetto UI, but adapt it to Windows. Example:

    type perfetto.txt | .\adb shell perfetto -c - --txt \
        -o /data/misc/perfetto-traces/trace.pftrace
    
  • After tracing has finished, copy the trace results to your computer using adb pull. Example:

    .\adb pull /data/misc/perfetto-traces/trace.pftrace
    
  • Now open the file trace.pftrace in the Perfetto UI.

Finding APIs

In this exercise three groups should find and talk (a bit) about Android APIs for media.

Split in three groups and search for

  • Group 1: Audio APIs
  • Group 2: Video APIs
  • Group 3: DRM (Digital Rights Management)
  • Group 4: Camera APIs

and make a summary of interesting findings and notes.

Use the Android Documentation for Developers and your favorite search engine.

Appendix - Working with emulators

Install a custom car emulator. See Add system images from OEMs on developer.android.com:

/images/configure_android_sdk_tools.png /images/configure_sdk_update_sites.png /images/select_target_hardware.png /images/select_system_image.png
QT_QPA_PLATFORM='wayland;xcb' emulator -list-avds

QT_QPA_PLATFORM='wayland;xcb' emulator @Honda_IVI-SYSTEM_API_30