Merge "Lifecycle: detecting blocked and unhealthy." into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
4e5ff2eb7d
@@ -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",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
35
core/java/android/os/incremental/IStorageHealthListener.aidl
Normal file
35
core/java/android/os/incremental/IStorageHealthListener.aidl
Normal 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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user