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

Commit 36ba03a2 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Gerrit Code Review
Browse files

Merge "Handle devices without quota, speed up lookup."

parents 950e3f56 66b1a12e
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();
}