// 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 /* */ /* 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: 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 bazel 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 bazel 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 bazel run :nexus_s -- --action=start. The script exposes the following flags:

*/