blob: 9fcf22d8a583d6d7f5b8a4dd759418ae091024e5 [file] [log] [blame]
Atneya Nair9f91a5e2024-05-09 16:25:05 -07001/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <media/NativePermissionController.h>
18
19#include <algorithm>
20#include <optional>
21#include <utility>
22
23#include <android-base/expected.h>
24#include <cutils/android_filesystem_config.h>
25#include <utils/Errors.h>
26
27using ::android::base::unexpected;
28using ::android::binder::Status;
29using ::android::error::Result;
30
31namespace com::android::media::permission {
32static std::optional<std::string> getFixedPackageName(uid_t uid) {
33 // These values are in sync with AppOpsService
34 switch (uid % AID_USER_OFFSET) {
35 case AID_ROOT:
36 return "root";
37 case AID_SYSTEM:
38 return "system";
39 case AID_SHELL:
40 return "shell";
41 case AID_MEDIA:
42 return "media";
43 case AID_AUDIOSERVER:
44 return "audioserver";
45 case AID_CAMERASERVER:
46 return "cameraserver";
47 // These packages are not handled by AppOps, but labeling may be useful for us
48 case AID_RADIO:
49 return "telephony";
50 case AID_BLUETOOTH:
51 return "bluetooth";
52 default:
53 return std::nullopt;
54 }
55}
56
57// -- Begin Binder methods
58Status NativePermissionController::populatePackagesForUids(
59 const std::vector<UidPackageState>& initialPackageStates) {
60 std::lock_guard l{m_};
61 if (!is_package_populated_) is_package_populated_ = true;
62 package_map_.clear();
63 std::transform(initialPackageStates.begin(), initialPackageStates.end(),
64 std::inserter(package_map_, package_map_.end()),
65 [](const auto& x) -> std::pair<uid_t, std::vector<std::string>> {
66 return {x.uid, x.packageNames};
67 });
68 std::erase_if(package_map_, [](const auto& x) { return x.second.empty(); });
69 return Status::ok();
70}
71
72Status NativePermissionController::updatePackagesForUid(const UidPackageState& newPackageState) {
73 std::lock_guard l{m_};
74 package_map_.insert_or_assign(newPackageState.uid, newPackageState.packageNames);
75 const auto& cursor = package_map_.find(newPackageState.uid);
76
77 if (newPackageState.packageNames.empty()) {
78 if (cursor != package_map_.end()) {
79 package_map_.erase(cursor);
80 }
81 } else {
82 if (cursor != package_map_.end()) {
83 cursor->second = newPackageState.packageNames;
84 } else {
85 package_map_.insert({newPackageState.uid, newPackageState.packageNames});
86 }
87 }
88 return Status::ok();
89}
90
Atneya Nairc23be502024-05-13 10:28:07 -070091Status NativePermissionController::populatePermissionState(PermissionEnum perm,
92 const std::vector<int>& uids) {
93 if (perm >= PermissionEnum::ENUM_SIZE || static_cast<int>(perm) < 0) {
94 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
95 }
96 std::lock_guard l{m_};
97 auto& cursor = permission_map_[static_cast<size_t>(perm)];
98 cursor = std::vector<uid_t>{uids.begin(), uids.end()};
99 // should be sorted
100 std::sort(cursor.begin(), cursor.end());
101 return Status::ok();
102}
103
Atneya Nair9f91a5e2024-05-09 16:25:05 -0700104// -- End Binder methods
105
106Result<std::vector<std::string>> NativePermissionController::getPackagesForUid(uid_t uid) const {
107 uid = uid % AID_USER_OFFSET;
108 const auto fixed_package_opt = getFixedPackageName(uid);
109 if (fixed_package_opt.has_value()) {
110 return Result<std::vector<std::string>>{std::in_place_t{}, {fixed_package_opt.value()}};
111 }
112 std::lock_guard l{m_};
113 if (!is_package_populated_) return unexpected{::android::NO_INIT};
114 const auto cursor = package_map_.find(uid);
115 if (cursor != package_map_.end()) {
116 return cursor->second;
117 } else {
118 return unexpected{::android::BAD_VALUE};
119 }
120}
121
122Result<bool> NativePermissionController::validateUidPackagePair(
123 uid_t uid, const std::string& packageName) const {
124 uid = uid % AID_USER_OFFSET;
125 const auto fixed_package_opt = getFixedPackageName(uid);
126 if (fixed_package_opt.has_value()) {
127 return packageName == fixed_package_opt.value();
128 }
129 std::lock_guard l{m_};
130 if (!is_package_populated_) return unexpected{::android::NO_INIT};
131 const auto cursor = package_map_.find(uid);
132 return (cursor != package_map_.end()) &&
133 (std::find(cursor->second.begin(), cursor->second.end(), packageName) !=
134 cursor->second.end());
135}
Atneya Nairc23be502024-05-13 10:28:07 -0700136
137Result<bool> NativePermissionController::checkPermission(PermissionEnum perm, uid_t uid) const {
138 std::lock_guard l{m_};
139 const auto& uids = permission_map_[static_cast<size_t>(perm)];
140 if (!uids.empty()) {
141 return std::binary_search(uids.begin(), uids.end(), uid);
142 } else {
143 return unexpected{::android::NO_INIT};
144 }
145}
146
Atneya Nair9f91a5e2024-05-09 16:25:05 -0700147} // namespace com::android::media::permission