Managing applications

Applications are one of the main objects AMS manages. A single application encapsulates one Android application and manages it within the cluster. It takes care about installing the supplied application package (Android Package Kit - APK), to make it available to users. Further AMS manages updates to existing applications which includes allowing the operator to give new uploaded versions a test run before making them available to any users.

Application Requirements

In order to run on the Anbox Cloud platform applications need to fulfill a set of requirements. These are:

  • Application SHOULD not download any additional resources on regular startup to contribute to short startup times. If additional resources need to be downloaded this can be done during the application bootstrap phase.
  • Application MUST NOT require the Google Play services to be available as Anbox Cloud does not include them.
  • Application MUST NOT require cellular data or telephony services, although WiFi is supported.

If the application fulfils all of the requirements above it is ready to run on the Anbox Cloud platform. If not, please file a bug report so that we can find out what we can do to still support the application.

Create Applications

Every application which should be available on an Anbox Cloud cluster has to be created first. The internal process will prepare a container based on the currently available image with the application package installed and will use that for any newly launched containers to support fast boot times.

Preparation

To create an application a Android package (APK) is needed with support for the target architecture. Additionally one of the available instance types has to be selected for the application which defines CPU/RAM constraints put onto the container launch for the application.

Note: See chapter Available Instance Types for a list of available instance types.

In order to create a new application a manifest file has to be written first to define the various attributes the new application should have. The manifest is a simple YAML file and looks like this:

name: candy
instance-type: a2.3
image: default
boot-activity: com.canonical.candy.GameApp
required-permissions:
  - android.permission.WRITE_EXTERNAL_STORAGE
  - android.permission.READ_EXTERNAL_STORAGE
addons:
  - ssh
tags:
  - game
extra-data:
  com.canonical.candy.obb:
    target: /data/app/com.canonical.candy-1/lib
  game-data-folder:
    target: /sdcard/Android/data/com.canonical.candy/
watchdog:
  disabled: false
  allowed-packages:
    - com.android.settings
services:
  - name: adb
    port: 5559
    protocols: [tcp]
    expose: false
resources:
  memory: 4GB
  disk-size: 8GB

The available attributes are listed in the following table:

Name Value type Description
name string Verbose name of the application, A few special characters are not allowed: ‘< > : " / \ | ? *’, as well as space
version string Version to encode with the application. Maximum length is 50 characters
instance-type string Container instance type all containers created for the application will use
required-permissions array of strings List of permissions to automatically grant to the application. See Android Permissions for a list of available permissions. If [*] was given, all required runtime permissions for the application will be granted on application installation
image (optional) string Name or ID of an image to be use for the application. Default image is used if empty
addons (optional) array List of addons to be installed during the application bootstrap process
tags (optional) array List of tags to be associated with the application
boot-package (optional) string Package to launch once the system has booted (default: package name retrieved from the apk if apk file is present)
boot-activity (optional) string Activity of boot package to launch once the system has booted (default: Main activity as defined in the application manifest)
video-encoder (optional) string Video encoder to be used by a container launched from the application (default: gpu-preferred)
watchdog (optional) map Watchdog settings to be configured on application installation
services (optional) array Services to be provided from the installed application
resources (optional) map Resources to be allocated on application installation
extra-data (optional) array List of additional data to be installed on application installation
abi (optional) string The preferred ABI for the application creation if the provided APK is a universal APK
version (optional) string a free-form version field which allows users to identify which application version is based on which APK version
inhibit-auto-updates (optional) boolean inhibit application automatic updates even if its dependencies (addons or image) get updated (default: false)

Video Encoder

A video encoder type can be specified through video-encoder field in the manifest file when creating an application so that a container launched from the application can use a GPU or software video encoder according to different scenarios.

Name Description
gpu a GPU-based video encoder
gpu-preferred a GPU-based video encoder if gpu slots are not used up, otherwise it fallbacks to use software-based video encoder
software a software-based video encoder

When gpu video encoder is specified in the manifest, AMS can fail to create an application if

  • GPU slots are used up by running containers
  • No GPU support across the entire lxd cluster

Watchdog Settings

The watchdog attribute includes the following field definitions:

Name Value type Description
disabled boolean Toggle application watchdog on or off (default: false)
allowed-packages array of strings Besides boot package, list of packages to be allowed to display in the foreground

When a container is launched, Anbox enables an application watchdog by default for the installed
package unless it’s disabled explicitly with:

name: candy
instance-type: a2.3
image: default
watchdog:
  disabled: true

If one of the following scenarios occurs, the watchdog will be triggered. The container will be terminated and ends up with error status.

  • The application crashes or an ANR is triggered
  • The application is not in the foreground when an application which is not listed in allowed-packages
    was brought into the in the foreground and gained the focus
  • The boot package or activity is invalid
  • One of the allowed-packages is invalid

