Anbox 容器管理服務(wù)

Anbox 安裝過程分析

Anbox 是在像 Ubuntu 這樣的普通 GNU/Linux 系統(tǒng)上座咆,基于容器啟動(dòng)完整 Android 系統(tǒng)的方案。

當(dāng)前安裝過程由多個(gè)步驟組成黎比,這些步驟將向主機(jī)系統(tǒng)中添加額外的組件,這些組件包括:

  • 由于沒有發(fā)行版內(nèi)核同時(shí)啟用 binder 和 ashmem,因此需要它們的源碼樹之外的內(nèi)核模塊
  • /dev/binder/dev/ashmem 設(shè)置正確權(quán)限的 udev 規(guī)則
  • upstart 或 systemd 任務(wù),用于作為用戶會(huì)話的一部分啟動(dòng) Anbox 會(huì)話管理器磺芭。

為了使 Anbox 的安裝過程盡可能簡(jiǎn)單,Anbox 官方已經(jīng)在一個(gè) snap (參考 https://snapcraft.io) 中打包了必須的步驟醉箕,稱為 "anbox-installer"钾腺。這個(gè)安裝器將執(zhí)行所有必須的步驟〖タ悖可以通過運(yùn)行如下命令放棒,在系統(tǒng)上安裝 Anbox 提供對(duì) snaps 的支持:

$ snap install --classic anbox-installer

另外,還可以通過如下命令獲得安裝器腳本:

$ wget https://raw.githubusercontent.com/anbox/anbox-installer/master/installer.sh -O anbox-installer

要通過 Anbox 的安裝器腳本安裝 Anbox 的話己英,簡(jiǎn)單地調(diào)用即可:

$ anbox-installer

這將指導(dǎo)我們完成安裝過程间螟。

anbox-installer 安裝器腳本的實(shí)現(xiàn)是這樣的:

#!/bin/bash

echo "Anbox (Android in a Box) - Installer"
echo
echo
echo "IMPORTANT: THIS IS ALPHA LEVEL SOFTWARE. EXPECT INSTABILITY AND"
echo "           BUGS !!!!!"
echo
echo "IMPORTANT: ALSO PLEASE BE AWARE THAT WE DON'T PROVIDE FULL"
echo "           CONFINEMENT FOR THE SNAP YET !!!!"
echo
echo
echo "PLEASE NOTE: This script will require root access on your system"
echo "to install all necessary things. It will prompt you to enter your"
echo "password when required."
echo
echo

if [ "$(id -u)" -eq 0 ] ; then
    echo "ERROR: Don't run the anbox-installer as root or via sudo. Simply"
    echo "       invoke it with your regular user. The script will use sudo"
    echo "       on its own when needed."
    exit 1
fi

if ! uname -a | grep -q x86_64 ; then
    echo "ERROR: We only have support for x86 64 bit devices today. As"
    echo "       your system has a different architecture we can't"
    echo "       support it yet."
    exit 1
fi

SUPPORTED_DISTROS=("Ubuntu" "LinuxMint" "neon" "elementary" "Zorin")
DISTRIB_ID="$(lsb_release -i -s)"

function contains() {
    local n=$#
    local value=${!n}
    for ((i=1;i < $#;i++)) {
        if [ "${!i}" == "${value}" ]; then
            echo "y"
            return 0
        fi
    }
    return 1
}

if [ "$(contains "${SUPPORTED_DISTROS[@]}" "$DISTRIB_ID")" != "y" ]; then
    echo "ERROR: You are running the installer on an unsupported distribution."
    echo "       At the moment we only support the following distributions:" 
    echo
    printf "%s, " "${SUPPORTED_DISTROS[@]}" | cut -d "," -f 1-${#SUPPORTED_DISTROS[@]}
    echo
    echo "If your distribution is in the list but you still see this message, open"
    echo "an issue here: https://github.com/anbox/anbox-installer"
    exit 1
fi

echo
echo "What do you want to do?"
echo
echo " 1. Install Anbox"
echo " 2. Uninstall Anbox"
echo
echo "Please enter your choice [1-2]: "
read -r action
echo
echo

[[ -n "$(which snap)" ]] || {
    echo "ERROR: Your system does not support snaps. Please have a look"
    echo "       at https://snapcraft.io/ to find out how you can add"
    echo "       support for snaps on your system."
    exit 1
}

uninstall() {
    set -x
    sudo snap remove anbox
    if [ -e /etc/apt/sources.list.d/morphis-ubuntu-anbox-support-xenial.list ]; then
        ppa_purged_installed=0
        if ! dpkg --get-selections | grep -q ppa-purge ; then
            sudo apt install -y ppa-purge
            ppa_purged_installed=1
        fi
        sudo apt install -y ppa-purge
        sudo ppa-purge -y ppa:morphis/anbox-support
        if [ "$ppa_purged_installed" -eq 1 ]; then
            sudo apt purge ppa-purge
        fi
    fi
    set +x
}

if [ "$action" == "2" ]; then
    echo "This will now remove the Android in a Box runtime environment"
    echo "from your device. Do you really want this?"
    echo
    echo "Please be aware that this will also remove any user data"
    echo "stored inside the runtime environment."
    echo
    echo "Please type 'I AGREE' followed by pressing ENTER to continue"
    echo "or type anything else to abort:"
    read -r input
    if [ "$input" != "I AGREE" ]; then
        exit 1
    fi
    echo
    uninstall
    echo
    echo "Successfully removed anbox!"
    echo
    exit 0
fi

if [ "$action" != "1" ]; then
    echo "ERROR: Invalid option selected!"
    exit 1
fi

echo "This is the installer for the anbox runtime environment. It will"
echo "install certain things on your system to ensure all requirements"
echo "are available for anbox to work correctly."
echo
echo "In summary we will install the following things:"
echo
echo " * Add the anbox-support ppa ppa:morphis/anbox-support to the"
echo "   host system"
echo " * Install the anbox-modules-dkms deb package from the ppa"
echo "   which will add kernel modules for ashmem and binder which are"
echo "   required for the Android container to work."
echo " * Configure binder and ashmem kernel modules to be loaded"
echo "   automatically on boot."
echo " * Install the anbox-common package from the ppa which will"
echo "   - Add an upstart job for the current user $USER which will"
echo "     start the anbox runtime on login."
echo "   - Add a X11 session configuration file to allow the system"
echo "     application launcher (Unity7, Gnome Shell, ..) to find"
echo "     available Android applications."
echo
echo "Please type 'I AGREE' followed by pressing ENTER to continue"
echo "or type anything else to abort:"
read -r input
if [ "$input" != "I AGREE" ]; then
    exit 1
fi
echo
echo

echo "Starting installation process ..."
echo

cleanup() {
    local err=$?
    trap - EXIT

    echo "ERROR: Installation failed. Removing all parts of Anbox again."
    uninstall

    exit $err
}

trap cleanup HUP PIPE INT QUIT TERM EXIT

set -ex

sudo add-apt-repository -y 'ppa:morphis/anbox-support'
# Users tend to have APT repositories installed which are not properly
# authenticated and because of that `apt update` will fail. We ignore
# this and proceed with the package installation. If the installation
# of a specific package fails this will indicate our point of abort.
sudo apt update || true
sudo apt install -y anbox-common

# Install kernel drivers only if necessary and let the user use the
# ones build into his kernel otherwise.
if [ -c /dev/binder ] && [ -c /dev/ashmem ]; then
    echo "Android binder and ashmem seems to be already enabled in kernel.";
else
    sudo apt install -y linux-headers-generic anbox-modules-dkms
    sudo modprobe binder_linux
    sudo modprobe ashmem_linux
fi

if snap info anbox | grep -q "installed:" ; then
     sudo snap refresh --edge anbox || true
else
     sudo snap install --edge --devmode anbox
fi

set +x

echo
echo "Done!"
echo
echo "To ensure all changes made to your system you should now reboot"
echo "your system. If you don't do this no Android applications will"
echo "show up in the system application launcher."
trap - EXIT

anbox-installer 安裝器腳本中的 echo 打印輸出有點(diǎn)多,同時(shí)這個(gè)腳本還提供了移除 anbox 的功能损肛。安裝 Anbox 的工作主要由如下這幾行代碼完成:

sudo add-apt-repository -y 'ppa:morphis/anbox-support'
. . . . . .
sudo apt update || true
sudo apt install -y anbox-common

# Install kernel drivers only if necessary and let the user use the
# ones build into his kernel otherwise.
if [ -c /dev/binder ] && [ -c /dev/ashmem ]; then
    echo "Android binder and ashmem seems to be already enabled in kernel.";
else
    sudo apt install -y linux-headers-generic anbox-modules-dkms
    sudo modprobe binder_linux
    sudo modprobe ashmem_linux
fi

if snap info anbox | grep -q "installed:" ; then
     sudo snap refresh --edge anbox || true
else
     sudo snap install --edge --devmode anbox
fi

set +x
. . . . . .
trap - EXIT

這段代碼厢破,通過三個(gè)步驟完成 Anbox 的安裝。

第一步治拿,安裝 anbox-common

sudo add-apt-repository -y 'ppa:morphis/anbox-support'
. . . . . .
sudo apt update || true
sudo apt install -y anbox-common

anbox-common 包的安裝的文件如下:

$ dpkg -L anbox-common
/.
/etc
/etc/X11
/etc/X11/Xsession.d
/etc/X11/Xsession.d/68anbox
/usr
/usr/share
/usr/share/doc
/usr/share/doc/anbox-common
/usr/share/doc/anbox-common/README.Debian
/usr/share/doc/anbox-common/changelog.gz
/usr/share/doc/anbox-common/copyright
/usr/src

第二步摩泪,安裝 binder 和 ashmem 驅(qū)動(dòng)

    sudo apt install -y linux-headers-generic anbox-modules-dkms
    sudo modprobe binder_linux
    sudo modprobe ashmem_linux

第三步,通過 snap 的方式安裝 anbox 包

     sudo snap install --edge --devmode anbox

anbox 包通過 snap 的方式進(jìn)行安裝劫谅。

Anbox 容器管理服務(wù)

整體看來见坑,Anbox 的安裝過程安裝了兩個(gè)組件,一是 binder 和 ashmem 內(nèi)核驅(qū)動(dòng)捏检;二是 Anbox荞驴,Anbox 又由 anbox-common 和 anbox snap 組成。

通過如下命令可以看到 anbox snap 的信息:

$ snap info anbox
name:      anbox
summary:   Android in a Box
publisher: morphis
description: |
  Runtime for Android applications which runs a full Android system
  in a container using Linux namespaces (user, ipc, net, mount) to
  separate the Android system fully from the host.
snap-id: Nr9K6UJaIOD8wHpDEQl16nabFFt9LLEQ
commands:
  - anbox
  - anbox.collect-bug-info
services:
  anbox.container-manager: simple, enabled, inactive
tracking:                  edge
installed:                 3-7266fe2 (65) 361MB devmode
refreshed:                 2017-11-17 21:37:23 +0800 CST
channels:                                 
  stable:                  –                    
  candidate:               –                    
  beta:                    1-dev     (15) 357MB devmode
  edge:                    3-7266fe2 (65) 361MB devmode

anbox 向主機(jī)系統(tǒng)中安裝了 2 個(gè)命令贯城,anboxanbox.collect-bug-info戴尸,以及一個(gè) service,anbox.container-manager冤狡,即 Anbox 的容器管理器服務(wù)孙蒙。

通過 Anbox 安裝器安裝 Anbox 之后,service 會(huì)自動(dòng)啟動(dòng)悲雳。通過如下命令可以查看這個(gè)服務(wù)的當(dāng)前狀態(tài):

$ sudo systemctl status snap.anbox.container-manager
● snap.anbox.container-manager.service - Service for snap application anbox.container-manager
   Loaded: loaded (/etc/systemd/system/snap.anbox.container-manager.service; enabled; vendor preset: enabled)
   Active: active (running) since 五 2017-12-01 09:55:46 CST; 3min 54s ago
  Process: 25619 ExecStop=/usr/bin/snap run --command=stop anbox.container-manager (code=exited, status=0/SUCCESS)
 Main PID: 30438 (anbox)
    Tasks: 10
   Memory: 1.8M
      CPU: 74ms
   CGroup: /system.slice/snap.anbox.container-manager.service
           ├─30438 /snap/anbox/65/usr/bin/anbox container-manager --data-path=/var/snap/anbox/common/ --android-image=/snap/anbox/
           └─30644 [lxc monitor] /var/snap/anbox/common/containers default

12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + [ ! -e /snap/anbox/65/android.img ]
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + start
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + mkdir -p /var/snap/anbox/common/lxc
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + /snap/anbox/65/bin/anbox-bridge.sh start
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + echo Y
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + tee /sys/module/fuse/parameters/userns_mounts
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: Y
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + AA_EXEC=/snap/anbox/65/usr/sbin/aa-exec -p unconfined --
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + [ ! -d /sys/kernel/security/apparmor ]
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + exec /snap/anbox/65/usr/sbin/aa-exec -p unconfined -- /snap/anbox/65

當(dāng) Anbox 的容器管理服務(wù)正常運(yùn)行時(shí)挎峦,通過在應(yīng)用列表中,點(diǎn)擊 Anbox 應(yīng)用合瓢,如下圖這樣:


Anbox Application

可以啟動(dòng) Anbox 會(huì)話坦胶。

當(dāng) Anbox 的容器管理服務(wù)起動(dòng)時(shí),它會(huì)監(jiān)聽一個(gè) Unix 域 Socket,/run/anbox-container.socket顿苇。(這個(gè)地址在 anbox/src/anbox/container/service.cpp 文件的 Service::create() 函數(shù)中峭咒,從 anbox::SystemConfiguration::container_socket_path() 獲得)。

當(dāng)啟動(dòng) Anbox 應(yīng)用纪岁,即會(huì)話管理器時(shí)凑队,它會(huì)通過 Unix 域 Socket 與容器管理服務(wù)建立連接。容器管理服務(wù)接收到連接幔翰,且容器還沒有啟動(dòng)時(shí)漩氨,它會(huì)掛載 Android 系統(tǒng)鏡像,起動(dòng) LXC 容器遗增,并在容器內(nèi)起動(dòng) Android 系統(tǒng)叫惊。

同時(shí)會(huì)話管理器與主機(jī)系統(tǒng)上的 ADB 服務(wù)建立連接。如:

$ ps -aux | grep anbox
hanpfei+ 15883  3.3  1.0 3024640 175500 ?      Sl   19:01   0:34 /usr/bin/python3 /usr/bin/remarkable /home/hanpfei0306/data/MyProjects/hanpfei-documents/source/_posts/anbox_container_manager_service.md
root     16732  0.1  0.0 569980 12288 ?        Ssl  19:17   0:00 /snap/anbox/x1/usr/bin/anbox container-manager --data-path=/var/snap/anbox/common/ --android-image=/snap/anbox/x1/android.img --daemon
hanpfei+ 16765  4.5  0.2 335372 44676 ?        Sl   19:17   0:00 /snap/anbox/x1/usr/bin/anbox launch --package=org.anbox.appmgr --component=org.anbox.appmgr.AppViewActivity
root     16794  0.0  0.0  36776  3692 ?        Ss   19:17   0:00 /snap/anbox/current/libexec/lxc/lxc-monitord /var/snap/anbox/common/containers 14
hanpfei+ 16917  0.0  0.2 1281208 42556 ?       Sl   19:18   0:00 /snap/anbox/x1/usr/bin/anbox session-manager
root     16931  0.0  0.0 576280  8216 ?        Ss   19:18   0:00 [lxc monitor] /var/snap/anbox/common/containers default
100000   16940  0.0  0.0   7920  2540 ?        Ss   19:18   0:00 /system/bin/sh /anbox-init.sh
100000   16999  0.0  0.0  16472  4068 ?        Sl   19:18   0:00 /system/bin/anboxd
hanpfei+ 17087  0.0  0.0  19300   936 pts/2    R+   19:18   0:00 grep --color=auto anbox
$ adb devices
List of devices attached
emulator-5558   device

$ lsof -i | grep adb
adb       30288 hanpfei0306    6u  IPv4 23788668      0t0  TCP localhost:5037 (LISTEN)
adb       30288 hanpfei0306    7u  IPv4 27391368      0t0  TCP localhost:42048->localhost:5559 (ESTABLISHED)
$ lsof -i | grep 42048
anbox     16917 hanpfei0306   29u  IPv4 27385836      0t0  TCP localhost:5559->localhost:42048 (ESTABLISHED)
adb       30288 hanpfei0306    7u  IPv4 27391368      0t0  TCP localhost:42048->localhost:5559 (ESTABLISHED)

此時(shí)可以通過 adb 命令查看 Anbox 起動(dòng)的 Android 系統(tǒng)的狀況做修,如下面這樣:

$ adb devices
List of devices attached
emulator-5558   device

$ adb logcat
--------- beginning of system
12-01 01:57:25.245    16    16 I vold    : Vold 3.0 (the awakening) firing up
12-01 01:57:25.245    16    16 V vold    : Detected support for: ext4 vfat
12-01 01:57:25.260    16    16 E vold    : Failed to open default fstab /fstab.goldfish: Operation not permitted
12-01 01:57:25.260    16    16 E vold    : Error reading configuration... continuing anyways: Operation not permitted
12-01 01:57:25.264    16    25 D vold    : e4crypt_init_user0
12-01 01:57:25.264    16    25 D vold    : e4crypt_prepare_user_storage for volume null, user 0, serial 0, flags 1
12-01 01:57:25.264    16    25 D vold    : Preparing: /data/system/users/0
12-01 01:57:25.264    16    25 D vold    : Preparing: /data/misc/profiles/cur/0
12-01 01:57:25.264    16    25 D vold    : Preparing: /data/misc/profiles/cur/0/foreign-dex
12-01 01:57:25.264    16    25 D vold    : Preparing: /data/system_de/0
12-01 01:57:25.264    16    25 D vold    : Preparing: /data/misc_de/0
12-01 01:57:25.264    16    25 D vold    : Preparing: /data/user_de/0

當(dāng) Anbox 起動(dòng)的 Android 系統(tǒng)內(nèi)所需的應(yīng)用程序都啟動(dòng)完畢時(shí)霍狰,通過 Anbox 應(yīng)用將可以看到 Android 系統(tǒng)的桌面,可以看到 Android 系統(tǒng)中的應(yīng)用饰及,如下圖:


image

Anbox 項(xiàng)目寫了一個(gè)名為 org.anbox.appmgr 的 Java 應(yīng)用程序蔗坯,用以替代原始 Android 系統(tǒng)中的 Launcher,以展示已安裝應(yīng)用列表旋炒。隨后就可以像操作普通的桌面 Linux 系統(tǒng)中的應(yīng)用那樣操作 Android 內(nèi)的應(yīng)用了步悠。

此時(shí),查看主機(jī) Linux 系統(tǒng)中與 Anbox 有關(guān)的進(jìn)程瘫镇,可以看到如下這些:

$ ps -aux | grep anbox
root     30438  0.0  0.0 373372 12144 ?        Ssl  09:55   0:00 /snap/anbox/65/usr/bin/anbox container-manager --data-path=/var/snap/anbox/common/ --android-image=/snap/anbox/65/android.img --daemon
hanpfei+ 30630  0.6  1.7 2770120 280580 ?      Sl   09:57   0:07 /snap/anbox/65/usr/bin/anbox session-manager
root     30644  0.0  0.0 379672  8016 ?        Ss   09:57   0:00 [lxc monitor] /var/snap/anbox/common/containers default
100000   30652  0.0  0.0   7920  6516 ?        Ss   09:57   0:00 /system/bin/sh /anbox-init.sh
100000   30711  0.0  0.0  16728  9240 ?        Sl   09:57   0:00 /system/bin/anboxd
110000   31209  0.0  0.7 1074676 116412 ?      Sl   09:57   0:00 org.anbox.appmgr

進(jìn)程號(hào)為 30438 和 30644 的兩個(gè)進(jìn)程組成了容器管理器服務(wù)鼎兽。進(jìn)程號(hào)為 30630 的進(jìn)程為我們啟動(dòng)的 Anbox 應(yīng)用。進(jìn)程號(hào)為 30652铣除,30711谚咬,和 31209 的幾個(gè)進(jìn)程,實(shí)際為 Anbox 啟動(dòng)的容器中運(yùn)行的 Android 系統(tǒng)的進(jìn)程尚粘。Anbox 的整體設(shè)計(jì)可以參考 Anbox 一文择卦。

Anbox snap

Anbox 應(yīng)用通過 snap 方式打包,下載 anbox 的源碼郎嫁,并在源碼目錄下執(zhí)行 snapcraft秉继,可以生成 anbox 的 .snap 文件:

$ mkdir android-images
$ cp /path/to/android.img android-images/android.img
$ snapcraft

生成的 .snap 文件還可以通過如下命令進(jìn)行安裝:

$ snap install --dangerous --devmode anbox_3-7266fe2_amd64.snap

通過 Anbox 的 snapcraft.yaml 文件,可以對(duì) Anbox 運(yùn)行時(shí)泽铛、命令和服務(wù)有更深入的了解尚辑。Anbox 的 snapcraft.yaml 文件長(zhǎng)這樣:

name: anbox
version: 3
version-script: |
  if [ "$SNAPCRAFT_GRADE" = "stable" ]; then
    echo $SNAPCRAFT_PROJECT_VERSION
  else
    echo $SNAPCRAFT_PROJECT_VERSION-$(git rev-parse --short HEAD)
  fi
summary: Android in a Box
description: |
  Runtime for Android applications which runs a full Android system
  in a container using Linux namespaces (user, ipc, net, mount) to
  separate the Android system fully from the host.
confinement: devmode
grade: devel

slots:
  # Depending on in which environment we're running we either need
  # to use the system or session DBus so we also need to have one
  # slot for each.
  dbus-session:
    interface: dbus
    bus: system
    name: org.anbox
  dbus-system:
    interface: dbus
    bus: system
    name: org.anbox

apps:
  anbox:
    command: bin/anbox-wrapper.sh
  container-manager:
    command: bin/container-manager.sh start
    stop-command: bin/container-manager.sh stop
    daemon: simple
  collect-bug-info:
    command: bin/collect-bug-info.sh

parts:
  android-images:
    plugin: dump
    # This needs to be any directory but not the root one as if we use
    # it we get superious permissions errors with the copied .git tree
    source: data
    build-packages:
      - wget
    install: |
      LOCAL_IMAGE=$SNAPCRAFT_PART_INSTALL/../../../android-images/android.img

      if [ -f $LOCAL_IMAGE ]; then

        echo "Using local image $LOCAL_IMAGE"
        cp $LOCAL_IMAGE $SNAPCRAFT_PART_INSTALL/android.img

      else

        IMAGE_PATH=
        IMAGE_NAME=
        ARCH=$(uname -m)

        case "$ARCH" in
          x86_64)
            IMAGE_PATH="2017/07/13"
            IMAGE_NAME="android_3_amd64.img"
            ;;
          arm*)
            IMAGE_PATH="2017/06/12"
            IMAGE_NAME="android_1_armhf.img"
            ;;
          *)
            echo "ERROR: Unknown architecture $ARCH"
            exit 1
            ;;
        esac

        # FIXME: downloading with a source: field doesn't work as snapcraft
        # expects the downloaded file to be an archive it can extract.
        echo "Downloading image..."
        wget http://build.anbox.io/android-images/$IMAGE_PATH/$IMAGE_NAME
        mv $IMAGE_NAME $SNAPCRAFT_PART_INSTALL/android.img

      fi
    prime:
      - android.img
  anbox-common:
    plugin: dump
    source: scripts
    organize:
      snap-wrapper.sh: bin/anbox-wrapper.sh
      container-manager.sh: bin/container-manager.sh
      anbox-bridge.sh: bin/anbox-bridge.sh
      collect-bug-info.sh: bin/collect-bug-info.sh
    prime:
      - bin/anbox-bridge.sh
      - bin/anbox-wrapper.sh
      - bin/container-manager.sh
      - bin/collect-bug-info.sh
  apparmor:
    plugin: nil
    stage-packages:
      - apparmor
  lxc:
    source: https://github.com/lxc/lxc
    source-type: git
    source-tag: lxc-2.0.7
    build-packages:
      - libapparmor-dev
      - libcap-dev
      - libgnutls28-dev
      - libseccomp-dev
      - pkg-config
    plugin: autotools
    configflags:
      - --disable-selinux
      - --disable-python
      - --disable-lua
      - --disable-tests
      - --disable-examples
      - --disable-doc
      - --disable-api-docs
      - --disable-bash
      - --disable-cgmanager
      - --disable-apparmor
      - --disable-seccomp
      - --enable-capabilities
      - --with-rootfs-path=/var/snap/anbox/common/lxc/
      - --libexecdir=/snap/anbox/current/libexec/
    organize:
      snap/anbox/current/libexec: libexec
    prime:
      - lib/liblxc.so.1
      - lib/liblxc.so.1.2.0
      - libexec/lxc/lxc-monitord
      - bin/lxc-start
      - bin/lxc-stop
      - bin/lxc-info
      - bin/lxc-attach
      - bin/lxc-ls
      - bin/lxc-top
  anbox:
    plugin: cmake
    after:
      - lxc
    source: .
    configflags:
      # FIXME: Anbox currently has some paths with hard coded prefixes. Once
      # that is fixed we can avoid using a prefix here.
      - -DCMAKE_INSTALL_PREFIX:PATH=/usr
      - -DANBOX_VERSION=$SNAPCRAFT_PROJECT_VERSION
    build-packages:
      - build-essential
      - cmake
      - cmake-data
      - cmake-extras
      - debhelper
      - dbus
      - google-mock
      - libboost-dev
      - libboost-filesystem-dev
      - libboost-log-dev
      - libboost-iostreams-dev
      - libboost-program-options-dev
      - libboost-system-dev
      - libboost-test-dev
      - libboost-thread-dev
      - libcap-dev
      - libdbus-1-dev
      - libdbus-cpp-dev
      - libegl1-mesa-dev
      - libgles2-mesa-dev
      - libglib2.0-dev
      - libglm-dev
      - libgtest-dev
      - libprotobuf-dev
      - libproperties-cpp-dev
      - libsdl2-dev
      - libsdl2-image-dev
      - pkg-config
      - protobuf-compiler
    stage-packages:
      - libegl1-mesa
      - libgles2-mesa
      - libgl1-mesa-glx
      - libsdl2-2.0-0
      - libsdl2-gfx-1.0-0
    install: |
      make test
    prime:
      - usr/bin/anbox
      - usr/share/anbox
      - usr/lib/*-linux-*/

