1 /*
2 * Copyright (C) 2023 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 <android/content/pm/IPackageManagerNative.h>
18
19 #include "AudioRecordClient.h"
20 #include "AudioPolicyService.h"
21 #include "binder/AppOpsManager.h"
22 #include "mediautils/ServiceUtilities.h"
23 #include <android_media_audiopolicy.h>
24 #include <media/AttrSourceIter.h>
25
26 #include <algorithm>
27
28 namespace android::media::audiopolicy {
29 namespace audiopolicy_flags = android::media::audiopolicy;
30 using android::AudioPolicyService;
31
32 namespace {
isAppOpSource(audio_source_t source)33 bool isAppOpSource(audio_source_t source) {
34 switch (source) {
35 case AUDIO_SOURCE_FM_TUNER:
36 case AUDIO_SOURCE_ECHO_REFERENCE:
37 case AUDIO_SOURCE_REMOTE_SUBMIX:
38 return false;
39 default:
40 break;
41 }
42 return true;
43 }
44
getTargetSdkForPackageName(std::string_view packageName)45 int getTargetSdkForPackageName(std::string_view packageName) {
46 const auto binder = defaultServiceManager()->checkService(String16{"package_native"});
47 int targetSdk = -1;
48 if (binder != nullptr) {
49 const auto pm = interface_cast<content::pm::IPackageManagerNative>(binder);
50 if (pm != nullptr) {
51 const auto status = pm->getTargetSdkVersionForPackage(
52 String16{packageName.data(), packageName.size()}, &targetSdk);
53 return status.isOk() ? targetSdk : -1;
54 }
55 }
56 return targetSdk;
57 }
58
doesPackageTargetAtLeastU(std::string_view packageName)59 bool doesPackageTargetAtLeastU(std::string_view packageName) {
60 return getTargetSdkForPackageName(packageName) >= __ANDROID_API_U__;
61 }
62 } // anonymous
63
64 // static
65 sp<OpRecordAudioMonitor>
createIfNeeded(const AttributionSourceState & attributionSource,const uint32_t virtualDeviceId,const audio_attributes_t & attr,wp<AudioPolicyService::AudioCommandThread> commandThread)66 OpRecordAudioMonitor::createIfNeeded(
67 const AttributionSourceState &attributionSource,
68 const uint32_t virtualDeviceId,
69 const audio_attributes_t &attr,
70 wp<AudioPolicyService::AudioCommandThread> commandThread)
71 {
72 if (isAudioServerOrRootUid(attributionSource.uid)) {
73 ALOGV("not silencing record for audio or root source %s",
74 attributionSource.toString().c_str());
75 return nullptr;
76 }
77
78 if (!isAppOpSource(attr.source)) {
79 ALOGD("not monitoring app op for uid %d and source %d",
80 attributionSource.uid, attr.source);
81 return nullptr;
82 }
83
84 if (!attributionSource.packageName.has_value()
85 || attributionSource.packageName.value().size() == 0) {
86 return nullptr;
87 }
88
89 return new OpRecordAudioMonitor(attributionSource, virtualDeviceId, attr,
90 getOpForSource(attr.source),
91 isRecordOpRequired(attr.source),
92 commandThread);
93 }
94
95 // The vdi is carried in the attribution source for appops perm checks.
96 // Overwrite the entire chain with the vdi associated with the mix this client is attached to
97 // This ensures the checkOps triggered by the listener are correct.
98 // Note: we still only register for events by package name, so we assume that we get events
99 // independent of vdi.
overwriteVdi(AttributionSourceState & chain,int vdi)100 static AttributionSourceState& overwriteVdi(AttributionSourceState& chain, int vdi) {
101 using permission::AttrSourceIter::begin;
102 using permission::AttrSourceIter::end;
103 if (vdi != 0 /* default vdi */) {
104 std::for_each(begin(chain), end(), [vdi](auto& attr) { attr.deviceId = vdi; });
105 }
106 return chain;
107 }
108
OpRecordAudioMonitor(AttributionSourceState attributionSource,const uint32_t virtualDeviceId,const audio_attributes_t & attr,int32_t appOp,bool shouldMonitorRecord,wp<AudioPolicyService::AudioCommandThread> commandThread)109 OpRecordAudioMonitor::OpRecordAudioMonitor(
110 AttributionSourceState attributionSource,
111 const uint32_t virtualDeviceId, const audio_attributes_t &attr,
112 int32_t appOp,
113 bool shouldMonitorRecord,
114 wp<AudioPolicyService::AudioCommandThread> commandThread) :
115 mHasOp(true),
116 mAttributionSource(overwriteVdi(attributionSource, virtualDeviceId)),
117 mVirtualDeviceId(virtualDeviceId), mAttr(attr),
118 mAppOp(appOp),
119 mShouldMonitorRecord(shouldMonitorRecord),
120 mCommandThread(commandThread) {}
121
~OpRecordAudioMonitor()122 OpRecordAudioMonitor::~OpRecordAudioMonitor()
123 {
124 if (mOpCallback != 0) {
125 mAppOpsManager.stopWatchingMode(mOpCallback);
126 }
127 mOpCallback.clear();
128 }
129
onFirstRef()130 void OpRecordAudioMonitor::onFirstRef()
131 {
132 using permission::AttrSourceIter::cbegin;
133 using permission::AttrSourceIter::cend;
134
135 checkOp();
136 mOpCallback = new RecordAudioOpCallback(this);
137 ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str());
138
139 int flags = doesPackageTargetAtLeastU(mAttributionSource.packageName.value_or(""))
140 ? AppOpsManager::WATCH_FOREGROUND_CHANGES
141 : 0;
142
143 const auto reg = [&](int32_t op) {
144 std::for_each(cbegin(mAttributionSource), cend(),
145 [&](const auto& attr) {
146 mAppOpsManager.startWatchingMode(
147 op,
148 VALUE_OR_FATAL(aidl2legacy_string_view_String16(
149 attr.packageName.value_or(""))),
150 flags, mOpCallback);
151 });
152 };
153 reg(mAppOp);
154 if (mAppOp != AppOpsManager::OP_RECORD_AUDIO && mShouldMonitorRecord) {
155 reg(AppOpsManager::OP_RECORD_AUDIO);
156 }
157 }
158
hasOp() const159 bool OpRecordAudioMonitor::hasOp() const {
160 return mHasOp.load();
161 }
162
163 // Called by RecordAudioOpCallback when the app op corresponding to this OpRecordAudioMonitor
164 // is updated in AppOp callback and in onFirstRef()
165 // Note this method is never called (and never to be) for audio server / root track
166 // due to the UID in createIfNeeded(). As a result for those record track, it's:
167 // - not called from constructor,
168 // - not called from RecordAudioOpCallback because the callback is not installed in this case
checkOp(bool updateUidStates)169 void OpRecordAudioMonitor::checkOp(bool updateUidStates) {
170 using permission::AttrSourceIter::cbegin;
171 using permission::AttrSourceIter::cend;
172
173 const auto check = [&](int32_t op) -> bool {
174 return std::all_of(cbegin(mAttributionSource), cend(), [&](const auto& x) {
175 return mAppOpsManager.checkOp(op, x.uid,
176 VALUE_OR_FATAL(aidl2legacy_string_view_String16(
177 x.packageName.value_or("")))) ==
178 AppOpsManager::MODE_ALLOWED;
179 });
180 };
181 bool hasIt = check(mAppOp);
182 if (mAppOp != AppOpsManager::OP_RECORD_AUDIO && mShouldMonitorRecord) {
183 hasIt = hasIt && check(AppOpsManager::OP_RECORD_AUDIO);
184 }
185
186 if (audiopolicy_flags::record_audio_device_aware_permission()) {
187 const bool canRecord = recordingAllowed(mAttributionSource, mVirtualDeviceId, mAttr.source);
188 hasIt = hasIt && canRecord;
189 }
190 // verbose logging only log when appOp changed
191 ALOGI_IF(hasIt != mHasOp.load(),
192 "App op %d missing, %ssilencing record %s",
193 mAppOp, hasIt ? "un" : "", mAttributionSource.toString().c_str());
194 mHasOp.store(hasIt);
195
196 if (updateUidStates) {
197 sp<AudioPolicyService::AudioCommandThread> commandThread = mCommandThread.promote();
198 if (commandThread != nullptr) {
199 commandThread->updateUidStatesCommand();
200 }
201 }
202 }
203
RecordAudioOpCallback(const wp<OpRecordAudioMonitor> & monitor)204 OpRecordAudioMonitor::RecordAudioOpCallback::RecordAudioOpCallback(
205 const wp<OpRecordAudioMonitor>& monitor) : mMonitor(monitor)
206 { }
207
opChanged(int32_t op,const String16 & packageName __unused)208 void OpRecordAudioMonitor::RecordAudioOpCallback::opChanged(int32_t op,
209 const String16& packageName __unused) {
210 sp<OpRecordAudioMonitor> monitor = mMonitor.promote();
211 if (monitor != NULL) {
212 if (op != monitor->getOp()) {
213 return;
214 }
215 monitor->checkOp(true);
216 }
217 }
218
219 } // namespace android::media::audiopolicy
220