The rules forbid launching another activity, not part of the installed package or listed allowed packages. Launching activities of the same package is allowed.

Supplying ['*'] to the allowed-packages when the watchdog is enabled allows any application
can be display in the foreground without triggering a watchdog.

Services

A container launched from the installed application can expose services you want to make accessible from outside the container. You must define the following properties for each service.

Name Value type Description
name string Name of service
port integer Port number to be exposed by the service
protocols array of strings Protocols to be used by the service (Possible values are: tcp, udp)
expose boolean Expose service to be accessible externally or internally

Resources

If the instance-type that is provided by AMS doesn’t meet the criteria that the installed application requires to function, you can make use of resources directive to override the predefined resources in instance-type.

Name Value type Minimum value Description
cpus integer 1 Number of vcpu cores
memory string 3GB Memory to be assigned to the application
disk-size string 3GB Disk size to be assigned to the application
gpu-slots(optional) integer 0 number of gpu slots to be assigned to the application

In the following application manifest file, the application is created with a2.3 instance-type, which will be assgined 2 vcpu cores, 3GB memory and 3GB disk size. With the following resources supplied to manifest file:

name: candy
instance-type: a2.3
resources:
  memory: 4GB
  disk-size: 8GB

The allocated memory and disk size will end up to 4GB and 8GB respectively on application installation and the number of vcpu cores remains the same. If all required fields(cpus/memory/disk-size) of resources are supplied in the application manifest, the instance-type field is no longer needed. Even if the instance-type field is provided, it will be overridden by resources in the end upon application installation.

Extra Data

Some Android applications which contain large program assets such as graphics, media files use so called OBB files to store additional data. These data files are separated from the APK and saved onto the external or internal SD card of an Android device. The extra-data field can be used in this case to install an APK with separated OBB files or any other additional data into the Android system.

Each item of extra-data should be declared as follows:

<name>:
    target: <target-path>
    owner:  <uid>:<gid> # optional
    permissions: <file-permission> # optional

The fields have the following purpose:

Name Value type Description
name string Name of file or directory to be installed into the Android filesystem
target-path string Target location for the file or directory
owner (optional) string Owner assigned to the target file or directory in the Android filesystem
permissions (optional) string Permissions assigned to the target file or directory in the Android filesystem

permissions represents Linux file permissions in octal notation.

It’s recommended to let Anbox choose the right values for owner and permissions instead of manually providing them. If owner and permissions are not specified, the following default values will be used:

Name App Data Installation Directory Type Value
owner sdcard File package_uid:sdcard_rw
sdcard Dir package_uid:sdcard_rw
system data File package_uid:package_gid
system data Dir package_uid:package_gid
permissions sdcard File 0660
sdcard Dir 0771
system data File 0660
system data Dir boot package folder -> 0700, nested folders of boot package folder -> 0770

Each item, e.g. file or folder, declared in the extra-data field of the manifest yaml file should be placed in a directory called extra-data.

For security reasons, the target location of the files and directories listed in the extra-data section is restricted to a few specific locations in the Android file system. These are:

  • /sdcard/Android/obb/<apk-package-name>
  • /sdcard/Android/data/<apk-package-name>
  • /data/app/<apk-package-name>
  • /data/data/<apk-package-name>

The image attribute defines which image the application is based on. If left empty, your application will be based on the default image. See Image Management for more details on this. Available images on your installation can be listed with the following command:

$ amc image list

The manifest and extra data in our example are placed next to the application package, which must be named app.apk:

$ tree
.
├── app.apk
├── extra-data
│   ├── com.canonical.candy.obb
│   └── game-data-folder
│       └── data.bin
└── manifest.yaml

From a Directory

When creating an application from the folder path, the location should contain the required components for the creation.

  • manifest.yaml
  • app.apk
  • extra-data (optional)

With everything in place the application can now be created:

$ amc application create <path/to/application-content>
applications:
- bcmap7u5nof07arqa2ag

When the create command returns the application package is uploaded to the AMS service and the bootstrap process was started. The application is not yet ready to be used. You can watch the status of the application with the following command:

$ amc application show bcmap7u5nof07arqa2ag
id: bcmap7u5nof07arqa2ag
name: candy
status: initializing
published: false
config:
  instance-type: a2.3
  boot-package: com.canonical.candy
versions:
  0:
    image: bf7u4cqkv5sg5jd5b2k0 (version 0)
    published: false
    status: initializing
    addons:
    - ssh
    boot-activity: com.canonical.candy.GameApp
    required-permissions:
    - android.permission.WRITE_EXTERNAL_STORAGE
    - android.permission.READ_EXTERNAL_STORAGE
    extra-data:
      com.canonical.candy.obb:
        target: /data/app/com.canonical.candy-1/lib
      game-data-folder:
        target: /sdcard/Android/data/com.canonical.candy/
    watchdog:
      disabled: false
      allowed-packages:
      - com.android.settings
    services:
    - port: 5559
      protocols:
      - tcp
      expose: false
      name: adb
