Merge "Lifecycle: detecting blocked and unhealthy." into rvc-dev

This commit is contained in:
Alex Buynytskyy
2020-05-27 04:15:54 +00:00
committed by Android (Google) Code Review
14 changed files with 301 additions and 112 deletions

View File

@@ -930,6 +930,8 @@ filegroup {
srcs: [ srcs: [
"core/java/android/os/incremental/IIncrementalService.aidl", "core/java/android/os/incremental/IIncrementalService.aidl",
"core/java/android/os/incremental/IncrementalNewFileParams.aidl", "core/java/android/os/incremental/IncrementalNewFileParams.aidl",
"core/java/android/os/incremental/IStorageHealthListener.aidl",
"core/java/android/os/incremental/StorageHealthCheckParams.aidl",
], ],
path: "core/java", path: "core/java",
} }

View File

@@ -19,6 +19,8 @@ package android.os.incremental;
import android.content.pm.DataLoaderParamsParcel; import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.IDataLoaderStatusListener; import android.content.pm.IDataLoaderStatusListener;
import android.os.incremental.IncrementalNewFileParams; import android.os.incremental.IncrementalNewFileParams;
import android.os.incremental.IStorageHealthListener;
import android.os.incremental.StorageHealthCheckParams;
/** @hide */ /** @hide */
interface IIncrementalService { interface IIncrementalService {
@@ -34,7 +36,10 @@ interface IIncrementalService {
* Opens or creates a storage given a target path and data loader params. Returns the storage ID. * Opens or creates a storage given a target path and data loader params. Returns the storage ID.
*/ */
int openStorage(in @utf8InCpp String path); int openStorage(in @utf8InCpp String path);
int createStorage(in @utf8InCpp String path, in DataLoaderParamsParcel params, in IDataLoaderStatusListener listener, int createMode); int createStorage(in @utf8InCpp String path, in DataLoaderParamsParcel params, int createMode,
in IDataLoaderStatusListener statusListener,
in StorageHealthCheckParams healthCheckParams,
in IStorageHealthListener healthListener);
int createLinkedStorage(in @utf8InCpp String path, int otherStorageId, int createMode); int createLinkedStorage(in @utf8InCpp String path, int otherStorageId, int createMode);
/** /**

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2020 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.
*/
package android.os.incremental;
/** @hide */
oneway interface IStorageHealthListener {
/** OK status, no pending reads. */
const int HEALTH_STATUS_OK = 0;
/* Statuses depend on timeouts defined in StorageHealthCheckParams. */
/** Pending reads detected, waiting for params.blockedTimeoutMs to confirm blocked state. */
const int HEALTH_STATUS_READS_PENDING = 1;
/** There are reads pending for params.blockedTimeoutMs, waiting till
* params.unhealthyTimeoutMs to confirm unhealthy state. */
const int HEALTH_STATUS_BLOCKED = 2;
/** There are reads pending for params.unhealthyTimeoutMs>,
* marking storage as unhealthy. */
const int HEALTH_STATUS_UNHEALTHY = 3;
/** Health status callback. */
void onHealthStatus(in int storageId, in int status);
}

View File

@@ -65,7 +65,9 @@ public final class IncrementalFileStorages {
public static IncrementalFileStorages initialize(Context context, public static IncrementalFileStorages initialize(Context context,
@NonNull File stageDir, @NonNull File stageDir,
@NonNull DataLoaderParams dataLoaderParams, @NonNull DataLoaderParams dataLoaderParams,
@Nullable IDataLoaderStatusListener dataLoaderStatusListener, @Nullable IDataLoaderStatusListener statusListener,
@Nullable StorageHealthCheckParams healthCheckParams,
@Nullable IStorageHealthListener healthListener,
List<InstallationFileParcel> addedFiles) throws IOException { List<InstallationFileParcel> addedFiles) throws IOException {
// TODO(b/136132412): sanity check if session should not be incremental // TODO(b/136132412): sanity check if session should not be incremental
IncrementalManager incrementalManager = (IncrementalManager) context.getSystemService( IncrementalManager incrementalManager = (IncrementalManager) context.getSystemService(
@@ -75,9 +77,9 @@ public final class IncrementalFileStorages {
throw new IOException("Failed to obtain incrementalManager."); throw new IOException("Failed to obtain incrementalManager.");
} }
final IncrementalFileStorages result = final IncrementalFileStorages result = new IncrementalFileStorages(stageDir,
new IncrementalFileStorages(stageDir, incrementalManager, dataLoaderParams, incrementalManager, dataLoaderParams, statusListener, healthCheckParams,
dataLoaderStatusListener); healthListener);
for (InstallationFileParcel file : addedFiles) { for (InstallationFileParcel file : addedFiles) {
if (file.location == LOCATION_DATA_APP) { if (file.location == LOCATION_DATA_APP) {
try { try {
@@ -100,7 +102,9 @@ public final class IncrementalFileStorages {
private IncrementalFileStorages(@NonNull File stageDir, private IncrementalFileStorages(@NonNull File stageDir,
@NonNull IncrementalManager incrementalManager, @NonNull IncrementalManager incrementalManager,
@NonNull DataLoaderParams dataLoaderParams, @NonNull DataLoaderParams dataLoaderParams,
@Nullable IDataLoaderStatusListener dataLoaderStatusListener) throws IOException { @Nullable IDataLoaderStatusListener statusListener,
@Nullable StorageHealthCheckParams healthCheckParams,
@Nullable IStorageHealthListener healthListener) throws IOException {
try { try {
mStageDir = stageDir; mStageDir = stageDir;
mIncrementalManager = incrementalManager; mIncrementalManager = incrementalManager;
@@ -117,10 +121,9 @@ public final class IncrementalFileStorages {
mDefaultStorage.bind(stageDir.getAbsolutePath()); mDefaultStorage.bind(stageDir.getAbsolutePath());
} else { } else {
mDefaultStorage = mIncrementalManager.createStorage(stageDir.getAbsolutePath(), mDefaultStorage = mIncrementalManager.createStorage(stageDir.getAbsolutePath(),
dataLoaderParams, dataLoaderParams, IncrementalManager.CREATE_MODE_CREATE
dataLoaderStatusListener, | IncrementalManager.CREATE_MODE_TEMPORARY_BIND, false,
IncrementalManager.CREATE_MODE_CREATE statusListener, healthCheckParams, healthListener);
| IncrementalManager.CREATE_MODE_TEMPORARY_BIND, false);
if (mDefaultStorage == null) { if (mDefaultStorage == null) {
throw new IOException( throw new IOException(
"Couldn't create incremental storage at " + stageDir); "Couldn't create incremental storage at " + stageDir);

View File

@@ -110,11 +110,15 @@ public final class IncrementalManager {
*/ */
@Nullable @Nullable
public IncrementalStorage createStorage(@NonNull String path, public IncrementalStorage createStorage(@NonNull String path,
@NonNull DataLoaderParams params, @Nullable IDataLoaderStatusListener listener, @NonNull DataLoaderParams params,
@CreateMode int createMode, @CreateMode int createMode,
boolean autoStartDataLoader) { boolean autoStartDataLoader,
@Nullable IDataLoaderStatusListener statusListener,
@Nullable StorageHealthCheckParams healthCheckParams,
@Nullable IStorageHealthListener healthListener) {
try { try {
final int id = mService.createStorage(path, params.getData(), listener, createMode); final int id = mService.createStorage(path, params.getData(), createMode,
statusListener, healthCheckParams, healthListener);
if (id < 0) { if (id < 0) {
return null; return null;
} }

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2020 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.
*/
package android.os.incremental;
/**
* @hide
*/
parcelable StorageHealthCheckParams {
/** Timeouts of the oldest pending read.
* Valid values 0ms < blockedTimeoutMs < unhealthyTimeoutMs < storage page read timeout.
* Invalid values will disable health checking. */
/** To consider storage "blocked". */
int blockedTimeoutMs;
/** To consider storage "unhealthy". */
int unhealthyTimeoutMs;
/** After storage is marked "unhealthy", how often to check if it recovered.
* Valid value 1000ms < unhealthyMonitoringMs. */
int unhealthyMonitoringMs;
}

View File

@@ -105,8 +105,10 @@ import android.os.RemoteException;
import android.os.RevocableFileDescriptor; import android.os.RevocableFileDescriptor;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.incremental.IStorageHealthListener;
import android.os.incremental.IncrementalFileStorages; import android.os.incremental.IncrementalFileStorages;
import android.os.incremental.IncrementalManager; import android.os.incremental.IncrementalManager;
import android.os.incremental.StorageHealthCheckParams;
import android.os.storage.StorageManager; import android.os.storage.StorageManager;
import android.provider.Settings.Secure; import android.provider.Settings.Secure;
import android.stats.devicepolicy.DevicePolicyEnums; import android.stats.devicepolicy.DevicePolicyEnums;
@@ -231,6 +233,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String SYSTEM_DATA_LOADER_PACKAGE = "android"; private static final String SYSTEM_DATA_LOADER_PACKAGE = "android";
private static final int INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS = 2000;
private static final int INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS = 7000;
private static final int INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS = 60000;
// TODO: enforce INSTALL_ALLOW_TEST // TODO: enforce INSTALL_ALLOW_TEST
// TODO: enforce INSTALL_ALLOW_DOWNGRADE // TODO: enforce INSTALL_ALLOW_DOWNGRADE
@@ -1568,7 +1574,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
dispatchSessionFinished(error, detailMessage, null); dispatchSessionFinished(error, detailMessage, null);
} }
private void onDataLoaderUnrecoverable() { private void onStorageUnhealthy() {
if (TextUtils.isEmpty(mPackageName)) { if (TextUtils.isEmpty(mPackageName)) {
// The package has not been installed. // The package has not been installed.
return; return;
@@ -2745,7 +2751,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final DataLoaderParams params = this.params.dataLoaderParams; final DataLoaderParams params = this.params.dataLoaderParams;
final boolean manualStartAndDestroy = !isIncrementalInstallation(); final boolean manualStartAndDestroy = !isIncrementalInstallation();
final IDataLoaderStatusListener listener = new IDataLoaderStatusListener.Stub() { final IDataLoaderStatusListener statusListener = new IDataLoaderStatusListener.Stub() {
@Override @Override
public void onStatusChanged(int dataLoaderId, int status) { public void onStatusChanged(int dataLoaderId, int status) {
switch (status) { switch (status) {
@@ -2757,7 +2763,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (mDestroyed || mDataLoaderFinished) { if (mDestroyed || mDataLoaderFinished) {
switch (status) { switch (status) {
case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE: case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
onDataLoaderUnrecoverable(); onStorageUnhealthy();
return; return;
} }
return; return;
@@ -2840,9 +2846,49 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}; };
if (!manualStartAndDestroy) { if (!manualStartAndDestroy) {
final StorageHealthCheckParams healthCheckParams = new StorageHealthCheckParams();
healthCheckParams.blockedTimeoutMs = INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS;
healthCheckParams.unhealthyTimeoutMs = INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS;
healthCheckParams.unhealthyMonitoringMs = INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS;
final boolean systemDataLoader =
params.getComponentName().getPackageName() == SYSTEM_DATA_LOADER_PACKAGE;
final IStorageHealthListener healthListener = new IStorageHealthListener.Stub() {
@Override
public void onHealthStatus(int storageId, int status) {
if (mDestroyed || mDataLoaderFinished) {
// App's installed.
switch (status) {
case IStorageHealthListener.HEALTH_STATUS_UNHEALTHY:
onStorageUnhealthy();
return;
}
return;
}
switch (status) {
case IStorageHealthListener.HEALTH_STATUS_OK:
break;
case IStorageHealthListener.HEALTH_STATUS_READS_PENDING:
case IStorageHealthListener.HEALTH_STATUS_BLOCKED:
if (systemDataLoader) {
// It's OK for ADB data loader to wait for pages.
break;
}
// fallthrough
case IStorageHealthListener.HEALTH_STATUS_UNHEALTHY:
// Even ADB installation can't wait for missing pages for too long.
mDataLoaderFinished = true;
dispatchSessionVerificationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Image is missing pages required for installation.");
break;
}
}
};
try { try {
mIncrementalFileStorages = IncrementalFileStorages.initialize(mContext, stageDir, mIncrementalFileStorages = IncrementalFileStorages.initialize(mContext, stageDir,
params, listener, addedFiles); params, statusListener, healthCheckParams, healthListener, addedFiles);
return false; return false;
} catch (IOException e) { } catch (IOException e) {
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE, e.getMessage(), throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE, e.getMessage(),
@@ -2850,8 +2896,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
} }
} }
if (!dataLoaderManager.bindToDataLoader( if (!dataLoaderManager.bindToDataLoader(sessionId, params.getData(), statusListener)) {
sessionId, params.getData(), listener)) {
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE, throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Failed to initialize data loader"); "Failed to initialize data loader");
} }

View File

@@ -118,14 +118,18 @@ binder::Status BinderIncrementalService::openStorage(const std::string& path,
} }
binder::Status BinderIncrementalService::createStorage( binder::Status BinderIncrementalService::createStorage(
const std::string& path, const content::pm::DataLoaderParamsParcel& params, const ::std::string& path, const ::android::content::pm::DataLoaderParamsParcel& params,
const ::android::sp<::android::content::pm::IDataLoaderStatusListener>& listener, int32_t createMode,
int32_t createMode, int32_t* _aidl_return) { const ::android::sp<::android::content::pm::IDataLoaderStatusListener>& statusListener,
const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
const ::android::sp<::android::os::incremental::IStorageHealthListener>& healthListener,
int32_t* _aidl_return) {
*_aidl_return = *_aidl_return =
mImpl.createStorage(path, const_cast<content::pm::DataLoaderParamsParcel&&>(params), mImpl.createStorage(path, const_cast<content::pm::DataLoaderParamsParcel&&>(params),
listener, android::incremental::IncrementalService::CreateOptions(createMode),
android::incremental::IncrementalService::CreateOptions( statusListener,
createMode)); const_cast<StorageHealthCheckParams&&>(healthCheckParams),
healthListener);
return ok(); return ok();
} }

View File

@@ -41,8 +41,11 @@ public:
binder::Status openStorage(const std::string& path, int32_t* _aidl_return) final; binder::Status openStorage(const std::string& path, int32_t* _aidl_return) final;
binder::Status createStorage( binder::Status createStorage(
const ::std::string& path, const ::android::content::pm::DataLoaderParamsParcel& params, const ::std::string& path, const ::android::content::pm::DataLoaderParamsParcel& params,
const ::android::sp<::android::content::pm::IDataLoaderStatusListener>& listener, int32_t createMode,
int32_t createMode, int32_t* _aidl_return) final; const ::android::sp<::android::content::pm::IDataLoaderStatusListener>& statusListener,
const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
const ::android::sp<IStorageHealthListener>& healthListener,
int32_t* _aidl_return) final;
binder::Status createLinkedStorage(const std::string& path, int32_t otherStorageId, binder::Status createLinkedStorage(const std::string& path, int32_t otherStorageId,
int32_t createMode, int32_t* _aidl_return) final; int32_t createMode, int32_t* _aidl_return) final;
binder::Status makeBindMount(int32_t storageId, const std::string& sourcePath, binder::Status makeBindMount(int32_t storageId, const std::string& sourcePath,
@@ -55,8 +58,7 @@ public:
binder::Status makeDirectories(int32_t storageId, const std::string& path, binder::Status makeDirectories(int32_t storageId, const std::string& path,
int32_t* _aidl_return) final; int32_t* _aidl_return) final;
binder::Status makeFile(int32_t storageId, const std::string& path, binder::Status makeFile(int32_t storageId, const std::string& path,
const ::android::os::incremental::IncrementalNewFileParams& params, const IncrementalNewFileParams& params, int32_t* _aidl_return) final;
int32_t* _aidl_return) final;
binder::Status makeFileFromRange(int32_t storageId, const std::string& targetPath, binder::Status makeFileFromRange(int32_t storageId, const std::string& targetPath,
const std::string& sourcePath, int64_t start, int64_t end, const std::string& sourcePath, int64_t start, int64_t end,
int32_t* _aidl_return) final; int32_t* _aidl_return) final;

View File

@@ -410,9 +410,12 @@ auto IncrementalService::getStorageSlotLocked() -> MountMap::iterator {
} }
} }
StorageId IncrementalService::createStorage( StorageId IncrementalService::createStorage(std::string_view mountPoint,
std::string_view mountPoint, DataLoaderParamsParcel&& dataLoaderParams, content::pm::DataLoaderParamsParcel&& dataLoaderParams,
const DataLoaderStatusListener& dataLoaderStatusListener, CreateOptions options) { CreateOptions options,
const DataLoaderStatusListener& statusListener,
StorageHealthCheckParams&& healthCheckParams,
const StorageHealthListener& healthListener) {
LOG(INFO) << "createStorage: " << mountPoint << " | " << int(options); LOG(INFO) << "createStorage: " << mountPoint << " | " << int(options);
if (!path::isAbsolute(mountPoint)) { if (!path::isAbsolute(mountPoint)) {
LOG(ERROR) << "path is not absolute: " << mountPoint; LOG(ERROR) << "path is not absolute: " << mountPoint;
@@ -545,8 +548,8 @@ StorageId IncrementalService::createStorage(
// Done here as well, all data structures are in good state. // Done here as well, all data structures are in good state.
secondCleanupOnFailure.release(); secondCleanupOnFailure.release();
auto dataLoaderStub = auto dataLoaderStub = prepareDataLoader(*ifs, std::move(dataLoaderParams), &statusListener,
prepareDataLoader(*ifs, std::move(dataLoaderParams), &dataLoaderStatusListener); std::move(healthCheckParams), &healthListener);
CHECK(dataLoaderStub); CHECK(dataLoaderStub);
mountIt->second = std::move(ifs); mountIt->second = std::move(ifs);
@@ -1254,7 +1257,7 @@ bool IncrementalService::mountExistingImage(std::string_view root) {
dataLoaderParams.arguments = loader.arguments(); dataLoaderParams.arguments = loader.arguments();
} }
prepareDataLoader(*ifs, std::move(dataLoaderParams), nullptr); prepareDataLoader(*ifs, std::move(dataLoaderParams));
CHECK(ifs->dataLoaderStub); CHECK(ifs->dataLoaderStub);
std::vector<std::pair<std::string, metadata::BindPoint>> bindPoints; std::vector<std::pair<std::string, metadata::BindPoint>> bindPoints;
@@ -1338,14 +1341,18 @@ void IncrementalService::runCmdLooper() {
IncrementalService::DataLoaderStubPtr IncrementalService::prepareDataLoader( IncrementalService::DataLoaderStubPtr IncrementalService::prepareDataLoader(
IncFsMount& ifs, DataLoaderParamsParcel&& params, IncFsMount& ifs, DataLoaderParamsParcel&& params,
const DataLoaderStatusListener* externalListener) { const DataLoaderStatusListener* statusListener,
StorageHealthCheckParams&& healthCheckParams, const StorageHealthListener* healthListener) {
std::unique_lock l(ifs.lock); std::unique_lock l(ifs.lock);
prepareDataLoaderLocked(ifs, std::move(params), externalListener); prepareDataLoaderLocked(ifs, std::move(params), statusListener, std::move(healthCheckParams),
healthListener);
return ifs.dataLoaderStub; return ifs.dataLoaderStub;
} }
void IncrementalService::prepareDataLoaderLocked(IncFsMount& ifs, DataLoaderParamsParcel&& params, void IncrementalService::prepareDataLoaderLocked(IncFsMount& ifs, DataLoaderParamsParcel&& params,
const DataLoaderStatusListener* externalListener) { const DataLoaderStatusListener* statusListener,
StorageHealthCheckParams&& healthCheckParams,
const StorageHealthListener* healthListener) {
if (ifs.dataLoaderStub) { if (ifs.dataLoaderStub) {
LOG(INFO) << "Skipped data loader preparation because it already exists"; LOG(INFO) << "Skipped data loader preparation because it already exists";
return; return;
@@ -1360,7 +1367,8 @@ void IncrementalService::prepareDataLoaderLocked(IncFsMount& ifs, DataLoaderPara
ifs.dataLoaderStub = ifs.dataLoaderStub =
new DataLoaderStub(*this, ifs.mountId, std::move(params), std::move(fsControlParcel), new DataLoaderStub(*this, ifs.mountId, std::move(params), std::move(fsControlParcel),
externalListener, path::join(ifs.root, constants().mount)); statusListener, std::move(healthCheckParams), healthListener,
path::join(ifs.root, constants().mount));
} }
template <class Duration> template <class Duration>
@@ -1680,19 +1688,24 @@ void IncrementalService::onAppOpChanged(const std::string& packageName) {
IncrementalService::DataLoaderStub::DataLoaderStub(IncrementalService& service, MountId id, IncrementalService::DataLoaderStub::DataLoaderStub(IncrementalService& service, MountId id,
DataLoaderParamsParcel&& params, DataLoaderParamsParcel&& params,
FileSystemControlParcel&& control, FileSystemControlParcel&& control,
const DataLoaderStatusListener* externalListener, const DataLoaderStatusListener* statusListener,
StorageHealthCheckParams&& healthCheckParams,
const StorageHealthListener* healthListener,
std::string&& healthPath) std::string&& healthPath)
: mService(service), : mService(service),
mId(id), mId(id),
mParams(std::move(params)), mParams(std::move(params)),
mControl(std::move(control)), mControl(std::move(control)),
mListener(externalListener ? *externalListener : DataLoaderStatusListener()), mStatusListener(statusListener ? *statusListener : DataLoaderStatusListener()),
mHealthListener(healthListener ? *healthListener : StorageHealthListener()),
mHealthPath(std::move(healthPath)) { mHealthPath(std::move(healthPath)) {
// TODO(b/153874006): enable external health listener.
mHealthListener = {};
healthStatusOk(); healthStatusOk();
} }
IncrementalService::DataLoaderStub::~DataLoaderStub() { IncrementalService::DataLoaderStub::~DataLoaderStub() {
if (mId != kInvalidStorageId) { if (isValid()) {
cleanupResources(); cleanupResources();
} }
} }
@@ -1710,13 +1723,14 @@ void IncrementalService::DataLoaderStub::cleanupResources() {
mStatusCondition.wait_until(lock, now + 60s, [this] { mStatusCondition.wait_until(lock, now + 60s, [this] {
return mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_DESTROYED; return mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
}); });
mListener = {}; mStatusListener = {};
mHealthListener = {};
mId = kInvalidStorageId; mId = kInvalidStorageId;
} }
sp<content::pm::IDataLoader> IncrementalService::DataLoaderStub::getDataLoader() { sp<content::pm::IDataLoader> IncrementalService::DataLoaderStub::getDataLoader() {
sp<IDataLoader> dataloader; sp<IDataLoader> dataloader;
auto status = mService.mDataLoaderManager->getDataLoader(mId, &dataloader); auto status = mService.mDataLoaderManager->getDataLoader(id(), &dataloader);
if (!status.isOk()) { if (!status.isOk()) {
LOG(ERROR) << "Failed to get dataloader: " << status.toString8(); LOG(ERROR) << "Failed to get dataloader: " << status.toString8();
return {}; return {};
@@ -1752,15 +1766,15 @@ void IncrementalService::DataLoaderStub::setTargetStatusLocked(int status) {
auto oldStatus = mTargetStatus; auto oldStatus = mTargetStatus;
mTargetStatus = status; mTargetStatus = status;
mTargetStatusTs = Clock::now(); mTargetStatusTs = Clock::now();
LOG(DEBUG) << "Target status update for DataLoader " << mId << ": " << oldStatus << " -> " LOG(DEBUG) << "Target status update for DataLoader " << id() << ": " << oldStatus << " -> "
<< status << " (current " << mCurrentStatus << ")"; << status << " (current " << mCurrentStatus << ")";
} }
bool IncrementalService::DataLoaderStub::bind() { bool IncrementalService::DataLoaderStub::bind() {
bool result = false; bool result = false;
auto status = mService.mDataLoaderManager->bindToDataLoader(mId, mParams, this, &result); auto status = mService.mDataLoaderManager->bindToDataLoader(id(), mParams, this, &result);
if (!status.isOk() || !result) { if (!status.isOk() || !result) {
LOG(ERROR) << "Failed to bind a data loader for mount " << mId; LOG(ERROR) << "Failed to bind a data loader for mount " << id();
return false; return false;
} }
return true; return true;
@@ -1771,9 +1785,9 @@ bool IncrementalService::DataLoaderStub::create() {
if (!dataloader) { if (!dataloader) {
return false; return false;
} }
auto status = dataloader->create(mId, mParams, mControl, this); auto status = dataloader->create(id(), mParams, mControl, this);
if (!status.isOk()) { if (!status.isOk()) {
LOG(ERROR) << "Failed to start DataLoader: " << status.toString8(); LOG(ERROR) << "Failed to create DataLoader: " << status.toString8();
return false; return false;
} }
return true; return true;
@@ -1784,7 +1798,7 @@ bool IncrementalService::DataLoaderStub::start() {
if (!dataloader) { if (!dataloader) {
return false; return false;
} }
auto status = dataloader->start(mId); auto status = dataloader->start(id());
if (!status.isOk()) { if (!status.isOk()) {
LOG(ERROR) << "Failed to start DataLoader: " << status.toString8(); LOG(ERROR) << "Failed to start DataLoader: " << status.toString8();
return false; return false;
@@ -1793,7 +1807,7 @@ bool IncrementalService::DataLoaderStub::start() {
} }
bool IncrementalService::DataLoaderStub::destroy() { bool IncrementalService::DataLoaderStub::destroy() {
return mService.mDataLoaderManager->unbindFromDataLoader(mId).isOk(); return mService.mDataLoaderManager->unbindFromDataLoader(id()).isOk();
} }
bool IncrementalService::DataLoaderStub::fsmStep() { bool IncrementalService::DataLoaderStub::fsmStep() {
@@ -1852,8 +1866,8 @@ binder::Status IncrementalService::DataLoaderStub::onStatusChanged(MountId mount
return binder::Status:: return binder::Status::
fromServiceSpecificError(-EINVAL, "onStatusChange came to invalid DataLoaderStub"); fromServiceSpecificError(-EINVAL, "onStatusChange came to invalid DataLoaderStub");
} }
if (mId != mountId) { if (id() != mountId) {
LOG(ERROR) << "Mount ID mismatch: expected " << mId << ", but got: " << mountId; LOG(ERROR) << "Mount ID mismatch: expected " << id() << ", but got: " << mountId;
return binder::Status::fromServiceSpecificError(-EPERM, "Mount ID mismatch."); return binder::Status::fromServiceSpecificError(-EPERM, "Mount ID mismatch.");
} }
@@ -1869,7 +1883,7 @@ binder::Status IncrementalService::DataLoaderStub::onStatusChanged(MountId mount
mCurrentStatus = newStatus; mCurrentStatus = newStatus;
targetStatus = mTargetStatus; targetStatus = mTargetStatus;
listener = mListener; listener = mStatusListener;
if (mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE) { if (mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE) {
// For unavailable, unbind from DataLoader to ensure proper re-commit. // For unavailable, unbind from DataLoader to ensure proper re-commit.
@@ -1877,7 +1891,7 @@ binder::Status IncrementalService::DataLoaderStub::onStatusChanged(MountId mount
} }
} }
LOG(DEBUG) << "Current status update for DataLoader " << mId << ": " << oldStatus << " -> " LOG(DEBUG) << "Current status update for DataLoader " << id() << ": " << oldStatus << " -> "
<< newStatus << " (target " << targetStatus << ")"; << newStatus << " (target " << targetStatus << ")";
if (listener) { if (listener) {

View File

@@ -21,6 +21,8 @@
#include <android/content/pm/FileSystemControlParcel.h> #include <android/content/pm/FileSystemControlParcel.h>
#include <android/content/pm/IDataLoaderStatusListener.h> #include <android/content/pm/IDataLoaderStatusListener.h>
#include <android/os/incremental/BnIncrementalServiceConnector.h> #include <android/os/incremental/BnIncrementalServiceConnector.h>
#include <android/os/incremental/BnStorageHealthListener.h>
#include <android/os/incremental/StorageHealthCheckParams.h>
#include <binder/IAppOpsCallback.h> #include <binder/IAppOpsCallback.h>
#include <utils/String16.h> #include <utils/String16.h>
#include <utils/StrongPointer.h> #include <utils/StrongPointer.h>
@@ -56,10 +58,15 @@ using RawMetadata = incfs::RawMetadata;
using Clock = std::chrono::steady_clock; using Clock = std::chrono::steady_clock;
using TimePoint = std::chrono::time_point<Clock>; using TimePoint = std::chrono::time_point<Clock>;
using Seconds = std::chrono::seconds; using Seconds = std::chrono::seconds;
using BootClockTsUs = uint64_t;
using IDataLoaderStatusListener = ::android::content::pm::IDataLoaderStatusListener; using IDataLoaderStatusListener = ::android::content::pm::IDataLoaderStatusListener;
using DataLoaderStatusListener = ::android::sp<IDataLoaderStatusListener>; using DataLoaderStatusListener = ::android::sp<IDataLoaderStatusListener>;
using StorageHealthCheckParams = ::android::os::incremental::StorageHealthCheckParams;
using IStorageHealthListener = ::android::os::incremental::IStorageHealthListener;
using StorageHealthListener = ::android::sp<IStorageHealthListener>;
class IncrementalService final { class IncrementalService final {
public: public:
explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir); explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
@@ -72,6 +79,8 @@ public:
static constexpr StorageId kInvalidStorageId = -1; static constexpr StorageId kInvalidStorageId = -1;
static constexpr StorageId kMaxStorageId = std::numeric_limits<int>::max(); static constexpr StorageId kMaxStorageId = std::numeric_limits<int>::max();
static constexpr BootClockTsUs kMaxBootClockTsUs = std::numeric_limits<BootClockTsUs>::max();
enum CreateOptions { enum CreateOptions {
TemporaryBind = 1, TemporaryBind = 1,
PermanentBind = 2, PermanentBind = 2,
@@ -97,8 +106,9 @@ public:
StorageId createStorage(std::string_view mountPoint, StorageId createStorage(std::string_view mountPoint,
content::pm::DataLoaderParamsParcel&& dataLoaderParams, content::pm::DataLoaderParamsParcel&& dataLoaderParams,
const DataLoaderStatusListener& dataLoaderStatusListener, CreateOptions options, const DataLoaderStatusListener& statusListener,
CreateOptions options = CreateOptions::Default); StorageHealthCheckParams&& healthCheckParams,
const StorageHealthListener& healthListener);
StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage, StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
CreateOptions options = CreateOptions::Default); CreateOptions options = CreateOptions::Default);
StorageId openStorage(std::string_view path); StorageId openStorage(std::string_view path);
@@ -161,7 +171,9 @@ private:
DataLoaderStub(IncrementalService& service, MountId id, DataLoaderStub(IncrementalService& service, MountId id,
content::pm::DataLoaderParamsParcel&& params, content::pm::DataLoaderParamsParcel&& params,
content::pm::FileSystemControlParcel&& control, content::pm::FileSystemControlParcel&& control,
const DataLoaderStatusListener* externalListener, std::string&& healthPath); const DataLoaderStatusListener* statusListener,
StorageHealthCheckParams&& healthCheckParams,
const StorageHealthListener* healthListener, std::string&& healthPath);
~DataLoaderStub(); ~DataLoaderStub();
// Cleans up the internal state and invalidates DataLoaderStub. Any subsequent calls will // Cleans up the internal state and invalidates DataLoaderStub. Any subsequent calls will
// result in an error. // result in an error.
@@ -212,7 +224,8 @@ private:
MountId mId = kInvalidStorageId; MountId mId = kInvalidStorageId;
content::pm::DataLoaderParamsParcel mParams; content::pm::DataLoaderParamsParcel mParams;
content::pm::FileSystemControlParcel mControl; content::pm::FileSystemControlParcel mControl;
DataLoaderStatusListener mListener; DataLoaderStatusListener mStatusListener;
StorageHealthListener mHealthListener;
std::condition_variable mStatusCondition; std::condition_variable mStatusCondition;
int mCurrentStatus = content::pm::IDataLoaderStatusListener::DATA_LOADER_DESTROYED; int mCurrentStatus = content::pm::IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
@@ -291,9 +304,13 @@ private:
DataLoaderStubPtr prepareDataLoader(IncFsMount& ifs, DataLoaderStubPtr prepareDataLoader(IncFsMount& ifs,
content::pm::DataLoaderParamsParcel&& params, content::pm::DataLoaderParamsParcel&& params,
const DataLoaderStatusListener* externalListener = nullptr); const DataLoaderStatusListener* statusListener = nullptr,
StorageHealthCheckParams&& healthCheckParams = {},
const StorageHealthListener* healthListener = nullptr);
void prepareDataLoaderLocked(IncFsMount& ifs, content::pm::DataLoaderParamsParcel&& params, void prepareDataLoaderLocked(IncFsMount& ifs, content::pm::DataLoaderParamsParcel&& params,
const DataLoaderStatusListener* externalListener = nullptr); const DataLoaderStatusListener* statusListener = nullptr,
StorageHealthCheckParams&& healthCheckParams = {},
const StorageHealthListener* healthListener = nullptr);
BindPathMap::const_iterator findStorageLocked(std::string_view path) const; BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
StorageId findStorageId(std::string_view path) const; StorageId findStorageId(std::string_view path) const;

View File

@@ -175,6 +175,10 @@ public:
ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final { ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final {
return incfs::writeBlocks({blocks.data(), size_t(blocks.size())}); return incfs::writeBlocks({blocks.data(), size_t(blocks.size())});
} }
WaitResult waitForPendingReads(const Control& control, std::chrono::milliseconds timeout,
std::vector<incfs::ReadInfo>* pendingReadsBuffer) const final {
return incfs::waitForPendingReads(control, timeout, pendingReadsBuffer);
}
}; };
RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env) RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env)

View File

@@ -69,6 +69,7 @@ public:
using Control = incfs::Control; using Control = incfs::Control;
using FileId = incfs::FileId; using FileId = incfs::FileId;
using ErrorCode = incfs::ErrorCode; using ErrorCode = incfs::ErrorCode;
using WaitResult = incfs::WaitResult;
using ExistingMountCallback = using ExistingMountCallback =
std::function<void(std::string_view root, std::string_view backingDir, std::function<void(std::string_view root, std::string_view backingDir,
@@ -90,6 +91,9 @@ public:
virtual ErrorCode unlink(const Control& control, std::string_view path) const = 0; virtual ErrorCode unlink(const Control& control, std::string_view path) const = 0;
virtual base::unique_fd openForSpecialOps(const Control& control, FileId id) const = 0; virtual base::unique_fd openForSpecialOps(const Control& control, FileId id) const = 0;
virtual ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const = 0; virtual ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const = 0;
virtual WaitResult waitForPendingReads(
const Control& control, std::chrono::milliseconds timeout,
std::vector<incfs::ReadInfo>* pendingReadsBuffer) const = 0;
}; };
class AppOpsManagerWrapper { class AppOpsManagerWrapper {

View File

@@ -284,6 +284,9 @@ public:
MOCK_CONST_METHOD2(unlink, ErrorCode(const Control& control, std::string_view path)); MOCK_CONST_METHOD2(unlink, ErrorCode(const Control& control, std::string_view path));
MOCK_CONST_METHOD2(openForSpecialOps, base::unique_fd(const Control& control, FileId id)); MOCK_CONST_METHOD2(openForSpecialOps, base::unique_fd(const Control& control, FileId id));
MOCK_CONST_METHOD1(writeBlocks, ErrorCode(std::span<const DataBlock> blocks)); MOCK_CONST_METHOD1(writeBlocks, ErrorCode(std::span<const DataBlock> blocks));
MOCK_CONST_METHOD3(waitForPendingReads,
WaitResult(const Control& control, std::chrono::milliseconds timeout,
std::vector<incfs::ReadInfo>* pendingReadsBuffer));
MockIncFs() { ON_CALL(*this, listExistingMounts(_)).WillByDefault(Return()); } MockIncFs() { ON_CALL(*this, listExistingMounts(_)).WillByDefault(Return()); }
@@ -292,12 +295,23 @@ public:
void openMountSuccess() { void openMountSuccess() {
ON_CALL(*this, openMount(_)).WillByDefault(Invoke(this, &MockIncFs::openMountForHealth)); ON_CALL(*this, openMount(_)).WillByDefault(Invoke(this, &MockIncFs::openMountForHealth));
} }
void waitForPendingReadsSuccess() {
ON_CALL(*this, waitForPendingReads(_, _, _))
.WillByDefault(Invoke(this, &MockIncFs::waitForPendingReadsForHealth));
}
static constexpr auto kPendingReadsFd = 42; static constexpr auto kPendingReadsFd = 42;
Control openMountForHealth(std::string_view) { Control openMountForHealth(std::string_view) {
return UniqueControl(IncFs_CreateControl(-1, kPendingReadsFd, -1)); return UniqueControl(IncFs_CreateControl(-1, kPendingReadsFd, -1));
} }
WaitResult waitForPendingReadsForHealth(
const Control& control, std::chrono::milliseconds timeout,
std::vector<incfs::ReadInfo>* pendingReadsBuffer) const {
pendingReadsBuffer->push_back({.bootClockTsUs = 0});
return android::incfs::WaitResult::HaveData;
}
RawMetadata getMountInfoMetadata(const Control& control, std::string_view path) { RawMetadata getMountInfoMetadata(const Control& control, std::string_view path) {
metadata::Mount m; metadata::Mount m;
m.mutable_storage()->set_id(100); m.mutable_storage()->set_id(100);
@@ -499,9 +513,9 @@ TEST_F(IncrementalServiceTest, testCreateStorageMountIncFsFails) {
mVold->mountIncFsFails(); mVold->mountIncFsFails();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(0); EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(0);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_LT(storageId, 0); ASSERT_LT(storageId, 0);
} }
@@ -510,9 +524,9 @@ TEST_F(IncrementalServiceTest, testCreateStorageMountIncFsInvalidControlParcel)
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(0); EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(0);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0); EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_LT(storageId, 0); ASSERT_LT(storageId, 0);
} }
@@ -523,9 +537,9 @@ TEST_F(IncrementalServiceTest, testCreateStorageMakeFileFails) {
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0); EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0);
EXPECT_CALL(*mVold, unmountIncFs(_)); EXPECT_CALL(*mVold, unmountIncFs(_));
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_LT(storageId, 0); ASSERT_LT(storageId, 0);
} }
@@ -537,9 +551,9 @@ TEST_F(IncrementalServiceTest, testCreateStorageBindMountFails) {
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0); EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0);
EXPECT_CALL(*mVold, unmountIncFs(_)); EXPECT_CALL(*mVold, unmountIncFs(_));
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_LT(storageId, 0); ASSERT_LT(storageId, 0);
} }
@@ -555,9 +569,9 @@ TEST_F(IncrementalServiceTest, testCreateStoragePrepareDataLoaderFails) {
EXPECT_CALL(*mDataLoader, destroy(_)).Times(0); EXPECT_CALL(*mDataLoader, destroy(_)).Times(0);
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2); EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_LT(storageId, 0); ASSERT_LT(storageId, 0);
} }
@@ -574,9 +588,9 @@ TEST_F(IncrementalServiceTest, testDeleteStorageSuccess) {
EXPECT_CALL(*mDataLoader, destroy(_)).Times(1); EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2); EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_GE(storageId, 0); ASSERT_GE(storageId, 0);
mIncrementalService->deleteStorage(storageId); mIncrementalService->deleteStorage(storageId);
} }
@@ -594,9 +608,9 @@ TEST_F(IncrementalServiceTest, testDataLoaderDestroyed) {
EXPECT_CALL(*mDataLoader, destroy(_)).Times(1); EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2); EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_GE(storageId, 0); ASSERT_GE(storageId, 0);
// Simulated crash/other connection breakage. // Simulated crash/other connection breakage.
mDataLoaderManager->setDataLoaderStatusDestroyed(); mDataLoaderManager->setDataLoaderStatusDestroyed();
@@ -616,9 +630,9 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderCreate) {
EXPECT_CALL(*mDataLoader, destroy(_)).Times(1); EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2); EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_GE(storageId, 0); ASSERT_GE(storageId, 0);
mDataLoaderManager->setDataLoaderStatusCreated(); mDataLoaderManager->setDataLoaderStatusCreated();
ASSERT_TRUE(mIncrementalService->startLoading(storageId)); ASSERT_TRUE(mIncrementalService->startLoading(storageId));
@@ -639,9 +653,9 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderPendingStart) {
EXPECT_CALL(*mDataLoader, destroy(_)).Times(1); EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2); EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_GE(storageId, 0); ASSERT_GE(storageId, 0);
ASSERT_TRUE(mIncrementalService->startLoading(storageId)); ASSERT_TRUE(mIncrementalService->startLoading(storageId));
mDataLoaderManager->setDataLoaderStatusCreated(); mDataLoaderManager->setDataLoaderStatusCreated();
@@ -661,9 +675,9 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderCreateUnavailable) {
EXPECT_CALL(*mDataLoader, destroy(_)).Times(1); EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2); EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_GE(storageId, 0); ASSERT_GE(storageId, 0);
mDataLoaderManager->setDataLoaderStatusUnavailable(); mDataLoaderManager->setDataLoaderStatusUnavailable();
} }
@@ -672,6 +686,7 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderRecreateOnPendingReads) {
mVold->mountIncFsSuccess(); mVold->mountIncFsSuccess();
mIncFs->makeFileSuccess(); mIncFs->makeFileSuccess();
mIncFs->openMountSuccess(); mIncFs->openMountSuccess();
mIncFs->waitForPendingReadsSuccess();
mVold->bindMountSuccess(); mVold->bindMountSuccess();
mDataLoader->initializeCreateOkNoStatus(); mDataLoader->initializeCreateOkNoStatus();
mDataLoaderManager->bindToDataLoaderSuccess(); mDataLoaderManager->bindToDataLoaderSuccess();
@@ -685,9 +700,9 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderRecreateOnPendingReads) {
EXPECT_CALL(*mLooper, addFd(MockIncFs::kPendingReadsFd, _, _, _, _)).Times(1); EXPECT_CALL(*mLooper, addFd(MockIncFs::kPendingReadsFd, _, _, _, _)).Times(1);
EXPECT_CALL(*mLooper, removeFd(MockIncFs::kPendingReadsFd)).Times(1); EXPECT_CALL(*mLooper, removeFd(MockIncFs::kPendingReadsFd)).Times(1);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_GE(storageId, 0); ASSERT_GE(storageId, 0);
mDataLoaderManager->setDataLoaderStatusUnavailable(); mDataLoaderManager->setDataLoaderStatusUnavailable();
ASSERT_NE(nullptr, mLooper->mCallback); ASSERT_NE(nullptr, mLooper->mCallback);
@@ -712,9 +727,9 @@ TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccess) {
// Not expecting callback removal. // Not expecting callback removal.
EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0); EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_GE(storageId, 0); ASSERT_GE(storageId, 0);
ASSERT_GE(mDataLoader->setStorageParams(true), 0); ASSERT_GE(mDataLoader->setStorageParams(true), 0);
} }
@@ -739,9 +754,9 @@ TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccessAndPermissionChang
// After callback is called, disable read logs and remove callback. // After callback is called, disable read logs and remove callback.
EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(1); EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(1);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_GE(storageId, 0); ASSERT_GE(storageId, 0);
ASSERT_GE(mDataLoader->setStorageParams(true), 0); ASSERT_GE(mDataLoader->setStorageParams(true), 0);
ASSERT_NE(nullptr, mAppOpsManager->mStoredCallback.get()); ASSERT_NE(nullptr, mAppOpsManager->mStoredCallback.get());
@@ -762,9 +777,9 @@ TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsCheckPermissionFails) {
EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(0); EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(0);
EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0); EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_GE(storageId, 0); ASSERT_GE(storageId, 0);
ASSERT_LT(mDataLoader->setStorageParams(true), 0); ASSERT_LT(mDataLoader->setStorageParams(true), 0);
} }
@@ -785,9 +800,9 @@ TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsFails) {
EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(0); EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(0);
EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0); EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0);
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
ASSERT_GE(storageId, 0); ASSERT_GE(storageId, 0);
ASSERT_LT(mDataLoader->setStorageParams(true), 0); ASSERT_LT(mDataLoader->setStorageParams(true), 0);
} }
@@ -799,9 +814,9 @@ TEST_F(IncrementalServiceTest, testMakeDirectory) {
mDataLoaderManager->bindToDataLoaderSuccess(); mDataLoaderManager->bindToDataLoaderSuccess();
mDataLoaderManager->getDataLoaderSuccess(); mDataLoaderManager->getDataLoaderSuccess();
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
std::string dir_path("test"); std::string dir_path("test");
// Expecting incfs to call makeDir on a path like: // Expecting incfs to call makeDir on a path like:
@@ -823,9 +838,9 @@ TEST_F(IncrementalServiceTest, testMakeDirectories) {
mDataLoaderManager->bindToDataLoaderSuccess(); mDataLoaderManager->bindToDataLoaderSuccess();
mDataLoaderManager->getDataLoaderSuccess(); mDataLoaderManager->getDataLoaderSuccess();
TemporaryDir tempDir; TemporaryDir tempDir;
int storageId = int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {}, IncrementalService::CreateOptions::CreateNew,
IncrementalService::CreateOptions::CreateNew); {}, {}, {});
auto first = "first"sv; auto first = "first"sv;
auto second = "second"sv; auto second = "second"sv;
auto third = "third"sv; auto third = "third"sv;