從 Anbox 的 snapcraft.yaml 文件中可以看到,Anbox snap 安裝的幾個(gè)命令和服務(wù)盔腔,是一些腳本:

apps:
  anbox:
    command: bin/anbox-wrapper.sh
  container-manager:
    command: bin/container-manager.sh start
    stop-command: bin/container-manager.sh stop
    daemon: simple
  collect-bug-info:
    command: bin/collect-bug-info.sh

Anbox snap 主要由這幾部分組成:

  • Android 系統(tǒng)鏡像杠茬,先找本地的 android-images/android.img月褥,如果找不到,就根據(jù)主機(jī)系統(tǒng)的 CPU 架構(gòu)瓢喉,從遠(yuǎn)端下載
  • anbox-common宁赤,主要是一些腳本,提供 Anbox snap 的命令和服務(wù)栓票,由 source: 行可以看到這些腳本都位于源碼目錄的 scripts 子目錄下
  • apparmor决左,從 Ubuntu 的 APT 源獲得
  • lxc,用于做容器管理逗载,從 GitHub 獲得源碼哆窿,并由 tag 為 lxc-2.0.7 的版本編譯生成
  • anbox 二進(jìn)制可執(zhí)行程序链烈,通過 cmake 編譯生成厉斟,如:
$ git clone https://github.com/anbox/anbox.git
$ cd anbox
$ mkdir build
$ cd build
$ cmake ..
$ make

