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

Commit e6580028 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 13874821 from 370a47ec to 25Q4-release

Change-Id: I10e0933edee1e1ef786a2366b3338d3681306468
parents 46baccf7 370a47ec
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -17,11 +17,24 @@
package com.android.media.permission;

/**
 * Entity representing the package names associated with a particular uid/app-id
 * Entity representing the packages associated with a particular app-id. Multiple packages can be
 * assigned a specific app-id.
 * {@hide}
 */
@JavaDerive(equals = true, toString = true)
parcelable UidPackageState {
    /**
     * State we retain for an individual package
     * {@hide}
     */
    @JavaDerive(equals = true, toString = true)
    parcelable PackageState {
        @utf8InCpp String packageName;
        int targetSdk;
        boolean isPlaybackCaptureAllowed;
    }
    // Technically, an app-id for real packages, since the package is associated with an appId,
    // which is associated with a uid per user.
    int uid;
    @utf8InCpp List<String> packageNames;
    List<PackageState> packageStates;
}
+69 −9
Original line number Diff line number Diff line
@@ -61,8 +61,9 @@ Status NativePermissionController::populatePackagesForUids(
    package_map_.clear();
    std::transform(initialPackageStates.begin(), initialPackageStates.end(),
                   std::inserter(package_map_, package_map_.end()),
                   [](const auto& x) -> std::pair<uid_t, std::vector<std::string>> {
                       return {x.uid, x.packageNames};
                   [](const auto& x)
                           -> std::pair<uid_t, std::vector<UidPackageState::PackageState>> {
                       return {x.uid, x.packageStates};
                   });
    std::erase_if(package_map_, [](const auto& x) { return x.second.empty(); });
    return Status::ok();
@@ -71,18 +72,18 @@ Status NativePermissionController::populatePackagesForUids(
Status NativePermissionController::updatePackagesForUid(const UidPackageState& newPackageState) {
    std::lock_guard l{m_};
    ALOGD("%s, %s", __func__, newPackageState.toString().c_str());
    package_map_.insert_or_assign(newPackageState.uid, newPackageState.packageNames);
    package_map_.insert_or_assign(newPackageState.uid, newPackageState.packageStates);
    const auto& cursor = package_map_.find(newPackageState.uid);

    if (newPackageState.packageNames.empty()) {
    if (newPackageState.packageStates.empty()) {
        if (cursor != package_map_.end()) {
            package_map_.erase(cursor);
        }
    } else {
        if (cursor != package_map_.end()) {
            cursor->second = newPackageState.packageNames;
            cursor->second = newPackageState.packageStates;
        } else {
            package_map_.insert({newPackageState.uid, newPackageState.packageNames});
            package_map_.insert({newPackageState.uid, newPackageState.packageStates});
        }
    }
    return Status::ok();
@@ -120,7 +121,11 @@ BinderResult<std::vector<std::string>> NativePermissionController::getPackagesFo
    }
    const auto cursor = package_map_.find(uid);
    if (cursor != package_map_.end()) {
        return cursor->second;
        std::vector<std::string> package_names;
        std::transform(cursor->second.begin(), cursor->second.end(),
                       std::back_inserter(package_names),
                       [](const auto& x) { return x.packageName; });
        return package_names;
    } else {
        return unexpectedExceptionCode(
                Status::EX_ILLEGAL_ARGUMENT,
@@ -150,8 +155,8 @@ BinderResult<bool> NativePermissionController::validateUidPackagePair(
                                        std::to_string(uid) + " for package " + packageName)
                                               .c_str());
    }
    return (std::find(cursor->second.begin(), cursor->second.end(), packageName) !=
            cursor->second.end());
    return std::any_of(cursor->second.begin(), cursor->second.end(),
                       [&](const auto& x) { return x.packageName == packageName; });
}

BinderResult<bool> NativePermissionController::checkPermission(PermissionEnum perm,
@@ -172,6 +177,61 @@ BinderResult<bool> NativePermissionController::checkPermission(PermissionEnum pe
    }
}

BinderResult<int32_t> NativePermissionController::getHighestTargetSdkForUid(uid_t uid) const {
    uid = uid % AID_USER_OFFSET;
    std::lock_guard l{m_};
    if (!is_package_populated_) {
        return unexpectedExceptionCode(
                Status::EX_ILLEGAL_STATE,
                "NPC::getHighestTargetSdkForUid: controller never populated by system_server");
    }
    const auto cursor = package_map_.find(uid);
    if (cursor != package_map_.end()) {
        if (cursor->second.empty()) {
            return unexpectedExceptionCode(
                    Status::EX_ILLEGAL_STATE,
                    ("NPC::getHighestTargetSdkForUid: empty package list for uid: " +
                     std::to_string(uid))
                            .c_str());
        }
        const auto max_it = std::max_element(
                cursor->second.begin(), cursor->second.end(),
                [](const auto& a, const auto& b) { return a.targetSdk < b.targetSdk; });
        return max_it->targetSdk;
    } else {
        return unexpectedExceptionCode(
                Status::EX_ILLEGAL_ARGUMENT,
                ("NPC::getHighestTargetSdkForUid: uid not found: " + std::to_string(uid)).c_str());
    }
}

BinderResult<bool> NativePermissionController::doesUidPermitPlaybackCapture(uid_t uid) const {
    uid = uid % AID_USER_OFFSET;
    std::lock_guard l{m_};
    if (!is_package_populated_) {
        return unexpectedExceptionCode(
                Status::EX_ILLEGAL_STATE,
                "NPC::doesUidPermitPlaybackCapture: controller never populated by system_server");
    }
    const auto cursor = package_map_.find(uid);
    if (cursor != package_map_.end()) {
        if (cursor->second.empty()) {
            return unexpectedExceptionCode(
                    Status::EX_ILLEGAL_STATE,
                    ("NPC::doesUidPermitPlaybackCapture: empty package list for uid: " +
                     std::to_string(uid))
                            .c_str());
        }
        return std::all_of(cursor->second.begin(), cursor->second.end(),
                           [](const auto& x) { return x.isPlaybackCaptureAllowed; });
    } else {
        return unexpectedExceptionCode(
                Status::EX_ILLEGAL_ARGUMENT,
                ("NPC::doesUidPermitPlaybackCapture: uid not found: " + std::to_string(uid))
                        .c_str());
    }
}

std::string NativePermissionController::dumpString() const {
    std::lock_guard l{m_};
    std::string res{"Permission map: \n"};
+15 −4
Original line number Diff line number Diff line
@@ -26,8 +26,17 @@

namespace com::android::media::permission {

// Interface for permission and package information required by audioserver, which is pushed down
// from system server to avoid cross deadlocks.
// With the exception of checkPermission, uids refer to app-ids, since package info is the same
// across users.
class IPermissionProvider {
  public:
    // True iff the uid holds the permission (user aware).
    // Fails with NO_INIT if cache hasn't been populated.
    virtual ::android::error::BinderResult<bool> checkPermission(PermissionEnum permission,
                                                                 uid_t uid) const = 0;

    // Get all package names which run under a certain app-id. Returns non-empty.
    // Not user specific, since packages are across users. Special app-ids (system,
    // shell, etc.) are handled.  Fails if the provider does not know about the
@@ -41,10 +50,12 @@ class IPermissionProvider {
    virtual ::android::error::BinderResult<bool> validateUidPackagePair(
            uid_t uid, const std::string& packageName) const = 0;

    // True iff the uid holds the permission (user aware).
    // Fails with NO_INIT if cache hasn't been populated.
    virtual ::android::error::BinderResult<bool> checkPermission(PermissionEnum permission,
                                                                 uid_t uid) const = 0;
    // Get the highest target sdk of all packages for a given app-id.
    virtual ::android::error::BinderResult<int32_t> getHighestTargetSdkForUid(uid_t uid) const = 0;

    // True iff all packages associated with the app-id allow playback capture (via manifest flags).
    virtual ::android::error::BinderResult<bool> doesUidPermitPlaybackCapture(uid_t uid) const = 0;

    virtual std::string dumpString() const = 0;
    virtual ~IPermissionProvider() = default;
};
+5 −1
Original line number Diff line number Diff line
@@ -43,12 +43,16 @@ class NativePermissionController : public BnNativePermissionController, public I
    ::android::error::BinderResult<bool> checkPermission(PermissionEnum permission,
                                                         uid_t uid) const final;

    ::android::error::BinderResult<int32_t> getHighestTargetSdkForUid(uid_t uid) const final;
    ::android::error::BinderResult<bool> doesUidPermitPlaybackCapture(uid_t uid) const final;

    std::string dumpString() const final;

  private:
    mutable std::mutex m_;
    // map of app_ids to the set of packages names which could run in them (should be 1)
    std::unordered_map<uid_t, std::vector<std::string>> package_map_ GUARDED_BY(m_);
    std::unordered_map<uid_t, std::vector<UidPackageState::PackageState>> package_map_
            GUARDED_BY(m_);
    bool is_package_populated_ GUARDED_BY(m_);
    // (logical) map of PermissionEnum to list of uids (not appid) which hold the perm
    std::array<std::vector<uid_t>, static_cast<size_t>(PermissionEnum::ENUM_SIZE)> permission_map_
+98 −23
Original line number Diff line number Diff line
@@ -41,10 +41,20 @@ class NativePermissionControllerTest : public ::testing::Test {
            android::sp<NativePermissionController>::make();
    NativePermissionController& controller_ = *holder_;
};
static UidPackageState createState(uid_t uid, std::vector<std::string> packagesNames) {
static UidPackageState::PackageState createPackageState(std::string packageName, int targetSdk = 34,
                                                        bool isPlaybackCaptureAllowed = false) {
    UidPackageState::PackageState out{};
    out.packageName = std::move(packageName);
    out.targetSdk = targetSdk;
    out.isPlaybackCaptureAllowed = isPlaybackCaptureAllowed;
    return out;
}

static UidPackageState createState(uid_t uid,
                                   std::vector<UidPackageState::PackageState> packagesStates) {
    UidPackageState out{};
    out.uid = uid;
    out.packageNames = std::move(packagesNames);
    out.packageStates = std::move(packagesStates);
    return out;
}

@@ -71,7 +81,7 @@ TEST_F(NativePermissionControllerTest, validateUidPackagePair_NotPopulated) {

// ---  Tests for populatePackagesForUids ----
TEST_F(NativePermissionControllerTest, populatePackages_EmptyInput) {
    std::vector<UidPackageState> input;
    const std::vector<UidPackageState> input;

    // succeeds
    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
@@ -82,9 +92,10 @@ TEST_F(NativePermissionControllerTest, populatePackages_EmptyInput) {
}

TEST_F(NativePermissionControllerTest, populatePackages_ValidInput) {
    std::vector<UidPackageState> input{
            createState(10000, {"com.example.app1", "com.example.app2"}),
            createState(10001, {"com.example2.app1"}),
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1"),
                                createPackageState("com.example.app2")}),
            createState(10001, {createPackageState("com.example2.app1")}),
    };

    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
@@ -96,11 +107,12 @@ TEST_F(NativePermissionControllerTest, populatePackages_ValidInput) {

// --- Tests for updatePackagesForUid ---
TEST_F(NativePermissionControllerTest, updatePackages_NewUid) {
    std::vector<UidPackageState> input{
            createState(10000, {"com.example.app1", "com.example.app2"}),
            createState(10001, {"com.example2.app1"}),
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1"),
                                createPackageState("com.example.app2")}),
            createState(10001, {createPackageState("com.example2.app1")}),
    };
    UidPackageState newState = createState(12000, {"com.example.other"});
    UidPackageState newState = createState(12000, {createPackageState("com.example.other")});

    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
    EXPECT_THAT(controller_.updatePackagesForUid(newState), BinderStatusMatcher::isOk());
@@ -113,14 +125,17 @@ TEST_F(NativePermissionControllerTest, updatePackages_NewUid) {
}

TEST_F(NativePermissionControllerTest, updatePackages_ExistingUid) {
    std::vector<UidPackageState> input{
            createState(10000, {"com.example.app1", "com.example.app2", "com.example.app3"}),
            createState(10001, {"com.example2.app1"}),
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1"),
                                createPackageState("com.example.app2"),
                                createPackageState("com.example.app3")}),
            createState(10001, {createPackageState("com.example2.app1")}),
    };

    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
    // Update packages for existing uid
    UidPackageState newState = createState(10000, {"com.example.other", "com.example.new"});
    UidPackageState newState = createState(10000, {createPackageState("com.example.other"),
                                                   createPackageState("com.example.new")});
    EXPECT_THAT(controller_.updatePackagesForUid(newState), BinderStatusMatcher::isOk());

    // Verify update
@@ -129,8 +144,8 @@ TEST_F(NativePermissionControllerTest, updatePackages_ExistingUid) {
}

TEST_F(NativePermissionControllerTest, updatePackages_EmptyRemovesEntry) {
    std::vector<UidPackageState> input{
            createState(10000, {"com.example.app1"}),
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1")}),
    };

    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
@@ -144,8 +159,9 @@ TEST_F(NativePermissionControllerTest, updatePackages_EmptyRemovesEntry) {
}

TEST_F(NativePermissionControllerTest, validateUidPackagePair_ValidPair) {
    std::vector<UidPackageState> input{
            createState(10000, {"com.example.app1", "com.example.app2"}),
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1"),
                                createPackageState("com.example.app2")}),
    };

    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
@@ -154,8 +170,9 @@ TEST_F(NativePermissionControllerTest, validateUidPackagePair_ValidPair) {
}

TEST_F(NativePermissionControllerTest, validateUidPackagePair_InvalidPackage) {
    std::vector<UidPackageState> input{
            createState(10000, {"com.example.app1", "com.example.app2"}),
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1"),
                                createPackageState("com.example.app2")}),
    };

    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
@@ -164,8 +181,9 @@ TEST_F(NativePermissionControllerTest, validateUidPackagePair_InvalidPackage) {
}

TEST_F(NativePermissionControllerTest, validateUidPackagePair_UnknownUid) {
    std::vector<UidPackageState> input{
            createState(10000, {"com.example.app1", "com.example.app2"}),
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1"),
                                createPackageState("com.example.app2")}),
    };

    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
@@ -210,3 +228,60 @@ TEST_F(NativePermissionControllerTest, populatePermissionState_NotInitialized) {
    EXPECT_THAT(controller_.checkPermission(PermissionEnum::MODIFY_AUDIO_ROUTING, 3),
                IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
}

// --- Tests for getHighestTargetSdkForUid ---
TEST_F(NativePermissionControllerTest, getHighestTargetSdkForUid_NotPopulated) {
    EXPECT_THAT(controller_.getHighestTargetSdkForUid(10000),
                IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
}

TEST_F(NativePermissionControllerTest, getHighestTargetSdkForUid_UidNotFound) {
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1")}),
    };
    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
    EXPECT_THAT(controller_.getHighestTargetSdkForUid(10001),
                IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT)));
}

TEST_F(NativePermissionControllerTest, getHighestTargetSdkForUid_ReturnsHighest) {
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1", 33),
                                createPackageState("com.example.app2", 34)}),
    };
    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
    EXPECT_THAT(controller_.getHighestTargetSdkForUid(10000), IsOkAnd(34));
}

// --- Tests for doesUidPermitPlaybackCapture ---
TEST_F(NativePermissionControllerTest, doesUidPermitPlaybackCapture_NotPopulated) {
    EXPECT_THAT(controller_.doesUidPermitPlaybackCapture(10000),
                IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
}

TEST_F(NativePermissionControllerTest, doesUidPermitPlaybackCapture_UidNotFound) {
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1")}),
    };
    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
    EXPECT_THAT(controller_.doesUidPermitPlaybackCapture(10001),
                IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT)));
}

TEST_F(NativePermissionControllerTest, doesUidPermitPlaybackCapture_AllTrue) {
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1", 33, true),
                                createPackageState("com.example.app2", 34, true)}),
    };
    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
    EXPECT_THAT(controller_.doesUidPermitPlaybackCapture(10000), IsOkAnd(IsTrue()));
}

TEST_F(NativePermissionControllerTest, doesUidPermitPlaybackCapture_SomeFalse) {
    const std::vector<UidPackageState> input{
            createState(10000, {createPackageState("com.example.app1", 33, true),
                                createPackageState("com.example.app2", 34, false)}),
    };
    EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
    EXPECT_THAT(controller_.doesUidPermitPlaybackCapture(10000), IsOkAnd(IsFalse()));
}
Loading