// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.rules.android;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
import static com.google.devtools.build.lib.syntax.Type.INTEGER;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.analysis.whitelisting.Whitelist;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.rules.java.JavaSemantics;
/** Rule definition for android_device. */
public final class AndroidDeviceRule implements RuleDefinition {
@Override
public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
return builder
/*
name_images/userdata.dat
:
Contains image files and snapshots to start the emulator
name_images/emulator-meta-data.pb
:
Contains serialized information necessary to pass on to the emulator to
restart it.
*/
/*
The vertical screen resolution in pixels to emulate.
The minimum value is 240.
*/
.add(attr("vertical_resolution", INTEGER).mandatory())
/*
The horizontal screen resolution in pixels to emulate.
The minimum value is 240.
*/
.add(attr("horizontal_resolution", INTEGER).mandatory())
/*
The amount of ram in megabytes to emulate for the device.
This is for the entire device, not just for a particular app installed on the device. The
minimum value is 64 megabytes.
*/
.add(attr("ram", INTEGER).mandatory())
/*
The density of the emulated screen in pixels per inch.
The minimum value of this is 30 ppi.
*/
.add(attr("screen_density", INTEGER).mandatory())
/*
The size in megabytes of the emulator's cache partition.
The minimum value of this is 16 megabytes.
*/
.add(attr("cache", INTEGER).mandatory())
/*
The size in megabytes of the virtual machine heap Android will use for each process.
The minimum value is 16 megabytes.
*/
.add(attr("vm_heap", INTEGER).mandatory())
/*
A filegroup containing the following files:
- system.img: The system partition
- kernel-qemu: The Linux kernel the emulator will load
- ramdisk.img: The initrd image to use at boot time
- userdata.img: The initial userdata partition
- source.properties: A properties file containing information about the
images
These files are part of the android sdk or provided by third parties (for
example Intel provides x86 images).
*/
.add(attr("system_image", LABEL).mandatory().legacyAllowAnyFileType())
/*
A single properties file to be placed in /default.prop on the emulator.
This allows the rule author to further configure the emulator to appear more like
a real device (In particular controlling its UserAgent strings and other
behaviour that might cause an application or server to behave differently to
a specific device). The properties in this file will override read only
properties typically set by the emulator such as ro.product.model.
*/
.add(attr("default_properties", LABEL)
.cfg(HostTransition.INSTANCE)
.allowedFileTypes(JavaSemantics.PROPERTIES))
/*
A list of apks to be installed on the device at boot time.
*/
.add(attr("platform_apks", LABEL_LIST).legacyAllowAnyFileType())
// Do not pregenerate oat files for tests by default unless the device
// supports it.
.add(attr("pregenerate_oat_files_for_tests", BOOLEAN).value(false))
.add(
attr("$adb_static", LABEL)
.cfg(HostTransition.INSTANCE)
.value(env.getToolsLabel("//tools/android:adb_static")))
.add(attr("$adb", LABEL)
.cfg(HostTransition.INSTANCE)
.value(env.getToolsLabel("//tools/android:adb")))
.add(
attr("$emulator_arm", LABEL)
.cfg(HostTransition.INSTANCE)
.value(env.getToolsLabel("//tools/android/emulator:emulator_arm")))
.add(
attr("$emulator_x86", LABEL)
.cfg(HostTransition.INSTANCE)
.value(env.getToolsLabel("//tools/android/emulator:emulator_x86")))
.add(
attr("$emulator_x86_bios", LABEL)
.cfg(HostTransition.INSTANCE)
.value(env.getToolsLabel("//tools/android/emulator:emulator_x86_bios")))
.add(
attr("$mksd", LABEL)
.cfg(HostTransition.INSTANCE)
.exec()
.value(env.getToolsLabel("//tools/android/emulator:mksd")))
.add(
attr("$empty_snapshot_fs", LABEL)
.cfg(HostTransition.INSTANCE)
.value(env.getToolsLabel("//tools/android/emulator:empty_snapshot_fs")))
.add(
attr("$xvfb_support", LABEL)
.cfg(HostTransition.INSTANCE)
.value(env.getToolsLabel("//tools/android/emulator:xvfb_support")))
.add(
attr("$unified_launcher", LABEL)
.cfg(HostTransition.INSTANCE)
.exec()
.value(env.getToolsLabel("//tools/android/emulator:unified_launcher")))
.add(
attr("$android_runtest", LABEL)
.cfg(HostTransition.INSTANCE)
.exec()
.value(env.getToolsLabel("//tools/android:android_runtest")))
.add(
attr("$testing_shbase", LABEL)
.cfg(HostTransition.INSTANCE)
.value(env.getToolsLabel("//tools/android/emulator:shbase")))
.add(
attr("$sdk_path", LABEL)
.cfg(HostTransition.INSTANCE)
.exec()
.value(env.getToolsLabel("//tools/android/emulator:sdk_path")))
.add(
attr("$is_executable", BOOLEAN)
.value(true)
.nonconfigurable("Called from RunCommand.isExecutable, which takes a Target"))
.add(
Whitelist.getAttributeFromWhitelistName(AndroidDevice.WHITELIST_NAME)
.value(env.getToolsLabel("//tools/android:android_device_whitelist")))
.removeAttribute("deps")
.removeAttribute("data")
.build();
}
@Override
public Metadata getMetadata() {
return RuleDefinition.Metadata.builder()
.name("android_device")
.ancestors(BaseRuleClasses.RuleBase.class)
.factoryClass(AndroidDevice.class)
.build();
}
}
/*
This rule creates an android emulator configured with the given
specifications. This emulator may be started via a blaze run
command or by executing the generated script directly. It is encouraged to depend
on existing android_device rules rather than defining your own.
This rule is a suitable target for the --run_under flag to blaze test and blaze
run. It starts an emulator, copies the target being tested/run to the emulator,
and tests it or runs it as appropriate.
android_device
supports creating KVM images if the underlying
system_image is X86 based and is
optimized for at most the I686 CPU architecture. To use KVM add
tags = ['requires-kvm']
to the android_device
rule.
${IMPLICIT_OUTPUTS}
Examples
The following example shows how to use android_device.
//java/android/helloandroid/BUILD
contains
android_device(
name = "nexus_s",
cache = 32,
default_properties = "nexus_s.properties",
horizontal_resolution = 480,
ram = 512,
screen_density = 233,
system_image = ":emulator_images_android_16_x86",
vertical_resolution = 800,
vm_heap = 32,
)
filegroup(
name = "emulator_images_android_16_x86",
srcs = glob(["androidsdk/system-images/android-16/**"]),
)
//java/android/helloandroid/nexus_s.properties
contains:
ro.product.brand=google
ro.product.device=crespo
ro.product.manufacturer=samsung
ro.product.model=Nexus S
ro.product.name=soju
This rule will generate images and a start script. You can start the emulator
locally by executing blaze run :nexus_s -- --action=start. The script exposes
the following flags:
- --adb_port: The port to expose adb on. If you wish to issue adb
commands to the emulator this is the port you will issue adb connect
to.
- --emulator_port: The port to expose the emulator's telnet management
console on.
- --enable_display: Starts the emulator with a display if true (defaults
to false).
- --action: Either start or kill.
- --apks_to_install: a list of apks to install on the emulator.
*/