還可以通過如下命令編譯帶符號(hào)的 Debug 版 anbox 二進(jìn)制可執(zhí)行程序:

$ mkdir Debug
$ cd Debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ..
$ make

或 Release 版:

$ mkdir Release
$ cd Release
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ make

這里來看一下 Anbox snap 的主要命令和服務(wù),也就是幾個(gè)腳本的實(shí)現(xiàn)强衡。container-manager.sh 腳本擦秽,用于起動(dòng)容器管理服務(wù),其內(nèi)容如下:

#!/bin/sh
set -x

# We need to put the rootfs somewhere where we can modify some
# parts of the content on first boot (namely file permissions).
# Other than that nothing should ever modify the content of the
# rootfs.

DATA_PATH=$SNAP_COMMON/
ROOTFS_PATH=$DATA_PATH/rootfs
ANDROID_IMG=$SNAP/android.img

if [ ! -e $ANDROID_IMG ]; then
    echo "ERROR: android image does not exist"
    exit 1
fi

start() {
    # Make sure our setup path for the container rootfs
    # is present as lxc is statically configured for
    # this path.
    mkdir -p $SNAP_COMMON/lxc

    # We start the bridge here as long as a oneshot service unit is not
    # possible. See snapcraft.yaml for further details.
    $SNAP/bin/anbox-bridge.sh start

    # Ensure FUSE support for user namespaces is enabled
    echo Y | tee /sys/module/fuse/parameters/userns_mounts || echo "WARNING: kernel doesn't support fuse in user namespaces"

    # Only try to use AppArmor when the kernel has support for it
    AA_EXEC="$SNAP/usr/sbin/aa-exec -p unconfined --"
    if [ ! -d /sys/kernel/security/apparmor ]; then
        echo "WARNING: AppArmor support is not available!"
        AA_EXEC=""
    fi

    exec $AA_EXEC $SNAP/bin/anbox-wrapper.sh container-manager \
        --data-path=$DATA_PATH \
        --android-image=$ANDROID_IMG \
        --daemon
}

