[incfs] Make native library extraction async
IncrementalService can create the library files beforehand, but
delay filling in their data. As it takes quite a while in
general (over a second in cases when the phone is busy), it's
better to run the unzipping and filling in a separate thread
and only make sure it finishes before the whole installation
process is complete.
This speeds up the megacity.apk installation by ~250-300ms,
1000-1100ms -> 750-800ms
Bug: 153513507
Test: adb install megacity.apk
Change-Id: Ia44f7e45b9e0abaebdfb6fe5352f9dcf29ab4ece
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index 27d40f1..4fdce4b 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -23,16 +23,19 @@
#include <utils/String16.h>
#include <utils/StrongPointer.h>
#include <utils/Vector.h>
+#include <ziparchive/zip_archive.h>
#include <atomic>
#include <chrono>
-#include <future>
+#include <condition_variable>
+#include <functional>
#include <limits>
#include <map>
#include <mutex>
#include <span>
#include <string>
#include <string_view>
+#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>
@@ -132,12 +135,15 @@
std::vector<std::string> listFiles(StorageId storage) const;
bool startLoading(StorageId storage) const;
+
bool configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
std::string_view libDirRelativePath, std::string_view abi);
+ bool waitForNativeBinariesExtraction(StorageId storage);
class AppOpsListener : public android::BnAppOpsCallback {
public:
- AppOpsListener(IncrementalService& incrementalService, std::string packageName) : incrementalService(incrementalService), packageName(std::move(packageName)) {}
+ AppOpsListener(IncrementalService& incrementalService, std::string packageName)
+ : incrementalService(incrementalService), packageName(std::move(packageName)) {}
void opChanged(int32_t op, const String16& packageName) final;
private:
@@ -277,7 +283,12 @@
bool unregisterAppOpsCallback(const std::string& packageName);
void onAppOpChanged(const std::string& packageName);
- // Member variables
+ void runJobProcessing();
+ void extractZipFile(const IfsMountPtr& ifs, ZipArchiveHandle zipFile, ZipEntry& entry,
+ const incfs::FileId& libFileId, std::string_view targetLibPath,
+ Clock::time_point scheduledTs);
+
+private:
std::unique_ptr<VoldServiceWrapper> const mVold;
std::unique_ptr<DataLoaderManagerWrapper> const mDataLoaderManager;
std::unique_ptr<IncFsWrapper> const mIncFs;
@@ -294,6 +305,14 @@
std::atomic_bool mSystemReady = false;
StorageId mNextId = 0;
+
+ using Job = std::function<void()>;
+ std::unordered_map<StorageId, std::vector<Job>> mJobQueue;
+ StorageId mPendingJobsStorage = kInvalidStorageId;
+ std::condition_variable mJobCondition;
+ std::mutex mJobMutex;
+ std::thread mJobProcessor;
+ bool mRunning = true;
};
} // namespace android::incremental