Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf8bc228 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by android-build-merger
Browse files

Merge "Handle devices without quota, speed up lookup." am: 36ba03a2 am: 411ae16a

am: 9eeb77f0

Change-Id: I6f6004769a576003a5fb27bcd78470badf43d68a
parents d06bc6a9 9eeb77f0
Loading
Loading
Loading
Loading
+65 −35
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@
#endif

using android::base::StringPrintf;
using std::endl;

namespace android {
namespace installd {
@@ -188,15 +189,22 @@ status_t InstalldNativeService::start() {
}

status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */) {
    auto out = std::fstream(StringPrintf("/proc/self/fd/%d", fd));
    const binder::Status dump_permission = checkPermission(kDump);
    if (!dump_permission.isOk()) {
        const String8 msg(dump_permission.toString8());
        write(fd, msg.string(), msg.size());
        out << dump_permission.toString8() << endl;
        return PERMISSION_DENIED;
    }
    std::lock_guard<std::recursive_mutex> lock(mLock);

    out << "installd is happy!" << endl << endl;
    out << "Devices with quota support:" << endl;
    for (const auto& n : mQuotaDevices) {
        out << "    " << n.first << " = " << n.second << endl;
    }
    out << endl;
    out.flush();

    std::string msg = "installd is happy\n";
    write(fd, msg.c_str(), strlen(msg.c_str()));
    return NO_ERROR;
}

@@ -888,28 +896,6 @@ static std::string toString(std::vector<int64_t> values) {
}
#endif

static std::string findDeviceForUuid(const std::unique_ptr<std::string>& uuid) {
    auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
    std::ifstream in("/proc/mounts");
    if (!in.is_open()) {
        PLOG(ERROR) << "Failed to read mounts";
        return "";
    }
    std::string source;
    std::string target;
    while (!in.eof()) {
        std::getline(in, source, ' ');
        std::getline(in, target, ' ');
        if (target == path) {
            return source;
        }
        // Skip to next line
        std::getline(in, source);
    }
    PLOG(ERROR) << "Failed to resolve block device for " << path;
    return "";
}

static void collectQuotaStats(const std::string& device, int32_t userId,
        int32_t appId, struct stats* stats, struct stats* extStats ATTRIBUTE_UNUSED) {
    if (device.empty()) return;
@@ -964,11 +950,6 @@ static void collectQuotaStats(const std::string& device, int32_t userId,
#endif
}

static void collectQuotaStats(const std::unique_ptr<std::string>& uuid, int32_t userId,
        int32_t appId, struct stats* stats, struct stats* extStats) {
    collectQuotaStats(findDeviceForUuid(uuid), userId, appId, stats, extStats);
}

static void collectManualStats(const std::string& path, struct stats* stats) {
    DIR *d;
    int dfd;
@@ -1090,6 +1071,11 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::stri

    const char* uuid_ = uuid ? uuid->c_str() : nullptr;

    auto device = findQuotaDeviceForUuid(uuid);
    if (device.empty()) {
        flags &= ~FLAG_USE_QUOTA;
    }

    for (auto packageName : packageNames) {
        auto obbCodePath = create_data_media_obb_path(uuid_, packageName.c_str());
        calculate_tree_size(obbCodePath, &extStats.codeSize);
@@ -1101,7 +1087,7 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::stri
                    multiuser_get_shared_gid(userId, appId));
        }

        collectQuotaStats(uuid, userId, appId, &stats, &extStats);
        collectQuotaStats(device, userId, appId, &stats, &extStats);

    } else {
        for (auto codePath : codePaths) {
@@ -1180,6 +1166,11 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str
    auto obbPath = create_data_path(uuid_) + "/media/obb";
    calculate_tree_size(obbPath, &extStats.codeSize);

    auto device = findQuotaDeviceForUuid(uuid);
    if (device.empty()) {
        flags &= ~FLAG_USE_QUOTA;
    }

    if (flags & FLAG_USE_QUOTA) {
        calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true);

@@ -1205,7 +1196,6 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str
        calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize,
                -1, -1, true);

        auto device = findDeviceForUuid(uuid);
        for (auto appId : appIds) {
            if (appId >= AID_APP_START) {
                collectQuotaStats(device, userId, appId, &stats, &extStats);
@@ -1273,11 +1263,14 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std:
    int64_t videoSize = 0;
    int64_t imageSize = 0;

    auto device = findQuotaDeviceForUuid(uuid);
    if (device.empty()) {
        flags &= ~FLAG_USE_QUOTA;
    }

    if (flags & FLAG_USE_QUOTA) {
        struct dqblk dq;

        auto device = findDeviceForUuid(uuid);

        uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
        if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
                reinterpret_cast<char*>(&dq)) != 0) {
@@ -1776,5 +1769,42 @@ binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath,
    return res ? ok() : error();
}

binder::Status InstalldNativeService::invalidateMounts() {
    ENFORCE_UID(AID_SYSTEM);
    std::lock_guard<std::recursive_mutex> lock(mLock);

    mQuotaDevices.clear();

    std::ifstream in("/proc/mounts");
    if (!in.is_open()) {
        return error("Failed to read mounts");
    }

    std::string source;
    std::string target;
    std::string ignored;
    struct dqblk dq;
    while (!in.eof()) {
        std::getline(in, source, ' ');
        std::getline(in, target, ' ');
        std::getline(in, ignored);

        if (source.compare(0, 11, "/dev/block/") == 0) {
            if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
                    reinterpret_cast<char*>(&dq)) == 0) {
                LOG(DEBUG) << "Found " << source << " with quota";
                mQuotaDevices[target] = source;
            }
        }
    }
    return ok();
}

std::string InstalldNativeService::findQuotaDeviceForUuid(
        const std::unique_ptr<std::string>& uuid) {
    auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
    return mQuotaDevices[path];
}

}  // namespace installd
}  // namespace android
+8 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <unistd.h>

#include <vector>
#include <unordered_map>

#include <binder/BinderService.h>
#include <cutils/multiuser.h>
@@ -100,8 +101,15 @@ public:
    binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet,
            const std::string& outputPath);

    binder::Status invalidateMounts();

private:
    std::recursive_mutex mLock;

    /* Map from mount point to underlying device node */
    std::unordered_map<std::string, std::string> mQuotaDevices;

    std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid);
};

}  // namespace installd
+2 −0
Original line number Diff line number Diff line
@@ -68,4 +68,6 @@ interface IInstalld {
            @utf8InCpp String outputPath);
    void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
            @utf8InCpp String outputPath);

    void invalidateMounts();
}