stop() {
    $SNAP/bin/anbox-bridge.sh stop
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    *)
        echo "ERROR: Unknown command '$1'"
        exit 1
        ;;
esac

在這個(gè)腳本中漩勤,啟動(dòng)容器管理服務(wù)時(shí)感挥,調(diào)用 anbox-bridge.sh start 腳本為 Anbox 創(chuàng)建虛擬網(wǎng)卡,并調(diào)用 anbox-wrapper.sh 啟動(dòng) anbox 二進(jìn)制可執(zhí)行程序越败。腳本的執(zhí)行依賴幾個(gè)環(huán)境變量的設(shè)置触幼。在腳本執(zhí)行時(shí),環(huán)境變量 SNAP 指向 /snap/anbox/current究飞,環(huán)境變量 SNAP_COMMON 指向 /var/snap/anbox/common置谦。

anbox-wrapper.sh 也就是 anbox 源碼庫(kù)中的 scripts/snap-wrapper.sh,其內(nèi)容如下:

#!/bin/bash

if [ "$SNAP_ARCH" == "amd64" ]; then
    ARCH="x86_64-linux-gnu"
elif [ "$SNAP_ARCH" == "armhf" ]; then
    ARCH="arm-linux-gnueabihf"
else
    ARCH="$SNAP_ARCH-linux-gnu"
