blob: d88c69fe6c1d2a530bba8527317e0ab079fa6e62 [file] [log] [blame]
/*
* Copyright (C) 2024 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.
*/
#include <media/NativePermissionController.h>
#include <algorithm>
#include <optional>
#include <utility>
#include <android-base/expected.h>
#include <cutils/android_filesystem_config.h>
#include <utils/Errors.h>
using ::android::base::unexpected;
using ::android::binder::Status;
using ::android::error::Result;
namespace com::android::media::permission {
static std::optional<std::string> getFixedPackageName(uid_t uid) {
// These values are in sync with AppOpsService
switch (uid % AID_USER_OFFSET) {
case AID_ROOT:
return "root";
case AID_SYSTEM:
return "system";
case AID_SHELL:
return "shell";
case AID_MEDIA:
return "media";
case AID_AUDIOSERVER:
return "audioserver";
case AID_CAMERASERVER:
return "cameraserver";
// These packages are not handled by AppOps, but labeling may be useful for us
case AID_RADIO:
return "telephony";
case AID_BLUETOOTH:
return "bluetooth";
default:
return std::nullopt;
}
}
// -- Begin Binder methods
Status NativePermissionController::populatePackagesForUids(
const std::vector<UidPackageState>& initialPackageStates) {
std::lock_guard l{m_};
if (!is_package_populated_) is_package_populated_ = true;
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};
});
std::erase_if(package_map_, [](const auto& x) { return x.second.empty(); });
return Status::ok();
}
Status NativePermissionController::updatePackagesForUid(const UidPackageState& newPackageState) {
std::lock_guard l{m_};
package_map_.insert_or_assign(newPackageState.uid, newPackageState.packageNames);
const auto& cursor = package_map_.find(newPackageState.uid);
if (newPackageState.packageNames.empty()) {
if (cursor != package_map_.end()) {
package_map_.erase(cursor);
}
} else {
if (cursor != package_map_.end()) {
cursor->second = newPackageState.packageNames;
} else {
package_map_.insert({newPackageState.uid, newPackageState.packageNames});
}
}
return Status::ok();
}
// -- End Binder methods
Result<std::vector<std::string>> NativePermissionController::getPackagesForUid(uid_t uid) const {
uid = uid % AID_USER_OFFSET;
const auto fixed_package_opt = getFixedPackageName(uid);
if (fixed_package_opt.has_value()) {
return Result<std::vector<std::string>>{std::in_place_t{}, {fixed_package_opt.value()}};
}
std::lock_guard l{m_};
if (!is_package_populated_) return unexpected{::android::NO_INIT};
const auto cursor = package_map_.find(uid);
if (cursor != package_map_.end()) {
return cursor->second;
} else {
return unexpected{::android::BAD_VALUE};
}
}
Result<bool> NativePermissionController::validateUidPackagePair(
uid_t uid, const std::string& packageName) const {
uid = uid % AID_USER_OFFSET;
const auto fixed_package_opt = getFixedPackageName(uid);
if (fixed_package_opt.has_value()) {
return packageName == fixed_package_opt.value();
}
std::lock_guard l{m_};
if (!is_package_populated_) return unexpected{::android::NO_INIT};
const auto cursor = package_map_.find(uid);
return (cursor != package_map_.end()) &&
(std::find(cursor->second.begin(), cursor->second.end(), packageName) !=
cursor->second.end());
}
} // namespace com::android::media::permission