Snap for 8378100 from 5891d7e486e3f2ba3fb74398cfce7ed082d5a85f to tm-release

Change-Id: I39275e0227c27ee757720a3018c83e53d6dce50b
diff --git a/IdleMaint.cpp b/IdleMaint.cpp
index 2fc0d4b..2bfe3d9 100644
--- a/IdleMaint.cpp
+++ b/IdleMaint.cpp
@@ -87,7 +87,7 @@
 static const int DEVGC_TIMEOUT_SEC = 120;
 static const int KBYTES_IN_SEGMENT = 2048;
 static const int MIN_GC_URGENT_SLEEP_TIME = 500;
-static const int ONE_HOUR_IN_MS = 3600000;
+static const int ONE_MINUTE_IN_MS = 60000;
 static const int GC_NORMAL_MODE = 0;
 static const int GC_URGENT_MID_MODE = 3;
 
@@ -531,9 +531,10 @@
 }
 
 void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate,
-                     float reclaimWeight) {
+                     float reclaimWeight, int32_t gcPeriod) {
     std::list<std::string> paths;
     bool needGC = true;
+    int32_t sleepTime;
 
     addFromFstab(&paths, PathTypes::kBlkDevice, true);
     if (paths.empty()) {
@@ -546,7 +547,9 @@
     std::string dirtySegmentsPath = f2fsSysfsPath + "/dirty_segments";
     std::string gcSleepTimePath = f2fsSysfsPath + "/gc_urgent_sleep_time";
     std::string gcUrgentModePath = f2fsSysfsPath + "/gc_urgent";
-    std::string freeSegmentsStr, dirtySegmentsStr;
+    std::string ovpSegmentsPath = f2fsSysfsPath + "/ovp_segments";
+    std::string reservedBlocksPath = f2fsSysfsPath + "/reserved_blocks";
+    std::string freeSegmentsStr, dirtySegmentsStr, ovpSegmentsStr, reservedBlocksStr;
 
     if (!ReadFileToString(freeSegmentsPath, &freeSegmentsStr)) {
         PLOG(WARNING) << "Reading failed in " << freeSegmentsPath;
@@ -558,9 +561,21 @@
         return;
     }
 
+    if (!ReadFileToString(ovpSegmentsPath, &ovpSegmentsStr)) {
+            PLOG(WARNING) << "Reading failed in " << ovpSegmentsPath;
+            return;
+        }
+
+    if (!ReadFileToString(reservedBlocksPath, &reservedBlocksStr)) {
+            PLOG(WARNING) << "Reading failed in " << reservedBlocksPath;
+            return;
+        }
+
     int32_t freeSegments = std::stoi(freeSegmentsStr);
     int32_t dirtySegments = std::stoi(dirtySegmentsStr);
+    int32_t reservedBlocks = std::stoi(ovpSegmentsStr) + std::stoi(reservedBlocksStr);
 
+    freeSegments = freeSegments > reservedBlocks ? freeSegments - reservedBlocks : 0;
     neededSegments *= reclaimWeight;
     if (freeSegments >= neededSegments) {
         LOG(INFO) << "Enough free segments: " << freeSegments
@@ -570,6 +585,18 @@
         LOG(INFO) << "The sum of free segments: " << freeSegments
                    << ", dirty segments: " << dirtySegments << " is under " << minSegmentThreshold;
         needGC = false;
+    } else {
+        neededSegments -= freeSegments;
+        neededSegments = std::min(neededSegments, (int32_t)(dirtySegments * dirtyReclaimRate));
+        if (neededSegments == 0) {
+            LOG(INFO) << "Low dirty segments: " << dirtySegments;
+            needGC = false;
+        } else {
+            sleepTime = gcPeriod * ONE_MINUTE_IN_MS / neededSegments;
+            if (sleepTime < MIN_GC_URGENT_SLEEP_TIME) {
+                sleepTime = MIN_GC_URGENT_SLEEP_TIME;
+            }
+        }
     }
 
     if (!needGC) {
@@ -579,18 +606,6 @@
         return;
     }
 
-    int32_t sleepTime;
-
-    neededSegments -= freeSegments;
-    neededSegments = std::min(neededSegments, (int32_t)(dirtySegments * dirtyReclaimRate));
-    if (neededSegments == 0) {
-        sleepTime = MIN_GC_URGENT_SLEEP_TIME;
-    } else {
-        sleepTime = ONE_HOUR_IN_MS / neededSegments;
-        if (sleepTime < MIN_GC_URGENT_SLEEP_TIME) {
-            sleepTime = MIN_GC_URGENT_SLEEP_TIME;
-        }
-    }
     if (!WriteStringToFile(std::to_string(sleepTime), gcSleepTimePath)) {
         PLOG(WARNING) << "Writing failed in " << gcSleepTimePath;
         return;
diff --git a/IdleMaint.h b/IdleMaint.h
index ae70b63..9a2af4a 100644
--- a/IdleMaint.h
+++ b/IdleMaint.h
@@ -27,7 +27,7 @@
 int AbortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener);
 int32_t GetStorageLifeTime();
 void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate,
-                     float reclaimWeight);
+                     float reclaimWeight, int32_t gcPeriod);
 void RefreshLatestWrite();
 int32_t GetWriteAmount();
 
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index ce6e6fc..8ba3aaf 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -494,11 +494,12 @@
 
 binder::Status VoldNativeService::setGCUrgentPace(int32_t neededSegments,
                                                   int32_t minSegmentThreshold,
-                                                  float dirtyReclaimRate, float reclaimWeight) {
+                                                  float dirtyReclaimRate, float reclaimWeight,
+                                                  int32_t gcPeriod) {
     ENFORCE_SYSTEM_OR_ROOT;
     ACQUIRE_LOCK;
 
-    SetGCUrgentPace(neededSegments, minSegmentThreshold, dirtyReclaimRate, reclaimWeight);
+    SetGCUrgentPace(neededSegments, minSegmentThreshold, dirtyReclaimRate, reclaimWeight, gcPeriod);
     return Ok();
 }
 
diff --git a/VoldNativeService.h b/VoldNativeService.h
index cb42973..423e8f9 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -90,7 +90,7 @@
     binder::Status abortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener);
     binder::Status getStorageLifeTime(int32_t* _aidl_return);
     binder::Status setGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold,
-                                   float dirtyReclaimRate, float reclaimWeight);
+                                   float dirtyReclaimRate, float reclaimWeight, int32_t gcPeriod);
     binder::Status refreshLatestWrite();
     binder::Status getWriteAmount(int32_t* _aidl_return);
 
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 05da7b0..d77c7da 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -68,7 +68,8 @@
     void abortIdleMaint(IVoldTaskListener listener);
     int getStorageLifeTime();
     void setGCUrgentPace(int neededSegments, int minSegmentThreshold,
-                         float dirtyReclaimRate, float reclaimWeight);
+                         float dirtyReclaimRate, float reclaimWeight,
+                         int gcPeriod);
     void refreshLatestWrite();
     int getWriteAmount();