fi

export LD_LIBRARY_PATH=$SNAP/usr/lib/$ARCH:$LD_LIBRARY_PATH

# Mesa Libs
export LD_LIBRARY_PATH=$SNAP/usr/lib/$ARCH/mesa:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$SNAP/usr/lib/$ARCH/mesa-egl:$LD_LIBRARY_PATH

# XDG Config
export XDG_CONFIG_DIRS=$SNAP/etc/xdg:$XDG_CONFIG_DIRS
export XDG_CONFIG_DIRS=$SNAP/usr/xdg:$XDG_CONFIG_DIRS

# Note: this doesn't seem to work, QML's LocalStorage either ignores
# or fails to use $SNAP_USER_DATA if defined here
export XDG_DATA_DIRS=$SNAP_USER_DATA:$XDG_DATA_DIRS
export XDG_DATA_DIRS=$SNAP/usr/share:$XDG_DATA_DIRS

# Tell libGL where to find the drivers
export LIBGL_DRIVERS_PATH=$SNAP/usr/lib/$ARCH/dri

# ensure the snappy gl libs win
export LD_LIBRARY_PATH="$SNAP_LIBRARY_PATH:$LD_LIBRARY_PATH"

# Workaround in snapd for proprietary nVidia drivers mounts the drivers in
# /var/lib/snapd/lib/gl that needs to be in LD_LIBRARY_PATH
# Without that OpenGL using apps do not work with the nVidia drivers.
# Ref.: https://bugs.launchpad.net/snappy/+bug/1588192
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/var/lib/snapd/lib/gl

