blob: 3748e17efeead497f679d921468695540f89bc37 [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ARC_SETUP_ARC_SETUP_H_
#define ARC_SETUP_ARC_SETUP_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <base/macros.h>
#include "arc/setup/android_sdk_version.h"
#include "arc/setup/arc_setup_metrics.h"
#include "arc/setup/arc_setup_util.h"
#include "arc/setup/config.h"
namespace base {
class FilePath;
} // namespace base
namespace brillo {
class CrosConfigInterface;
} // namespace brillo
namespace arc {
struct ArcPaths;
class ArcSetupMetrics;
// This MUST be in sync with 'enum BootType' in metrics.mojom.
// Note: This enum has to be in sync with Android's arc-boot-type-detector.
enum class ArcBootType {
UNKNOWN = 0,
// This is for the very first (opt-in) boot.
FIRST_BOOT = 1,
// This is for the first boot after Chrome OS update which also updates the
// ARC++ image.
FIRST_BOOT_AFTER_UPDATE = 2,
// This is for regular boot.
REGULAR_BOOT = 3,
};
// Enum that describes which native bridge mode is used to run arm binaries on
// x86.
enum class ArcBinaryTranslationType {
NONE = 0,
HOUDINI = 1,
NDK_TRANSLATION = 2,
};
// Enum that describes what action ArcSetup will perform.
enum class Mode {
SETUP = 0,
BOOT_CONTINUE,
STOP,
ONETIME_SETUP,
// None of our scripts for production uses ONETIME_STOP. Only our development
// script does to unmount system/vendor images before pushing new ones.
ONETIME_STOP,
PRE_CHROOT,
APPLY_PER_BOARD_CONFIG, // for ARCVM
CREATE_DATA, // for ARCVM
REMOVE_DATA,
REMOVE_STALE_DATA,
MOUNT_SDCARD,
UNMOUNT_SDCARD,
UPDATE_RESTORECON_LAST,
HANDLE_UPGRADE, // for ARC upgrades
UNKNOWN,
};
// A class that does the actual setup (and stop) operations.
class ArcSetup {
public:
ArcSetup(Mode mode, const base::FilePath& config_json);
ArcSetup(const ArcSetup&) = delete;
ArcSetup& operator=(const ArcSetup&) = delete;
~ArcSetup();
// Does the setup or stop operations depending on the environment variable.
// The return value is void because the function aborts when one or more of
// the operations fail.
void Run();
void set_arc_mounter_for_testing(std::unique_ptr<ArcMounter> mounter) {
arc_mounter_ = std::move(mounter);
}
const ArcMounter* arc_mounter_for_testing() const {
return arc_mounter_.get();
}
void MountOnOnetimeSetupForTesting();
void UnmountOnOnetimeStopForTesting();
private:
enum class PlayStoreAutoUpdate { kDefault, kOn, kOff };
// Converts |PlayStoreAutoUpdate| to Android string param.
static std::string GetPlayStoreAutoUpdateParam(
PlayStoreAutoUpdate play_store_auto_update);
// Clears executables /data/app/*/oat and /data/dalvik-cache.
void DeleteExecutableFilesInData(
bool should_delete_data_dalvik_cache_directory,
bool should_delete_data_app_executables);
// Clears unused cache directory that was used in ARC-N.
void DeleteUnusedCacheDirectory();
// Waits for the rt-limits job to start.
void WaitForRtLimitsJob();
// Waits for directories in /run the container depends on to be created.
void WaitForArcDirectories();
// Remounts /vendor.
void RemountVendorDirectory();
// Identifies type of binary translation.
ArcBinaryTranslationType IdentifyBinaryTranslationType();
// Sets up binfmt_misc handler to run arm binaries on x86.
void SetUpBinFmtMisc(ArcBinaryTranslationType bin_type);
// Sets up a dummy android-data directory on tmpfs.
void SetUpDummyAndroidDataOnTmpfs();
// Sets up android-data directory. It bind-mounts
// /home/root/<hash>/android-data to |bind_target|.
void SetUpAndroidData(const base::FilePath& bind_target);
// Sets up shared APK cache directory.
void SetUpSharedApkDirectory();
// Sets up sdcard mount, if required.
void SetUpSdcard();
// Creates files and directories needed by the container.
void CreateContainerFilesAndDirectories();
// Detects and applies per-board hardware configurations.
void ApplyPerBoardConfigurations();
void ApplyPerBoardConfigurationsInternal(
const base::FilePath& oem_mount_directory);
// Sets up shared tmpfs to share mount points for external storage.
void SetUpSharedTmpfsForExternalStorage();
// Sets up /mnt filesystem for arc-obb-mounter.
void SetUpFilesystemForObbMounter();
// Generates boot*.art files on host side and stores them in
// |host_dalvik_cache_directory|. Returns true on success.
bool GenerateHostSideCodeInternal(
const base::FilePath& host_dalvik_cache_directory,
ArcCodeRelocationResult* result);
// Calls GenerateHostSideCodeInternal(). If the internal function returns
// false, deletes all files in |host_dalvik_cache_directory|.
bool GenerateHostSideCode(const base::FilePath& host_dalvik_cache_directory);
// Calls InstallHostSideCodeInternal() for each isa the device supports.
bool InstallLinksToHostSideCode();
// Installs links to *boot*.{art,oat} files to |dest_isa_directory|. Returns
// false when |src_isa_directory| is empty.
bool InstallLinksToHostSideCodeInternal(
const base::FilePath& src_isa_directory,
const base::FilePath& dest_isa_directory,
const std::string& isa);
// Provides some fake kernel command line arguments that are needed.
void CreateAndroidCmdlineFile(bool is_dev_mode,
bool is_inside_vm,
bool is_debuggable,
PlayStoreAutoUpdate play_store_auto_update,
const std::string& dalvik_memory_profile,
bool disable_system_default_app);
// Create fake procfs entries expected by android.
void CreateFakeProcfsFiles();
// Bind-mounts /sys/kernel/debug/tracing to
// |arc_paths.debugfs_directory|/tracing.
void SetUpMountPointForDebugFilesystem(bool is_dev_mode);
// Sets up media mount points such as arc-removable-media and arc-myfiles.
void SetUpMountPointsForMedia();
// Sets up a mount point for arc-adbd.
void SetUpMountPointForAdbd();
// Sets up a mount point for arc-adbd UNIX domain sockets.
void SetUpMountPointForAdbdUnixSocket();
// Cleans up mount points for arc-removable-media if any.
void CleanUpStaleMountPoints();
// Sets up a mount point for passing the user's /data and /cache to the
// container.
void SetUpSharedMountPoints();
// Sets up the correct ownership for <configfs>/sdcardfs, if the directory
// exists.
void SetUpOwnershipForSdcardConfigfs();
// Restores the labels of files and directories. This has to be called before
// MakeMountpointsReadOnly() makes the directories read-only.
void RestoreContext();
// Initializes SELinux contexts of SysFS entries necessary to enumerate
// graphics hardware. Cannot be done using RestoreContext(), because
// symbolic links are involved.
void SetUpGraphicsSysfsContext();
// Initializes SELinux contexts of SysFS entries necessary to enumerate
// power supplies (batteries, line power, etc.) As with graphics symbolic
// links are involved.
// TODO(ejcaruso, b/78300746): remove this when we can use genfs_contexts
void SetUpPowerSysfsContext();
// Notifies networking service that the container is starting.
void StartNetworking();
// Notifies networking service that the container is stopping.
void StopNetworking();
// Makes some mount points read-only.
void MakeMountPointsReadOnly();
// Sets up a subset property file for camera.
void SetUpCameraProperty(const base::FilePath& build_prop);
// Sets up a default apps.
void SetUpDefaultApps();
// Cleans up binfmt_misc handlers that run arm binaries on x86.
void CleanUpBinFmtMiscSetUp();
// Cleanup sdcard mount.
void UnmountSdcard();
// Unmounts files and directories that are not necessary after shutting down
// the container.
void UnmountOnStop();
// Removes the pipe for 'bugreport'.
void RemoveBugreportPipe();
// Removes the FIFO file for emulating /dev/kmsg.
void RemoveAndroidKmsgFifo();
// Fills |out_boot_type| with the boot type.
// If Android's packages.xml exists, fills |out_data_sdk_version| with the SDK
// version for the internal storage found in the XML. If packages.xml doesn't
// exist, fills it with AndroidSdkVersion::UNKNOWN.
void GetBootTypeAndDataSdkVersion(ArcBootType* out_boot_type,
AndroidSdkVersion* out_data_sdk_version);
// Checks if arc-setup should clobber /data/dalvik-cache and /data/app/*/oat
// before starting the container.
void ShouldDeleteDataExecutables(
ArcBootType boot_type,
bool* out_should_delete_data_dalvik_cache_directory,
bool* out_should_delete_data_app_executables);
// Returns a serial number for the user.
std::string GetSerialNumber();
// Mounts pre-installed demo apps to the shared mount point that will be
// passed into the container.
// |demo_apps_image| - path to the image containing set of demo session apps.
// |demo_apps_mount_directory| - the path to which demo apps should be
// mounted.
void MountDemoApps(const base::FilePath& demo_apps_image,
const base::FilePath& demo_apps_mount_directory);
// Bind-mounts the user's /data and /cache to the shared mount point to pass
// them into the container. For demo sessions, it additionally mounts demo
// apps that should be loaded as pre-installed by the container.
void MountSharedAndroidDirectories();
// Unmounts the user's /data and /cache bind-mounted to the shared mount
// point.
void UnmountSharedAndroidDirectories();
// Starts the adbd proxy if the system is running in dev mode, not in a VM,
// and there is kernel support for it.
void MaybeStartAdbdProxy(bool is_dev_mode,
bool is_inside_vm,
const std::string& serialnumber);
// Asks the (partially booted) container to turn itself into a fully
// functional one.
void ContinueContainerBoot(ArcBootType boot_type,
const std::string& serialnumber);
// Ensures that directories that are necessary for starting a container
// exist.
void EnsureContainerDirectories();
// Mounts image files that are necessary for container startup.
void MountOnOnetimeSetup();
// Unmounts image files that have been mounted in MountOnOnetimeSetup.
void UnmountOnOnetimeStop();
// Various bind-mounts inside the container's mount namespace on pre-chroot
// stage.
void BindMountInContainerNamespaceOnPreChroot(
const base::FilePath& rootfs,
const ArcBinaryTranslationType binary_translation_type);
// Restores SELinux contexts of files inside the container's mount namespace.
void RestoreContextOnPreChroot(const base::FilePath& rootfs);
// Creates /dev/.coldboot_done file in the container's mount namespace.
void CreateDevColdbootDoneOnPreChroot(const base::FilePath& rootfs);
// Sends details about updated version to UMA.
void SendUpgradeMetrics(AndroidSdkVersion data_sdk_version);
// Deletes Android data if we are doing an unsupported upgrade.
void DeleteAndroidDataOnUpgrade(AndroidSdkVersion data_sdk_version);
// Converts |version_str| to the enum.
AndroidSdkVersion SdkVersionFromString(const std::string& version_str);
// Gets the image's SDK version. This function returns UNKNOWN when the system
// image hasn't been mounted yet.
AndroidSdkVersion GetSdkVersion();
// Called when arc-setup is called with --mode=setup
void OnSetup();
// Called when arc-setup is called with --mode=boot-continue.
void OnBootContinue();
// Called when arc-setup is called with --mode=stop.
void OnStop();
// Does a setup that is only needed once per Chrome OS boot (i.e.
// --mode=onetime-setup).
void OnOnetimeSetup();
// Called when arc-setup is called with --mode=onetime-stop.
void OnOnetimeStop();
// Called when arc-setup is called with --mode=pre-chroot.
void OnPreChroot();
// Called when arc-apply-per-board-config is executed.
void OnApplyPerBoardConfig();
// Called when arc-create-data is executed.
void OnCreateData();
// Called when arc-remove-data is executed.
void OnRemoveData();
// Called when arc-remove-stale-data is executed.
void OnRemoveStaleData();
// Called when arc-setup is called with --mode=mount-sdcard.
void OnMountSdcard();
// Called when arc-setup is called with --mode=unmount-sdcard.
void OnUnmountSdcard();
// Called when arc-setup is called with --mode=update-restorecon-last.
void OnUpdateRestoreconLast();
// Called on every boot to handle any necessary upgrades.
void OnHandleUpgrade();
// Returns system build property.
std::string GetSystemBuildPropertyOrDie(const std::string& name);
const Mode mode_;
const Config config_;
std::unique_ptr<ArcMounter> arc_mounter_;
std::unique_ptr<ArcPaths> arc_paths_;
std::unique_ptr<ArcSetupMetrics> arc_setup_metrics_;
// Used to prevent multiple reading system properties file. Once this file is
// read, it's content is stored here. If map is empty this indicates that
// properties file was never read.
std::map<std::string, std::string> system_properties_;
};
} // namespace arc
#endif // ARC_SETUP_ARC_SETUP_H_