blob: d88c69fe6c1d2a530bba8527317e0ab079fa6e62 [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
91// -- End Binder methods
92
93Result<std::vector<std::string>> NativePermissionController::getPackagesForUid(uid_t uid) const {
94 uid = uid % AID_USER_OFFSET;
95 const auto fixed_package_opt = getFixedPackageName(uid);
96 if (fixed_package_opt.has_value()) {
97 return Result<std::vector<std::string>>{std::in_place_t{}, {fixed_package_opt.value()}};
98 }
99 std::lock_guard l{m_};
100 if (!is_package_populated_) return unexpected{::android::NO_INIT};
101 const auto cursor = package_map_.find(uid);
102 if (cursor != package_map_.end()) {
103 return cursor->second;
104 } else {
105 return unexpected{::android::BAD_VALUE};
106 }
107}
108
109Result<bool> NativePermissionController::validateUidPackagePair(
110 uid_t uid, const std::string& packageName) const {
111 uid = uid % AID_USER_OFFSET;
112 const auto fixed_package_opt = getFixedPackageName(uid);
113 if (fixed_package_opt.has_value()) {
114 return packageName == fixed_package_opt.value();
115 }
116 std::lock_guard l{m_};
117 if (!is_package_populated_) return unexpected{::android::NO_INIT};
118 const auto cursor = package_map_.find(uid);
119 return (cursor != package_map_.end()) &&
120 (std::find(cursor->second.begin(), cursor->second.end(), packageName) !=
121 cursor->second.end());
122}
123} // namespace com::android::media::permission