diff options
author | Amin Hassani <ahassani@chromium.org> | 2020-10-29 16:47:58 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-11-03 03:19:41 +0000 |
commit | ec7bc11c3103d9310568a391271be52baef273a7 (patch) | |
tree | c7d69b3c47c8ff86876cd662b4ace630c1e1362b /aosp/dynamic_partition_control_android.h | |
parent | 24e1d72aa2a1024417121b0d91bf9a6f3b883a96 (diff) |
update_engine: Create cros vs. aosp boundary clear
Its time to make the boundary between Chrome OS and Android code more
clear. This CL moves all CrOS only code to "chromeos" directory and the
same for Android (in "android" directory). This way we would easily know
which code is uses in which project and can keep the code cleaner and
more maintainable.
One big remaining problem is download_action* files. It seems like
DownloadAction class does a lot of things that chrome OS needs and it
depends on a lot of Chrome OS stuff, but Android is also using thie
Action in a way that circumvent the Chrome OS stuff. For example Android
checks for SystemState to be nullptr to not do things. This is really
fragile and needs to change. Probably Android Team has to implement
their own DownloadAction of some sort and not re use the Chrome OS one
in a very fragile way.
Removed a few android files that have not been used anywhere.
Changed some clang-format and lint issues in order to pass preupload.
BUG=b:171829801
TEST=cros_workon_make --board reef --test update_engine
Change-Id: I3fff1d4a100a065a5c1484a845241b5521614d9f
Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/2508965
Tested-by: Amin Hassani <ahassani@chromium.org>
Auto-Submit: Amin Hassani <ahassani@chromium.org>
Reviewed-by: Jae Hoon Kim <kimjae@chromium.org>
Reviewed-by: Tianjie Xu <xunchang@google.com>
Reviewed-by: Kelvin Zhang <zhangkelvin@google.com>
Commit-Queue: Amin Hassani <ahassani@chromium.org>
Diffstat (limited to 'aosp/dynamic_partition_control_android.h')
-rw-r--r-- | aosp/dynamic_partition_control_android.h | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/aosp/dynamic_partition_control_android.h b/aosp/dynamic_partition_control_android.h new file mode 100644 index 00000000..79f87d9d --- /dev/null +++ b/aosp/dynamic_partition_control_android.h @@ -0,0 +1,294 @@ +// +// Copyright (C) 2018 The Android Open Source Project +// +// 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. +// + +#ifndef UPDATE_ENGINE_AOSP_DYNAMIC_PARTITION_CONTROL_ANDROID_H_ +#define UPDATE_ENGINE_AOSP_DYNAMIC_PARTITION_CONTROL_ANDROID_H_ + +#include <memory> +#include <set> +#include <string> +#include <vector> + +#include <base/files/file_util.h> +#include <libsnapshot/auto_device.h> +#include <libsnapshot/snapshot.h> + +#include "update_engine/common/dynamic_partition_control_interface.h" + +namespace chromeos_update_engine { + +class DynamicPartitionControlAndroid : public DynamicPartitionControlInterface { + public: + DynamicPartitionControlAndroid(); + ~DynamicPartitionControlAndroid(); + FeatureFlag GetDynamicPartitionsFeatureFlag() override; + FeatureFlag GetVirtualAbFeatureFlag() override; + bool OptimizeOperation(const std::string& partition_name, + const InstallOperation& operation, + InstallOperation* optimized) override; + void Cleanup() override; + + bool PreparePartitionsForUpdate(uint32_t source_slot, + uint32_t target_slot, + const DeltaArchiveManifest& manifest, + bool update, + uint64_t* required_size) override; + bool FinishUpdate(bool powerwash_required) override; + std::unique_ptr<AbstractAction> GetCleanupPreviousUpdateAction( + BootControlInterface* boot_control, + PrefsInterface* prefs, + CleanupPreviousUpdateActionDelegateInterface* delegate) override; + + bool ResetUpdate(PrefsInterface* prefs) override; + + bool ListDynamicPartitionsForSlot( + uint32_t current_slot, std::vector<std::string>* partitions) override; + + bool VerifyExtentsForUntouchedPartitions( + uint32_t source_slot, + uint32_t target_slot, + const std::vector<std::string>& partitions) override; + + bool GetDeviceDir(std::string* path) override; + + // Return the device for partition |partition_name| at slot |slot|. + // |current_slot| should be set to the current active slot. + // Note: this function is only used by BootControl*::GetPartitionDevice. + // Other callers should prefer BootControl*::GetPartitionDevice over + // BootControl*::GetDynamicPartitionControl()->GetPartitionDevice(). + bool GetPartitionDevice(const std::string& partition_name, + uint32_t slot, + uint32_t current_slot, + bool not_in_payload, + std::string* device, + bool* is_dynamic); + + bool GetPartitionDevice(const std::string& partition_name, + uint32_t slot, + uint32_t current_slot, + std::string* device); + + protected: + // These functions are exposed for testing. + + // Unmap logical partition on device mapper. This is the reverse operation + // of MapPartitionOnDeviceMapper. + // Returns true if unmapped successfully. + virtual bool UnmapPartitionOnDeviceMapper( + const std::string& target_partition_name); + + // Retrieves metadata from |super_device| at slot |slot|. + virtual std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder( + const std::string& super_device, uint32_t slot); + + // Retrieves metadata from |super_device| at slot |source_slot|. And modifies + // the metadata so that during updates, the metadata can be written to + // |target_slot|. In particular, on retrofit devices, the returned metadata + // automatically includes block devices at |target_slot|. + virtual std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder( + const std::string& super_device, + uint32_t source_slot, + uint32_t target_slot); + + // Write metadata |builder| to |super_device| at slot |target_slot|. + virtual bool StoreMetadata(const std::string& super_device, + android::fs_mgr::MetadataBuilder* builder, + uint32_t target_slot); + + // Map logical partition on device-mapper. + // |super_device| is the device path of the physical partition ("super"). + // |target_partition_name| is the identifier used in metadata; for example, + // "vendor_a" + // |slot| is the selected slot to mount; for example, 0 for "_a". + // Returns true if mapped successfully; if so, |path| is set to the device + // path of the mapped logical partition. + virtual bool MapPartitionOnDeviceMapper( + const std::string& super_device, + const std::string& target_partition_name, + uint32_t slot, + bool force_writable, + std::string* path); + + // Return true if a static partition exists at device path |path|. + virtual bool DeviceExists(const std::string& path); + + // Returns the current state of the underlying device mapper device + // with given name. + // One of INVALID, SUSPENDED or ACTIVE. + virtual android::dm::DmDeviceState GetState(const std::string& name); + + // Returns the path to the device mapper device node in '/dev' corresponding + // to 'name'. If the device does not exist, false is returned, and the path + // parameter is not set. + virtual bool GetDmDevicePathByName(const std::string& name, + std::string* path); + + // Return the name of the super partition (which stores super partition + // metadata) for a given slot. + virtual std::string GetSuperPartitionName(uint32_t slot); + + virtual void set_fake_mapped_devices(const std::set<std::string>& fake); + + // Allow mock objects to override this to test recovery mode. + virtual bool IsRecovery(); + + // Determine path for system_other partition. + // |source_slot| should be current slot. + // |target_slot| should be "other" slot. + // |partition_name_suffix| should be "system" + suffix(|target_slot|). + // Return true and set |path| if successful. + // Set |path| to empty if no need to erase system_other. + // Set |should_unmap| to true if path needs to be unmapped later. + // + // Note: system_other cannot use GetPartitionDevice or + // GetDynamicPartitionDevice because: + // - super partition metadata may be loaded from the source slot + // - UPDATED flag needs to be check to skip erasing if partition is not + // created by flashing tools + // - Snapshots from previous update attempts should not be used. + virtual bool GetSystemOtherPath(uint32_t source_slot, + uint32_t target_slot, + const std::string& partition_name_suffix, + std::string* path, + bool* should_unmap); + + // Returns true if any entry in the fstab file in |path| has AVB enabled, + // false if not enabled, and nullopt for any error. + virtual std::optional<bool> IsAvbEnabledInFstab(const std::string& path); + + // Returns true if system_other has AVB enabled, false if not enabled, and + // nullopt for any error. + virtual std::optional<bool> IsAvbEnabledOnSystemOther(); + + // Erase system_other partition that may contain system_other.img. + // After the update, the content of system_other may be corrupted but with + // valid AVB footer. If the update is rolled back and factory data reset is + // triggered, system_b fails to be mapped with verity errors (see + // b/152444348). Erase the system_other so that mapping system_other is + // skipped. + virtual bool EraseSystemOtherAvbFooter(uint32_t source_slot, + uint32_t target_slot); + + // Helper for PreparePartitionsForUpdate. Used for devices with dynamic + // partitions updating without snapshots. + // If |delete_source| is set, source partitions are deleted before resizing + // target partitions (using DeleteSourcePartitions). + virtual bool PrepareDynamicPartitionsForUpdate( + uint32_t source_slot, + uint32_t target_slot, + const DeltaArchiveManifest& manifest, + bool delete_source); + + private: + friend class DynamicPartitionControlAndroidTest; + friend class SnapshotPartitionTestP; + + void UnmapAllPartitions(); + bool MapPartitionInternal(const std::string& super_device, + const std::string& target_partition_name, + uint32_t slot, + bool force_writable, + std::string* path); + + // Update |builder| according to |partition_metadata|. + // - In Android mode, this is only called when the device + // does not have Virtual A/B. + // - When sideloading, this maybe called as a fallback path if CoW cannot + // be created. + bool UpdatePartitionMetadata(android::fs_mgr::MetadataBuilder* builder, + uint32_t target_slot, + const DeltaArchiveManifest& manifest); + + // Helper for PreparePartitionsForUpdate. Used for snapshotted partitions for + // Virtual A/B update. + bool PrepareSnapshotPartitionsForUpdate(uint32_t source_slot, + uint32_t target_slot, + const DeltaArchiveManifest& manifest, + uint64_t* required_size); + + enum class DynamicPartitionDeviceStatus { + SUCCESS, + ERROR, + TRY_STATIC, + }; + + // Return SUCCESS and path in |device| if partition is dynamic. + // Return ERROR if any error. + // Return TRY_STATIC if caller should resolve the partition as a static + // partition instead. + DynamicPartitionDeviceStatus GetDynamicPartitionDevice( + const base::FilePath& device_dir, + const std::string& partition_name_suffix, + uint32_t slot, + uint32_t current_slot, + bool not_in_payload, + std::string* device); + + // Return true if |partition_name_suffix| is a block device of + // super partition metadata slot |slot|. + bool IsSuperBlockDevice(const base::FilePath& device_dir, + uint32_t current_slot, + const std::string& partition_name_suffix); + + // If sideloading a full OTA, delete source partitions from |builder|. + bool DeleteSourcePartitions(android::fs_mgr::MetadataBuilder* builder, + uint32_t source_slot, + const DeltaArchiveManifest& manifest); + + // Returns true if metadata is expected to be mounted, false otherwise. + // Note that it returns false on non-Virtual A/B devices. + // + // Almost all functions of SnapshotManager depends on metadata being mounted. + // - In Android mode for Virtual A/B devices, assume it is mounted. If not, + // let caller fails when calling into SnapshotManager. + // - In recovery for Virtual A/B devices, it is possible that metadata is not + // formatted, hence it cannot be mounted. Caller should not call into + // SnapshotManager. + // - On non-Virtual A/B devices, updates do not depend on metadata partition. + // Caller should not call into SnapshotManager. + // + // This function does NOT mount metadata partition. Use EnsureMetadataMounted + // to mount metadata partition. + bool ExpectMetadataMounted(); + + // Ensure /metadata is mounted. Returns true if successful, false otherwise. + // + // Note that this function returns true on non-Virtual A/B devices without + // doing anything. + bool EnsureMetadataMounted(); + + // Set boolean flags related to target build. This includes flags like + // target_supports_snapshot_ and is_target_dynamic_. + bool SetTargetBuildVars(const DeltaArchiveManifest& manifest); + + std::set<std::string> mapped_devices_; + const FeatureFlag dynamic_partitions_; + const FeatureFlag virtual_ab_; + std::unique_ptr<android::snapshot::ISnapshotManager> snapshot_; + std::unique_ptr<android::snapshot::AutoDevice> metadata_device_; + bool target_supports_snapshot_ = false; + // Whether the target partitions should be loaded as dynamic partitions. Set + // by PreparePartitionsForUpdate() per each update. + bool is_target_dynamic_ = false; + uint32_t source_slot_ = UINT32_MAX; + uint32_t target_slot_ = UINT32_MAX; + + DISALLOW_COPY_AND_ASSIGN(DynamicPartitionControlAndroid); +}; + +} // namespace chromeos_update_engine + +#endif // UPDATE_ENGINE_AOSP_DYNAMIC_PARTITION_CONTROL_ANDROID_H_ |