DataLoader lifecycle.

- restarting DataLoaders for not fully downloaded mounts,
- exponential backoff retry on DataLoader restart.

Bug: 173223115
Bug: 160634487
Test: atest PackageManagerShellCommandTest PackageManagerShellCommandIncrementalTest IncrementalServiceTest PackageManagerServiceTest ChecksumsTest
Change-Id: I5a93fd515ef0fec09452ce7bb4cd79fbd283d45f
This commit is contained in:
Alex Buynytskyy
2021-02-06 20:31:43 -08:00
parent de3ce41f28
commit b19ee3ebd8
9 changed files with 221 additions and 41 deletions

View File

@@ -41,6 +41,7 @@ public class DataLoaderManager {
* @param dataLoaderId ID for the new data loader binder service.
* @param params DataLoaderParamsParcel object that contains data loader params, including
* its package name, class name, and additional parameters.
* @param bindDelayMs introduce a delay before actual bind in case we want to avoid busylooping
* @param listener Callback for the data loader service to report status back to the
* caller.
* @return false if 1) target ID collides with a data loader that is already bound to data
@@ -48,9 +49,9 @@ public class DataLoaderManager {
* or 4) fails to bind to the specified data loader service, otherwise return true.
*/
public boolean bindToDataLoader(int dataLoaderId, @NonNull DataLoaderParamsParcel params,
@NonNull IDataLoaderStatusListener listener) {
long bindDelayMs, @NonNull IDataLoaderStatusListener listener) {
try {
return mService.bindToDataLoader(dataLoaderId, params, listener);
return mService.bindToDataLoader(dataLoaderId, params, bindDelayMs, listener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -23,7 +23,7 @@ import android.content.pm.IDataLoaderStatusListener;
/** @hide */
interface IDataLoaderManager {
boolean bindToDataLoader(int id, in DataLoaderParamsParcel params,
boolean bindToDataLoader(int id, in DataLoaderParamsParcel params, long bindDelayMs,
IDataLoaderStatusListener listener);
IDataLoader getDataLoader(int dataLoaderId);
void unbindFromDataLoader(int dataLoaderId);

View File

@@ -27,6 +27,8 @@ import android.content.pm.IDataLoaderManager;
import android.content.pm.IDataLoaderStatusListener;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -45,12 +47,20 @@ import java.util.List;
public class DataLoaderManagerService extends SystemService {
private static final String TAG = "DataLoaderManager";
private final Context mContext;
private final HandlerThread mThread;
private final Handler mHandler;
private final DataLoaderManagerBinderService mBinderService;
private SparseArray<DataLoaderServiceConnection> mServiceConnections = new SparseArray<>();
public DataLoaderManagerService(Context context) {
super(context);
mContext = context;
mThread = new HandlerThread(TAG);
mThread.start();
mHandler = new Handler(mThread.getLooper());
mBinderService = new DataLoaderManagerBinderService();
}
@@ -62,7 +72,7 @@ public class DataLoaderManagerService extends SystemService {
final class DataLoaderManagerBinderService extends IDataLoaderManager.Stub {
@Override
public boolean bindToDataLoader(int dataLoaderId, DataLoaderParamsParcel params,
IDataLoaderStatusListener listener) {
long bindDelayMs, IDataLoaderStatusListener listener) {
synchronized (mServiceConnections) {
if (mServiceConnections.get(dataLoaderId) != null) {
return true;
@@ -76,19 +86,21 @@ public class DataLoaderManagerService extends SystemService {
}
// Binds to the specific data loader service.
DataLoaderServiceConnection connection = new DataLoaderServiceConnection(dataLoaderId,
listener);
final DataLoaderServiceConnection connection = new DataLoaderServiceConnection(
dataLoaderId, listener);
Intent intent = new Intent();
final Intent intent = new Intent();
intent.setComponent(dataLoaderComponent);
if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE,
UserHandle.of(UserHandle.getCallingUserId()))) {
Slog.e(TAG,
"Failed to bind to: " + dataLoaderComponent + " for ID=" + dataLoaderId);
mContext.unbindService(connection);
return false;
}
return true;
return mHandler.postDelayed(() -> {
if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE,
mHandler, UserHandle.of(UserHandle.getCallingUserId()))) {
Slog.e(TAG,
"Failed to bind to: " + dataLoaderComponent + " for ID="
+ dataLoaderId);
mContext.unbindService(connection);
}
}, bindDelayMs);
}
/**

View File

@@ -3778,7 +3778,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
if (!dataLoaderManager.bindToDataLoader(sessionId, params.getData(), statusListener)) {
final long bindDelayMs = 0;
if (!dataLoaderManager.bindToDataLoader(sessionId, params.getData(), bindDelayMs,
statusListener)) {
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Failed to initialize data loader");
}

View File

@@ -69,6 +69,14 @@ struct Constants {
static constexpr auto progressUpdateInterval = 1000ms;
static constexpr auto perUidTimeoutOffset = progressUpdateInterval * 2;
static constexpr auto minPerUidTimeout = progressUpdateInterval * 3;
// If DL was up and not crashing for 10mins, we consider it healthy and reset all delays.
static constexpr auto healthyDataLoaderUptime = 10min;
// 10s, 100s (~2min), 1000s (~15min), 10000s (~3hrs)
static constexpr auto minBindDelay = 10s;
static constexpr auto maxBindDelay = 10000s;
static constexpr auto bindDelayMultiplier = 10;
static constexpr auto bindDelayJitterDivider = 10;
};
static const Constants& constants() {
@@ -386,6 +394,28 @@ void IncrementalService::onDump(int fd) {
dprintf(fd, "}\n");
}
bool IncrementalService::needStartDataLoaderLocked(IncFsMount& ifs) {
if (ifs.dataLoaderStub->params().packageName == Constants::systemPackage) {
return true;
}
// Check all permanent binds.
for (auto&& [_, bindPoint] : ifs.bindPoints) {
if (bindPoint.kind != BindKind::Permanent) {
continue;
}
const auto progress = getLoadingProgressFromPath(ifs, bindPoint.sourceDir,
/*stopOnFirstIncomplete=*/true);
if (!progress.isError() && !progress.fullyLoaded()) {
LOG(INFO) << "Non system mount: [" << bindPoint.sourceDir
<< "], partial progress: " << progress.getProgress() * 100 << "%";
return true;
}
}
return false;
}
void IncrementalService::onSystemReady() {
if (mSystemReady.exchange(true)) {
return;
@@ -396,8 +426,11 @@ void IncrementalService::onSystemReady() {
std::lock_guard l(mLock);
mounts.reserve(mMounts.size());
for (auto&& [id, ifs] : mMounts) {
if (ifs->mountId == id &&
ifs->dataLoaderStub->params().packageName == Constants::systemPackage) {
if (ifs->mountId != id) {
continue;
}
if (needStartDataLoaderLocked(*ifs)) {
mounts.push_back(ifs);
}
}
@@ -1539,6 +1572,11 @@ static long elapsedMcs(Duration start, Duration end) {
return std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
}
template <class Duration>
static constexpr auto castToMs(Duration d) {
return std::chrono::duration_cast<std::chrono::milliseconds>(d);
}
// Extract lib files from zip, create new files in incfs and write data to them
// Lib files should be placed next to the APK file in the following matter:
// Example:
@@ -2134,9 +2172,43 @@ void IncrementalService::DataLoaderStub::setTargetStatusLocked(int status) {
<< status << " (current " << mCurrentStatus << ")";
}
Milliseconds IncrementalService::DataLoaderStub::updateBindDelay() {
std::unique_lock lock(mMutex);
const auto previousBindTs = mPreviousBindTs;
const auto now = Clock::now();
mPreviousBindTs = now;
const auto nonCrashingInterval = std::max(castToMs(now - previousBindTs), 100ms);
if (previousBindTs.time_since_epoch() == Clock::duration::zero() ||
nonCrashingInterval > Constants::healthyDataLoaderUptime) {
mPreviousBindDelay = 0ms;
return mPreviousBindDelay;
}
constexpr auto minBindDelayMs = castToMs(Constants::minBindDelay);
constexpr auto maxBindDelayMs = castToMs(Constants::maxBindDelay);
const auto bindDelayMs =
std::min(std::max(mPreviousBindDelay * Constants::bindDelayMultiplier, minBindDelayMs),
maxBindDelayMs)
.count();
const auto bindDelayJitterRangeMs = bindDelayMs / Constants::bindDelayJitterDivider;
const auto bindDelayJitterMs = rand() % (bindDelayJitterRangeMs * 2) - bindDelayJitterRangeMs;
mPreviousBindDelay = std::chrono::milliseconds(bindDelayMs + bindDelayJitterMs);
return mPreviousBindDelay;
}
bool IncrementalService::DataLoaderStub::bind() {
const auto bindDelay = updateBindDelay();
if (bindDelay > 1s) {
LOG(INFO) << "Delaying bind to " << mParams.packageName << " by "
<< bindDelay.count() / 1000 << "s";
}
bool result = false;
auto status = mService.mDataLoaderManager->bindToDataLoader(id(), mParams, this, &result);
auto status = mService.mDataLoaderManager->bindToDataLoader(id(), mParams, bindDelay.count(),
this, &result);
if (!status.isOk() || !result) {
LOG(ERROR) << "Failed to bind a data loader for mount " << id();
return false;
@@ -2249,7 +2321,8 @@ binder::Status IncrementalService::DataLoaderStub::onStatusChanged(MountId mount
listener = mStatusListener;
if (mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE) {
if (mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE ||
mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_UNRECOVERABLE) {
// For unavailable, unbind from DataLoader to ensure proper re-commit.
setTargetStatusLocked(IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
}
@@ -2544,6 +2617,9 @@ void IncrementalService::DataLoaderStub::onDump(int fd) {
dprintf(fd, " blockIndex: %d\n", pendingRead.block);
dprintf(fd, " bootClockTsUs: %lld\n", (long long)pendingRead.bootClockTsUs);
}
dprintf(fd, " bind: %llds ago (delay: %llds)\n",
(long long)(elapsedMcs(mPreviousBindTs, Clock::now()) / 1000000),
(long long)(mPreviousBindDelay.count() / 1000));
dprintf(fd, " }\n");
const auto& params = mParams;
dprintf(fd, " dataLoaderParams: {\n");

View File

@@ -245,7 +245,6 @@ private:
void setTargetStatusLocked(int status);
bool fsmStep();
bool fsmStep(int currentStatus, int targetStatus);
void onHealthStatus(StorageHealthListener healthListener, int healthStatus);
void updateHealthStatus(bool baseline = false);
@@ -259,6 +258,8 @@ private:
BootClockTsUs getOldestPendingReadTs();
Milliseconds updateBindDelay();
void registerForPendingReads();
void unregisterFromPendingReads();
@@ -276,6 +277,9 @@ private:
int mTargetStatus = content::pm::IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
TimePoint mTargetStatusTs = {};
TimePoint mPreviousBindTs = {};
Milliseconds mPreviousBindDelay = {};
std::string mHealthPath;
incfs::UniqueControl mHealthControl;
struct {
@@ -370,6 +374,8 @@ private:
void addBindMountRecordLocked(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
std::string&& source, std::string&& target, BindKind kind);
bool needStartDataLoaderLocked(IncFsMount& ifs);
DataLoaderStubPtr prepareDataLoader(IncFsMount& ifs,
content::pm::DataLoaderParamsParcel&& params,
const DataLoaderStatusListener* statusListener = nullptr,

View File

@@ -70,9 +70,10 @@ public:
~RealDataLoaderManager() = default;
binder::Status bindToDataLoader(MountId mountId,
const content::pm::DataLoaderParamsParcel& params,
int bindDelayMs,
const sp<content::pm::IDataLoaderStatusListener>& listener,
bool* _aidl_return) const final {
return mInterface->bindToDataLoader(mountId, params, listener, _aidl_return);
return mInterface->bindToDataLoader(mountId, params, bindDelayMs, listener, _aidl_return);
}
binder::Status getDataLoader(MountId mountId,
sp<content::pm::IDataLoader>* _aidl_return) const final {

View File

@@ -63,7 +63,7 @@ class DataLoaderManagerWrapper {
public:
virtual ~DataLoaderManagerWrapper() = default;
virtual binder::Status bindToDataLoader(
MountId mountId, const content::pm::DataLoaderParamsParcel& params,
MountId mountId, const content::pm::DataLoaderParamsParcel& params, int bindDelayMs,
const sp<content::pm::IDataLoaderStatusListener>& listener, bool* result) const = 0;
virtual binder::Status getDataLoader(MountId mountId,
sp<content::pm::IDataLoader>* result) const = 0;

View File

@@ -208,8 +208,9 @@ public:
EXPECT_TRUE(mDataLoaderHolder != nullptr);
}
MOCK_CONST_METHOD4(bindToDataLoader,
MOCK_CONST_METHOD5(bindToDataLoader,
binder::Status(int32_t mountId, const DataLoaderParamsParcel& params,
int bindDelayMs,
const sp<IDataLoaderStatusListener>& listener,
bool* _aidl_return));
MOCK_CONST_METHOD2(getDataLoader,
@@ -217,11 +218,11 @@ public:
MOCK_CONST_METHOD1(unbindFromDataLoader, binder::Status(int32_t mountId));
void bindToDataLoaderSuccess() {
ON_CALL(*this, bindToDataLoader(_, _, _, _))
ON_CALL(*this, bindToDataLoader(_, _, _, _, _))
.WillByDefault(Invoke(this, &MockDataLoaderManager::bindToDataLoaderOk));
}
void bindToDataLoaderFails() {
ON_CALL(*this, bindToDataLoader(_, _, _, _))
ON_CALL(*this, bindToDataLoader(_, _, _, _, _))
.WillByDefault(Return(
(binder::Status::fromExceptionCode(1, String8("failed to prepare")))));
}
@@ -234,6 +235,7 @@ public:
.WillByDefault(Invoke(this, &MockDataLoaderManager::unbindFromDataLoaderOk));
}
binder::Status bindToDataLoaderOk(int32_t mountId, const DataLoaderParamsParcel& params,
int bindDelayMs,
const sp<IDataLoaderStatusListener>& listener,
bool* _aidl_return) {
mId = mountId;
@@ -245,6 +247,40 @@ public:
}
return binder::Status::ok();
}
binder::Status bindToDataLoaderOkWith10sDelay(int32_t mountId,
const DataLoaderParamsParcel& params,
int bindDelayMs,
const sp<IDataLoaderStatusListener>& listener,
bool* _aidl_return) {
CHECK(1000 * 9 <= bindDelayMs && bindDelayMs <= 1000 * 11) << bindDelayMs;
return bindToDataLoaderOk(mountId, params, bindDelayMs, listener, _aidl_return);
}
binder::Status bindToDataLoaderOkWith100sDelay(int32_t mountId,
const DataLoaderParamsParcel& params,
int bindDelayMs,
const sp<IDataLoaderStatusListener>& listener,
bool* _aidl_return) {
CHECK(1000 * 9 * 9 < bindDelayMs && bindDelayMs < 1000 * 11 * 11) << bindDelayMs;
return bindToDataLoaderOk(mountId, params, bindDelayMs, listener, _aidl_return);
}
binder::Status bindToDataLoaderOkWith1000sDelay(int32_t mountId,
const DataLoaderParamsParcel& params,
int bindDelayMs,
const sp<IDataLoaderStatusListener>& listener,
bool* _aidl_return) {
CHECK(1000 * 9 * 9 * 9 < bindDelayMs && bindDelayMs < 1000 * 11 * 11 * 11) << bindDelayMs;
return bindToDataLoaderOk(mountId, params, bindDelayMs, listener, _aidl_return);
}
binder::Status bindToDataLoaderOkWith10000sDelay(int32_t mountId,
const DataLoaderParamsParcel& params,
int bindDelayMs,
const sp<IDataLoaderStatusListener>& listener,
bool* _aidl_return) {
CHECK(1000 * 9 * 9 * 9 * 9 < bindDelayMs && bindDelayMs < 1000 * 11 * 11 * 11 * 11)
<< bindDelayMs;
return bindToDataLoaderOk(mountId, params, bindDelayMs, listener, _aidl_return);
}
binder::Status getDataLoaderOk(int32_t mountId, sp<IDataLoader>* _aidl_return) {
*_aidl_return = mDataLoader;
return binder::Status::ok();
@@ -261,6 +297,9 @@ public:
void setDataLoaderStatusUnavailable() {
mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE);
}
void setDataLoaderStatusUnrecoverable() {
mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_UNRECOVERABLE);
}
binder::Status unbindFromDataLoaderOk(int32_t id) {
if (mDataLoader) {
if (auto status = mDataLoader->destroy(id); !status.isOk()) {
@@ -676,7 +715,7 @@ protected:
TEST_F(IncrementalServiceTest, testCreateStorageMountIncFsFails) {
mVold->mountIncFsFails();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(0);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(0);
TemporaryDir tempDir;
int storageId =
mIncrementalService->createStorage(tempDir.path, mDataLoaderParcel,
@@ -686,7 +725,7 @@ TEST_F(IncrementalServiceTest, testCreateStorageMountIncFsFails) {
TEST_F(IncrementalServiceTest, testCreateStorageMountIncFsInvalidControlParcel) {
mVold->mountIncFsInvalidControlParcel();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(0);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(0);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0);
TemporaryDir tempDir;
int storageId =
@@ -698,7 +737,7 @@ TEST_F(IncrementalServiceTest, testCreateStorageMountIncFsInvalidControlParcel)
TEST_F(IncrementalServiceTest, testCreateStorageMakeFileFails) {
mVold->mountIncFsSuccess();
mIncFs->makeFileFails();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(0);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(0);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0);
EXPECT_CALL(*mVold, unmountIncFs(_));
TemporaryDir tempDir;
@@ -712,7 +751,7 @@ TEST_F(IncrementalServiceTest, testCreateStorageBindMountFails) {
mVold->mountIncFsSuccess();
mIncFs->makeFileSuccess();
mVold->bindMountFails();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(0);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(0);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0);
EXPECT_CALL(*mVold, unmountIncFs(_));
TemporaryDir tempDir;
@@ -727,7 +766,7 @@ TEST_F(IncrementalServiceTest, testCreateStoragePrepareDataLoaderFails) {
mIncFs->makeFileSuccess();
mVold->bindMountSuccess();
mDataLoaderManager->bindToDataLoaderFails();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0);
EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(0);
EXPECT_CALL(*mDataLoader, start(_)).Times(0);
@@ -755,11 +794,11 @@ TEST_F(IncrementalServiceTest, testDeleteStorageSuccess) {
mIncrementalService->deleteStorage(storageId);
}
TEST_F(IncrementalServiceTest, testDataLoaderDestroyed) {
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(2);
TEST_F(IncrementalServiceTest, testDataLoaderDestroyedAndDelayed) {
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(6);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(2);
EXPECT_CALL(*mDataLoader, start(_)).Times(2);
EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(6);
EXPECT_CALL(*mDataLoader, start(_)).Times(6);
EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
TemporaryDir tempDir;
@@ -768,13 +807,38 @@ TEST_F(IncrementalServiceTest, testDataLoaderDestroyed) {
IncrementalService::CreateOptions::CreateNew);
ASSERT_GE(storageId, 0);
mIncrementalService->startLoading(storageId, std::move(mDataLoaderParcel), {}, {}, {}, {});
// Simulated crash/other connection breakage.
ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
.WillByDefault(Invoke(mDataLoaderManager,
&MockDataLoaderManager::bindToDataLoaderOkWith10sDelay));
mDataLoaderManager->setDataLoaderStatusDestroyed();
ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
.WillByDefault(Invoke(mDataLoaderManager,
&MockDataLoaderManager::bindToDataLoaderOkWith100sDelay));
mDataLoaderManager->setDataLoaderStatusDestroyed();
ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
.WillByDefault(Invoke(mDataLoaderManager,
&MockDataLoaderManager::bindToDataLoaderOkWith1000sDelay));
mDataLoaderManager->setDataLoaderStatusDestroyed();
ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
.WillByDefault(Invoke(mDataLoaderManager,
&MockDataLoaderManager::bindToDataLoaderOkWith10000sDelay));
mDataLoaderManager->setDataLoaderStatusDestroyed();
ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
.WillByDefault(Invoke(mDataLoaderManager,
&MockDataLoaderManager::bindToDataLoaderOkWith10000sDelay));
mDataLoaderManager->setDataLoaderStatusDestroyed();
}
TEST_F(IncrementalServiceTest, testStartDataLoaderCreate) {
mDataLoader->initializeCreateOkNoStatus();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoader, start(_)).Times(1);
@@ -793,7 +857,7 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderCreate) {
TEST_F(IncrementalServiceTest, testStartDataLoaderPendingStart) {
mDataLoader->initializeCreateOkNoStatus();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoader, start(_)).Times(1);
@@ -811,7 +875,7 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderPendingStart) {
TEST_F(IncrementalServiceTest, testStartDataLoaderCreateUnavailable) {
mDataLoader->initializeCreateOkNoStatus();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoader, start(_)).Times(0);
@@ -827,12 +891,30 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderCreateUnavailable) {
mDataLoaderManager->setDataLoaderStatusUnavailable();
}
TEST_F(IncrementalServiceTest, testStartDataLoaderCreateUnrecoverable) {
mDataLoader->initializeCreateOkNoStatus();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoader, start(_)).Times(0);
EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
TemporaryDir tempDir;
int storageId =
mIncrementalService->createStorage(tempDir.path, mDataLoaderParcel,
IncrementalService::CreateOptions::CreateNew);
ASSERT_GE(storageId, 0);
ASSERT_TRUE(mIncrementalService->startLoading(storageId, std::move(mDataLoaderParcel), {}, {},
{}, {}));
mDataLoaderManager->setDataLoaderStatusUnrecoverable();
}
TEST_F(IncrementalServiceTest, testStartDataLoaderRecreateOnPendingReads) {
mIncFs->waitForPendingReadsSuccess();
mIncFs->openMountSuccess();
mDataLoader->initializeCreateOkNoStatus();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(2);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(2);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(2);
EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(2);
EXPECT_CALL(*mDataLoader, start(_)).Times(0);
@@ -856,7 +938,7 @@ TEST_F(IncrementalServiceTest, testStartDataLoaderRecreateOnPendingReads) {
TEST_F(IncrementalServiceTest, testStartDataLoaderUnhealthyStorage) {
mIncFs->openMountSuccess();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoader, start(_)).Times(1);
@@ -1406,7 +1488,7 @@ static ErrorCode checkPerUidTimeoutsEmpty(
}
TEST_F(IncrementalServiceTest, testPerUidTimeoutsTooShort) {
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(1);
EXPECT_CALL(*mDataLoader, start(_)).Times(1);