# We set XDG_DATA_HOME to SNAP_USER_COMMON here as this will be the location we will
# create all our application launchers in. The system application launcher will
# be configured by our installer to look into this directory for available
# launchers.
export XDG_DATA_HOME="$SNAP_USER_COMMON/app-data"

exec $SNAP/usr/bin/anbox $@

在這個(gè)腳本中亿傅,主要導(dǎo)出了一些環(huán)境變量媒峡,LD_LIBRARY_PATHXDG_CONFIG_DIRS葵擎,XDG_DATA_DIRS谅阿,LIBGL_DRIVERS_PATHXDG_DATA_HOME,以使 anbox 二進(jìn)制可執(zhí)行程序在啟動(dòng)之后酬滤,可以找到所需的動(dòng)態(tài)鏈接庫(kù)等签餐。

打賞

參考文檔:
Upstart
淺析 Linux 初始化 init 系統(tǒng),Systemd
Debug vs Release in CMAKE

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盯串,一起剝皮案震驚了整個(gè)濱河市氯檐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嘴脾,老刑警劉巖男摧,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔬墩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡耗拓,警方通過查閱死者的電腦和手機(jī)拇颅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乔询,“玉大人樟插,你說我怎么就攤上這事「偷螅” “怎么了黄锤?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)食拜。 經(jīng)常有香客問我鸵熟,道長(zhǎng),這世上最難降的妖魔是什么负甸? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任流强,我火速辦了婚禮,結(jié)果婚禮上呻待,老公的妹妹穿的比我還像新娘打月。我一直安慰自己,他們只是感情好蚕捉,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布奏篙。 她就那樣靜靜地躺著,像睡著了一般迫淹。 火紅的嫁衣襯著肌膚如雪秘通。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天千绪,我揣著相機(jī)與錄音充易,去河邊找鬼。 笑死荸型,一個(gè)胖子當(dāng)著我的面吹牛盹靴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瑞妇,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼稿静,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了辕狰?” 一聲冷哼從身側(cè)響起改备,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蔓倍,沒想到半個(gè)月后悬钳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盐捷,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年默勾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碉渡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡母剥,死狀恐怖滞诺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情环疼,我是刑警寧澤习霹,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站炫隶,受9級(jí)特大地震影響淋叶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜等限,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一爸吮、第九天 我趴在偏房一處隱蔽的房頂上張望芬膝。 院中可真熱鬧望门,春花似錦、人聲如沸锰霜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽癣缅。三九已至厨剪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間友存,已是汗流浹背祷膳。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屡立,地道東北人直晨。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像膨俐,于是被迫代替她去往敵國(guó)和親勇皇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理焚刺,服務(wù)發(fā)現(xiàn)敛摘,斷路器,智...
    卡卡羅2017閱讀 134,638評(píng)論 18 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,867評(píng)論 25 707
  • 1:InputChannel提供函數(shù)創(chuàng)建底層的Pipe對(duì)象 2: 1)客戶端需要新建窗口 2)new ViewRo...
    自由人是工程師閱讀 5,284評(píng)論 0 18
  • Ubuntu的發(fā)音 Ubuntu捕虽,源于非洲祖魯人和科薩人的語言氓润,發(fā)作 oo-boon-too 的音。了解發(fā)音是有意...
    螢火蟲de夢(mèng)閱讀 99,217評(píng)論 9 467
  • 今天弄了一個(gè)好習(xí)慣計(jì)劃表薯鳍,感覺蠻好的咖气,可以督促自己在2017年更上一層樓,雖然都是小事挖滤,可小事如果堅(jiān)持下來崩溪,細(xì)水長(zhǎng)...
    大胡子呢閱讀 169評(píng)論 0 0