resources:
  memory: 4GB
  disk-size: 8GB

Once the status of the application switches to ready the application is ready and can be used.

From a Tarball

An application can be also created from a tarball file. The tarball file has to be compressed with bzip2 and must follow the format of the application package as described before.

For example, a tarball can be created with:

$ tar cvjf foo.tar.bz2 -C <package-folder-path> app.apk extra-data manifest.yaml

Once the tarball is created you can proceed creating the application:

$ amc application create foo.tar.bz2
applications:
- bcmap7u5nof07arqa2ag

The AMS service now starts the application bootstrap process as described before.

Note: Due to Snap strict confinement, no matter which approach you’re going to take, the folder or tarball file must be located home directory

Bootstrap process

Whenever creating an application either from a directory or a tarball, AMS will perform a bootstrap process, which builds the application and synchronizes it across all LXD nodes in the cluster. There are major benefits the bootstrap process provides:

  • It enables AMS to launch a container for an application without installing the APK everytime
  • It dramatically speeds up startup time of a regular container

Furthermore an application is synchronized within the LXD cluster, which enables AMS continuing to work when nodes are being remove from the cluster through [Node Management] or lost from the cluster unexpectedly.

A temporary base container will be created and used for the bootstrapping during the application creation:

$ amc application create foo.tar.bz2
applications:
- bq789q0j1qm02cebmoeg
$ amc ls
+----------------------+-------------+------+----------+------+---------------+-----------+
|          ID          | APPLICATION | TYPE |  STATUS  | NODE |    ADDRESS    | ENDPOINTS |
+----------------------+-------------+------+----------+------+---------------+-----------+
| bq78a3oj1qm02cebmof0 |    candy    | base | prepared | lxd0 | 192.168.100.2 |           |
+----------------------+-------------+------+----------+------+---------------+-----------+

In general, the bootstrap process goes through the following steps in order:

  • Configure network interface and gateway
  • Apply any pending Ubuntu system security updates
  • Install addons via the install hook provided by each addon listed in the application manifest file
  • Launch Android container
  • Install the APK provided by the application
  • Grant the application permissions as requested in the application manifest
  • Install the extra data as listed in the application manifest
  • Execute the prepare hook provided by each addon listed in the application manifest

If one of the steps fails, AMS will interrupt the bootstrap process and make the entire process fail. As a result, the status of base container will be marked with error and the application’s status will end up with error as well.

Note: An application crash or ANR upon APK installation will cause the bootstrap process to terminate abnormally and the status of application is set to error too.

When a base container runs into an error status, you can see what has gone wrong there by checking the error message with:

$ amc show bq78a3oj1qm02cebmof0
id: bq78a3oj1qm02cebmof0
name: ams-bq78a3oj1qm02cebmof0
status: error
node: lxd0
created_at: 2019-08-09T02:11:33Z
application:
    id: bq6ktjgj1qm027q585kg
network:
    address: ""
    public_address: ""
    services: []
stored_logs:
- container.log
- system.log
- android.log
error_message: 'Failed to install application: com.foo.bar: Failed to extract native libraries, res=-113'
config: {}

Or show container logs which is useful for troubleshooting problems in a container.

If an application bootstrap succeeds, the base container will be automatically removed and the status of the application changes to ready and is ready to be used.

Wait for Applications

With amc wait command, it enables to wait for an application to reach a specific condition. If the condition is not satisfied within the specified time (5 minutes by default), a timeout error will be returned by AMS.

The supported conditions for an application are as follows:

Name Value
instance-type Supported instance type. See chapter Available Instance Types for a list of available instance types
addons Comma separated list of addons
tag Application tag name
publishd “true” or “false” which indicates if the application is published
immutable “true” or “false” which indicates if the application is changeable
status Application status, possible values: “error”, “unknown”, “initializing”, “ready”, “deleted”

One example of using amc wait command is to wait for the application bootstrap to be done since
the application bootstrap is performed asynchronously by the AMS service and takes some time to
process. The application can not be used until the bootstrap is complete and the status is marked
as ready.

$ amc wait -c status=ready bcmap7u5nof07arqa2ag

Update Applications

Updating an existing application works similar as creating a new one. Each time an existing application is updated it is extended with a new version. All versions an application currently has are individually usable but only one can be available to users.
When a new version of an application is available you have to update the application managed by the AMS service. As input you have to provide an updated tarball in the same format as described before. The amc application update command accepts both a directory and a direct path to a file.

From a directory:

$ amc application update bcmap7u5nof07arqa2ag $PWD/foo

From a file:

