A guide on how to get up and running with a DownLoadable Content (DLC).
go/dlc-framework to see if DLC is right the right use case. (If you already know enough about DLCs and is a clear solution for you, please jump right in)
DLC allows ChromeOS developers to ship a feature (e.g. a ebuild/package) to stateful partition as packages (ebuilds) and provides a way to download at runtime.
The steps for developing a DLC involves the following:
A DLC involves adding a portage package (ebuild). The package file should inherit dlc.eclass.
(Note: modifying a DLC requires upreving the package)
See an example DLC: scaled-dlc ebuild
Within the package, must include the src_install
function to install the DLC content using a special path prefix set by $(dlc_add_path )
. This means, that before installing any DLC files, you have to add the dlc prefix path to into, insinto
and exeinto
using $(dlc_add_path your_path)
. Always call dlc_src_install
at the end of your src_install
function to pack the DLC.
The following variables must/can be set:
DLC_PREALLOC_BLOCKS
- The number of blocks to reserve for A/B copies of a DLC. Each block is 4KiB. It is necessary to set this value more than the minimum required to accommodate future size growth (recommendation is 130% of the DLC size).DLC_SCALED
- All new DLCs should be scaled. In the future this value will be on by default. Please set this to true
.DLC_ID
- The unique ID, requirements:-
(dash).${PN}
)DLC_DESCRIPTION
- Human reable description of the package. Override iff the default ${DESCRIPTION}
is not enough to describe purpose. (Default is ${DESCRIPTION}
)DLC_PACKAGE
- deprecated, do not use. (Default is package
)DLC_NAME
- Name of the DLC. It is for description/info purpose only. (Default is ${PN}
)DLC_VERSION
- Version of the DLC. It is for description/info purpose only. (Default is ${PVR}
)DLC_PRELOAD
- Preload the DLC. When set to true, the DLC will be preloaded (pre-installed) for test images. Should only be set if tast/tauto tests run for features depending on the DLC. (Default is false)DLC_ENABLED
- Override being a DLC. When set to false, $(dlc_add_path)
will not modify the path and everything will be installed into the rootfs instead of the DLC path. This allows the use of the same ebuild file to create a DLC under special conditions (i.e. Make a package a DLC for certain boards or install in rootfs for others). (Default is true)Installing a DLC on a device is similar to installing a portage package (ebuild):
emerge-${BOARD} <DLC_ID>
cros deploy ${IP} <DLC_ID>
Once your ready to enable your DLC, you can target enabling the DLC package selectively behind your own USE flags or at the top level target-chromium-os package to be enabled across all ChromeOS devices behind the main dlc
USE flag.
Note: if you need to enable a DLC selectively per board, you must do so using your own USE flag.
Permitted ash chrome or system daemons that can access D-Bus can call dlcservice APIs to install/uninstall a DLC.
A DLC is downloaded and installed at runtime by dlcservice and will return a root mount path for the DLC when installed.
This root mount path should **NEVER** be hardcoded/cached/persisted across reboots.
This warrants always requesting to install the DLC before use at all times. The DLC will remain mounted as long as the device or UI (ash chrome) does not restart. It is completely up to dlcservice to return any type of root mount paths in the future, but the root will always be suffixed at /run/imageloader
.
If your service/daemon uses minijail, you will have to:
MS_BIND|MS_REC
) /run/imageloader/
by passing the parameter -k
to minijail.-v -Kslave
to allow propagation of the mount namespace of the mounted DLC image to your service.If your service/daemon also starts on starting system-services
:
and started dlcservice
.On a locally built test build|image, calling dlcservice API does not download the DLC (no DLC is being served), unless the DLC is preloaded using Write tests dependent on a DLC. For local development, please follow Building a DLC locally.
In order to test a DLC dependent feature, the optional variable field DLC_PRELOAD
needs to be set to true while the integration/tast tests invoke installing the DLC. This will allow tests to seamlessly install the DLC on test images.
There is ongoing effort to tie DLC provisioning into the ChromeOS test run as part of OS provisioning. Also, there are gRPC services that tast/tauto tests can directly invoke to provision a DLC - there however isn't a client that nicely wraps all of this for the test writer at the moment.
Currently, DLCs can be installed without policy checks. This poses a security risk, as code paths or flows that depend on the existence of DLCs could be inadvertently executed or triggered, potentially leading to unexpected behavior or vulnerabilities.
To mitigate this risk, for DLCs that enforce installation behind a policy, we strongly recommend that developers avoid relying on code paths or flows that depend on the existence of DLCs. Ensure that DLCs are only installed when authorized (as needed) and that any code paths or flows that depend on them are executed only under controlled conditions.
Blockling of DLC installation is avaialble in crosh, but is not enforced at the system service level.
You don't, our infrastructure will handle all this for you.
This is fundamentally not possible with DLCs, just as developers are tied to release process, DLCs are too.
Note: in the case of scaled DLCs, all release builds can install the DLC OTA, while legacy DLCs are strictly tied to releases that go live.
Modifying a DLC is the same as modifying a portage package (ebuild). A DLC is updated at the same time the device itself is updated.
Note: in the case of scaled DLCs, it will not update with the OS at the moment.
If you are using a developer-built image, you cannot easily install DLC from production servers. Instead, you should use preloading or deploy the DLC package.
The DLC that has preloading enabled must first be uninstalled. Uninstall the DLC using the utility binary: dlcservice_util --uninstall --id=<DLC_ID>
.
Next step is to wipe the preloaded DLC on your test image device. You can remove the preloaded directory for your DLC at /var/cache/dlc-images/<DLC_ID>
.
If your DLC is a scaled DLC, you can proceed with the DLC installation and be on your way.
If your DLC is a legacy DLC, you must modify your ChromeOS lsb-release to fake being a signed device. This must be done by disabling rootfs verification and adding a -signed
suffix to the key CHROMEOS_RELEASE_BOARD
.
e.g. the key should look like CHROMEOS_RELEASE_BOARD=<BOARD>-signed
.
Also, for legacy DLCs, this will only work for “live” images (ChromeOS builds that were pushed).