First pass at updated cache clearing logic.

The old clearing algorithm is very naive and it sorts all cached files
globally by modified time.  This sadly lets apps gamify the system by
setting their modified times far in the future, and it's very
expensive because it requires a global filesystem traversal to free
up even the smallest amount of data.

Instead, this CL introduces a much more fair cache clearing algorithm
that deletes files from specific UIDs based on how much cache space
that UID is using proportional to the space allocated to them.  This
new design has several nice properties:

-- It uses the recently added quotactl() feature to rapidly target
the apps that are using the most space.
-- We only need to traverse the filesystem for UIDs that actively
enter the crosshairs of the clearing algorithm.
-- Disciplined apps who stay under their allocated quota will be
the last to have their cached data cleared.
-- This design can be easily adapted to support additional features
such as atomic purging and tombstones.

In summary, the new algorithm is extremely efficient when freeing up
the typical small-to-medium amounts of disk space, and is only
moderately less efficient than the old algorithm when forced to clear
all cached data.

Test: builds, boots, clearing strategy looks sane
Bug: 33965858
Change-Id: I66f95089cb33f1add3f31fcf1082ab2469870fda
diff --git a/cmds/installd/CacheTracker.h b/cmds/installd/CacheTracker.h
new file mode 100644
index 0000000..91692d7
--- /dev/null
+++ b/cmds/installd/CacheTracker.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_INSTALLD_CACHE_TRACKER_H
+#define ANDROID_INSTALLD_CACHE_TRACKER_H
+
+#include <memory>
+#include <string>
+#include <queue>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <android-base/macros.h>
+#include <cutils/multiuser.h>
+
+#include "CacheItem.h"
+
+namespace android {
+namespace installd {
+
+/**
+ * Cache tracker for a single UID. Each tracker is used in two modes: first
+ * for loading lightweight "stats", and then by loading detailed "items"
+ * which can then be purged to free up space.
+ */
+class CacheTracker {
+public:
+    CacheTracker(userid_t userId, appid_t appId, const std::string& quotaDevice);
+    ~CacheTracker();
+
+    std::string toString();
+
+    void addDataPath(const std::string& dataPath);
+
+    void loadStats();
+    void loadItems();
+
+    void ensureItems();
+
+    int getCacheRatio();
+
+    int64_t cacheUsed;
+    int64_t cacheQuota;
+
+    std::vector<std::shared_ptr<CacheItem>> items;
+
+private:
+    userid_t mUserId;
+    appid_t mAppId;
+    std::string mQuotaDevice;
+    bool mItemsLoaded;
+
+    std::vector<std::string> mDataPaths;
+
+    void loadItemsFrom(const std::string& path);
+
+    DISALLOW_COPY_AND_ASSIGN(CacheTracker);
+};
+
+}  // namespace installd
+}  // namespace android
+
+#endif  // ANDROID_INSTALLD_CACHE_TRACKER_H