Lifecycle: detecting blocked and unhealthy, part 2.
Part 2: continuous health checking, blocked and unhealthy states.
Bug: 153874006
Test: atest PackageManagerShellCommandTest PackageManagerShellCommandIncrementalTest IncrementalServiceTest
Change-Id: Ifdbff7dfa24b3bd9b96c534a40bb1226082749ca
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index 05f62b9..57e4669 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -35,6 +35,7 @@
#include <limits>
#include <map>
#include <mutex>
+#include <set>
#include <span>
#include <string>
#include <string_view>
@@ -186,17 +187,12 @@
void onDump(int fd);
- MountId id() const { return mId; }
+ MountId id() const { return mId.load(std::memory_order_relaxed); }
const content::pm::DataLoaderParamsParcel& params() const { return mParams; }
private:
binder::Status onStatusChanged(MountId mount, int newStatus) final;
- void registerForPendingReads();
- void unregisterFromPendingReads();
- int onPendingReads();
-
- bool isValid() const { return mId != kInvalidStorageId; }
sp<content::pm::IDataLoader> getDataLoader();
bool bind();
@@ -208,21 +204,27 @@
void setTargetStatusLocked(int status);
bool fsmStep();
+ bool fsmStep(int currentStatus, int targetStatus);
- // Watching for pending reads.
- void healthStatusOk();
- // Pending reads detected, waiting for Xsecs to confirm blocked state.
- void healthStatusReadsPending();
- // There are reads pending for X+secs, waiting for additional Ysecs to confirm unhealthy
- // state.
- void healthStatusBlocked();
- // There are reads pending for X+Ysecs, marking storage as unhealthy.
- void healthStatusUnhealthy();
+ void onHealthStatus(StorageHealthListener healthListener, int healthStatus);
+ void updateHealthStatus(bool baseline = false);
+
+ bool isValid() const { return id() != kInvalidStorageId; }
+
+ bool isHealthParamsValid() const;
+
+ const incfs::UniqueControl& initializeHealthControl();
+ void resetHealthControl();
+
+ BootClockTsUs getOldestPendingReadTs();
+
+ void registerForPendingReads();
+ void unregisterFromPendingReads();
IncrementalService& mService;
std::mutex mMutex;
- MountId mId = kInvalidStorageId;
+ std::atomic<MountId> mId = kInvalidStorageId;
content::pm::DataLoaderParamsParcel mParams;
content::pm::FileSystemControlParcel mControl;
DataLoaderStatusListener mStatusListener;
@@ -235,6 +237,11 @@
std::string mHealthPath;
incfs::UniqueControl mHealthControl;
+ struct {
+ TimePoint userTs;
+ BootClockTsUs kernelTsUs;
+ } mHealthBase = {TimePoint::max(), kMaxBootClockTsUs};
+ StorageHealthCheckParams mHealthCheckParams;
};
using DataLoaderStubPtr = sp<DataLoaderStub>;
@@ -331,6 +338,8 @@
bool unregisterAppOpsCallback(const std::string& packageName);
void onAppOpChanged(const std::string& packageName);
+ using Job = std::function<void()>;
+
void runJobProcessing();
void extractZipFile(const IfsMountPtr& ifs, ZipArchiveHandle zipFile, ZipEntry& entry,
const incfs::FileId& libFileId, std::string_view targetLibPath,
@@ -338,6 +347,10 @@
void runCmdLooper();
+ void addTimedJob(MountId id, TimePoint when, Job what);
+ void removeTimedJobs(MountId id);
+ void runTimers();
+
private:
const std::unique_ptr<VoldServiceWrapper> mVold;
const std::unique_ptr<DataLoaderManagerWrapper> mDataLoaderManager;
@@ -360,7 +373,6 @@
std::atomic_bool mRunning{true};
- using Job = std::function<void()>;
std::unordered_map<MountId, std::vector<Job>> mJobQueue;
MountId mPendingJobsMount = kInvalidStorageId;
std::condition_variable mJobCondition;
@@ -368,6 +380,19 @@
std::thread mJobProcessor;
std::thread mCmdLooperThread;
+
+ struct TimedJob {
+ MountId id;
+ TimePoint when;
+ Job what;
+ friend bool operator<(const TimedJob& lhs, const TimedJob& rhs) {
+ return lhs.when < rhs.when;
+ }
+ };
+ std::set<TimedJob> mTimedJobs;
+ std::condition_variable mTimerCondition;
+ std::mutex mTimerMutex;
+ std::thread mTimerThread;
};
} // namespace android::incremental