$ amc application update bcmap7u5nof07arqa2ag foo.tar.bz2

AMS will start the update process internally. You can watch the status of the new version with the following command:

$ amc application show bcmap7u5nof07arqa2ag
id: bcmap7u5nof07arqa2ag
name: candy
status: ready
published: false
config:
  instance-type: a2.3
  boot-package: com.canonical.candy
versions:
  0:
    image: bf7u4cqkv5sg5jd5b2k0 (version 0)
    published: false
    status: active
    addons:
    - ssh
    boot-activity: com.canonical.candy.GameApp
    required-permissions:
    - android.permission.WRITE_EXTERNAL_STORAGE
    - android.permission.READ_EXTERNAL_STORAGE
    extra-data:
      com.canonical.candy.obb:
        target: /data/app/com.canonical.candy-1/lib
      game-data-folder:
        target: /sdcard/Android/data/com.canonical.candy/
    watchdog:
      disabled: false
      allowed-packages:
      - com.android.settings
    services:
    - port: 5559
      protocols:
      - tcp
      expose: false
      name: adb
  1:
    image: bf7u4cqkv5sg5jd5b2k0 (version 0)
    published: false
    status: active
    addons:
    - ssh
    boot-activity: com.canonical.candy.GameApp
    required-permissions:
    - android.permission.READ_EXTERNAL_STORAGE
    - android.permission.READ_EXTERNAL_STORAGE
    extra-data:
      com.canonical.candy.obb:
        target: /data/app/com.canonical.candy-1/lib
    watchdog:
      disabled: false
      allowed-packages:
      - com.android.settings
    services:
    - port: 5559
      protocols:
      - tcp
      expose: false
      name: adb
resources:
  memory: 4GB
  disk-size: 8GB

Each version gets a monotonically increasing number assigned (here we have version 0 and version 1).
In addition each version has a status which indicates the status of the bootstrap process AMS is
performing for it. Once an application version is marked as active it is ready to be used.

The most important part of an application version is the published field. If a version is marked as published it is accessible to users of Anbox Cloud. Generally when launching containers by using the AMS REST API and no specific application version is given the last published version of an application is used to create the container.

Marking an application version as published can be achieved with the following command

$ amc application publish bcmap7u5nof07arqa2ag 1

Next to publishing an application version its already possible to revoke it

$ amc application revoke bcmap7u5nof07arqa2ag 1

As consequence if an application only has a single published version and that version is revoked the application can’t be used by any users anymore. AMS will still list the application but will mark it as not published as it has no published versions.

Each version takes space on the LXD nodes. To free up space and remove old and unneeded version they can be individually removed with the only requirement that an application needs to have at least a single version at all time. Removing a specific application version is possible with the following command:

$ amc application delete --version=1 bcmap7u5nof07arqa2ag

The amc command will ask for your approval before the version is removed as it may affect your users. If you want to bypass the check you can add the --yes flag to the command.

Change Image an Application is based on

The image an application is based on can be easily changed with the following command:

$ amc application set com.canonical.candy image <image name or id>

Changing the image will cause AMS to generate a new version for the application. Previous versions will continue using the image the application used before.

Inhibit application auto updates

Once an image or one of addons that an application depends on get updated, AMS will update the application automatically in the background to respect the change of its dependency. If you want to inhibit auto updates for an application by AMS, you could do:

$ amc application set <application id or name > inhibit-auto-updates true

This will inhibit AMS to update the application automatically if one of the application’s dependencies gets updated.

Delete Applications

When an application is no longer needed it can be fully removed from Anbox Cloud. Removing an application will cause all of its versions to be removed next to all currently active containers. Please be extra careful as this might affect your users if any are still using containers of the application you want to remove.

Once you’re sure you want to remove the application you can do so with the following command:

$ amc application delete bcmap7u5nof07arqa2ag

The amc tool will ask for your approval before the application is removed. If you want to bypass the check you can add the --yes flag to the command.

Filter Applications

By default, amc application ls shows all applications. If you want to search for specific types of applications, e.g. only show a group of applications with a particular tag, you can use the --filter flag to filter and group applications.

The filter flag accepts a key-value pair as input for the filter. The following attributes are valid keys.

Name Value
instance-type Supported instance type. See chapter Available Instance Types for a list of available instance types
addons Comma separated list of addons
tag Application tag name (deprecated, use tags instead)
tags Comma separated list of tags
publishd “true” or “false” which indicates if the application is published
immutable “true” or “false” which indicates if the application is immutable
status Application status, possible values: “error”, “unknown”, “initializing”, “ready”, “deleted”

To list all applications with a tag called “game”:

$ amc application ls --filter tag=game

If you need to apply multiple filters, you could pass multiple flags:

$ amc application ls --filter published=true --filter tag=game

This will query all published applications that have the tag “game”

Next Steps