• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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/AppOpsSession.h>
18 #include <media/AttrSourceIter.h>
19 
20 #include <binder/AppOpsManager.h>
21 #include <binder/PermissionController.h>
22 
23 using ::android::content::AttributionSourceState;
24 
25 namespace android::media::permission {
26 
27 // Package name param is unreliable (can be empty), but we should only get valid events based on
28 // how we register the listener.
opChanged(int32_t op,int32_t,const String16 &,const String16 &)29 binder::Status DefaultAppOpsFacade::OpMonitor::opChanged(int32_t op, int32_t, const String16&,
30                                                          const String16&) {
31     if (mOps.attributedOp != op && mOps.additionalOp != op) return binder::Status::ok();
32     DefaultAppOpsFacade x{};
33     const auto allowed = x.checkAccess(mAttr, mOps);
34     std::lock_guard l_{mLock};
35     if (mCb != nullptr) {
36         mCb(allowed);
37     }
38     return binder::Status::ok();
39 }
40 
startAccess(const ValidatedAttributionSourceState & attr_,Ops ops)41 bool DefaultAppOpsFacade::startAccess(const ValidatedAttributionSourceState& attr_, Ops ops) {
42     const AttributionSourceState& attr = attr_;
43     // TODO(b/384845037) no support for additional op at the moment
44     if (ops.attributedOp == AppOpsManager::OP_NONE) return true;  // nothing to do
45     // TODO(b/384845037) caching and sync up-call marking
46     AppOpsManager ap{};
47     return ap.startOpNoThrow(
48         /*op=*/ ops.attributedOp,
49         /*uid=*/ attr.uid,
50         /*callingPackage=*/ String16{attr.packageName.value_or("").c_str()},
51         /*startIfModeDefault=*/ false,
52         /*attributionTag=*/ attr.attributionTag.has_value() ?
53             String16{attr.attributionTag.value().c_str()}
54                                             : String16{},
55         /*message=*/ String16{"AppOpsSession start"})
56     == AppOpsManager::MODE_ALLOWED;
57 }
58 
stopAccess(const ValidatedAttributionSourceState & attr_,Ops ops)59 void DefaultAppOpsFacade::stopAccess(const ValidatedAttributionSourceState& attr_, Ops ops) {
60     const AttributionSourceState& attr = attr_;
61     // TODO(b/384845037) caching and sync up-call marking
62     AppOpsManager ap{};
63     return ap.finishOp(
64         /*op=*/ ops.attributedOp,
65         /*uid=*/ attr.uid,
66         /*callingPackage=*/ String16{attr.packageName.value_or("").c_str()},
67         /*attributionTag=*/ attr.attributionTag.has_value() ?
68                                             String16{attr.attributionTag.value().c_str()}
69                                             : String16{});
70 }
71 
checkAccess(const ValidatedAttributionSourceState & attr,Ops ops)72 bool DefaultAppOpsFacade::checkAccess(const ValidatedAttributionSourceState& attr, Ops ops) {
73     const auto check = [&](int32_t op) -> bool {
74         if (op == AppOpsManager::OP_NONE) return true;
75         return std::all_of(
76                 AttrSourceIter::cbegin(attr), AttrSourceIter::cend(), [&](const auto& x) {
77                     return AppOpsManager{}.checkOp(op, x.uid,
78                                                    String16{x.packageName.value_or("").c_str()}) ==
79                                    AppOpsManager::MODE_ALLOWED;
80                 });
81     };
82     return check(ops.attributedOp) && check(ops.additionalOp);
83 }
84 
addChangeCallback(const ValidatedAttributionSourceState & attr,Ops ops,std::function<void (bool)> cb)85 uintptr_t DefaultAppOpsFacade::addChangeCallback(const ValidatedAttributionSourceState& attr,
86                                                  Ops ops, std::function<void(bool)> cb) {
87     const auto listener = sp<OpMonitor>::make(attr, ops, std::move(cb));
88     const auto reg = [&](int32_t op) {
89         std::for_each(AttrSourceIter::cbegin(attr), AttrSourceIter::cend(),
90                       [&listener, op](const auto& x) {
91                           AppOpsManager{}.startWatchingMode(
92                                   op, String16{x.packageName.value_or("").c_str()},
93                                   AppOpsManager::WATCH_FOREGROUND_CHANGES, listener);
94                       });
95     };
96     if (ops.attributedOp != AppOpsManager::OP_NONE) reg(ops.attributedOp);
97     if (ops.additionalOp != AppOpsManager::OP_NONE) reg(ops.additionalOp);
98     std::lock_guard l_{sMapLock};
99     const auto cookie = reinterpret_cast<uintptr_t>(listener.get());
100     sCbMap[cookie] = std::move(listener);
101     return cookie;
102 }
103 
removeChangeCallback(uintptr_t ptr)104 void DefaultAppOpsFacade::removeChangeCallback(uintptr_t ptr) {
105     sp<OpMonitor> monitor;
106     {
107         std::lock_guard l_{sMapLock};
108         if (const auto iter = sCbMap.find(ptr); iter != sCbMap.end()) {
109             monitor = std::move(iter->second);
110             sCbMap.erase(iter);
111         }
112     }
113     LOG_ALWAYS_FATAL_IF(monitor == nullptr, "Unexpected nullptr in cb map");
114     monitor->stopListening();
115     // Callbacks are stored via binder identity in AppOpsService, so unregistering the callback
116     // removes it regardless of how many calls to startWatchingMode occurred
117     AppOpsManager{}.stopWatchingMode(monitor);
118 }
119 
120 }  // namespace android::media::permission
121