1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AudioPolicy"
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioPolicy.h>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker namespace android {
23*ec779b8eSAndroid Build Coastguard Worker
24*ec779b8eSAndroid Build Coastguard Worker //
25*ec779b8eSAndroid Build Coastguard Worker // AudioMixMatchCriterion implementation
26*ec779b8eSAndroid Build Coastguard Worker //
AudioMixMatchCriterion(audio_usage_t usage,audio_source_t source,uint32_t rule)27*ec779b8eSAndroid Build Coastguard Worker AudioMixMatchCriterion::AudioMixMatchCriterion(audio_usage_t usage,
28*ec779b8eSAndroid Build Coastguard Worker audio_source_t source,
29*ec779b8eSAndroid Build Coastguard Worker uint32_t rule)
30*ec779b8eSAndroid Build Coastguard Worker : mRule(rule)
31*ec779b8eSAndroid Build Coastguard Worker {
32*ec779b8eSAndroid Build Coastguard Worker if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
33*ec779b8eSAndroid Build Coastguard Worker mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
34*ec779b8eSAndroid Build Coastguard Worker mValue.mUsage = usage;
35*ec779b8eSAndroid Build Coastguard Worker } else {
36*ec779b8eSAndroid Build Coastguard Worker mValue.mSource = source;
37*ec779b8eSAndroid Build Coastguard Worker }
38*ec779b8eSAndroid Build Coastguard Worker }
39*ec779b8eSAndroid Build Coastguard Worker
readFromParcel(Parcel * parcel)40*ec779b8eSAndroid Build Coastguard Worker status_t AudioMixMatchCriterion::readFromParcel(Parcel *parcel)
41*ec779b8eSAndroid Build Coastguard Worker {
42*ec779b8eSAndroid Build Coastguard Worker mRule = parcel->readInt32();
43*ec779b8eSAndroid Build Coastguard Worker switch (mRule) {
44*ec779b8eSAndroid Build Coastguard Worker case RULE_MATCH_ATTRIBUTE_USAGE:
45*ec779b8eSAndroid Build Coastguard Worker case RULE_EXCLUDE_ATTRIBUTE_USAGE:
46*ec779b8eSAndroid Build Coastguard Worker mValue.mUsage = (audio_usage_t) parcel->readInt32();
47*ec779b8eSAndroid Build Coastguard Worker break;
48*ec779b8eSAndroid Build Coastguard Worker case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
49*ec779b8eSAndroid Build Coastguard Worker case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET:
50*ec779b8eSAndroid Build Coastguard Worker mValue.mSource = (audio_source_t) parcel->readInt32();
51*ec779b8eSAndroid Build Coastguard Worker break;
52*ec779b8eSAndroid Build Coastguard Worker case RULE_MATCH_UID:
53*ec779b8eSAndroid Build Coastguard Worker case RULE_EXCLUDE_UID:
54*ec779b8eSAndroid Build Coastguard Worker mValue.mUid = (uid_t) parcel->readInt32();
55*ec779b8eSAndroid Build Coastguard Worker break;
56*ec779b8eSAndroid Build Coastguard Worker case RULE_MATCH_USERID:
57*ec779b8eSAndroid Build Coastguard Worker case RULE_EXCLUDE_USERID:
58*ec779b8eSAndroid Build Coastguard Worker mValue.mUserId = (int) parcel->readInt32();
59*ec779b8eSAndroid Build Coastguard Worker break;
60*ec779b8eSAndroid Build Coastguard Worker case RULE_MATCH_AUDIO_SESSION_ID:
61*ec779b8eSAndroid Build Coastguard Worker case RULE_EXCLUDE_AUDIO_SESSION_ID:
62*ec779b8eSAndroid Build Coastguard Worker mValue.mAudioSessionId = (audio_session_t) parcel->readInt32();
63*ec779b8eSAndroid Build Coastguard Worker break;
64*ec779b8eSAndroid Build Coastguard Worker default:
65*ec779b8eSAndroid Build Coastguard Worker ALOGE("Trying to build AudioMixMatchCriterion from unknown rule %d", mRule);
66*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
67*ec779b8eSAndroid Build Coastguard Worker }
68*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
69*ec779b8eSAndroid Build Coastguard Worker }
70*ec779b8eSAndroid Build Coastguard Worker
writeToParcel(Parcel * parcel) const71*ec779b8eSAndroid Build Coastguard Worker status_t AudioMixMatchCriterion::writeToParcel(Parcel *parcel) const
72*ec779b8eSAndroid Build Coastguard Worker {
73*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(mRule);
74*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(mValue.mUsage);
75*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
76*ec779b8eSAndroid Build Coastguard Worker }
77*ec779b8eSAndroid Build Coastguard Worker
isExcludeCriterion() const78*ec779b8eSAndroid Build Coastguard Worker bool AudioMixMatchCriterion::isExcludeCriterion() const {
79*ec779b8eSAndroid Build Coastguard Worker return mRule & RULE_EXCLUSION_MASK;
80*ec779b8eSAndroid Build Coastguard Worker }
81*ec779b8eSAndroid Build Coastguard Worker
82*ec779b8eSAndroid Build Coastguard Worker //
83*ec779b8eSAndroid Build Coastguard Worker // AudioMix implementation
84*ec779b8eSAndroid Build Coastguard Worker //
85*ec779b8eSAndroid Build Coastguard Worker
readFromParcel(Parcel * parcel)86*ec779b8eSAndroid Build Coastguard Worker status_t AudioMix::readFromParcel(Parcel *parcel)
87*ec779b8eSAndroid Build Coastguard Worker {
88*ec779b8eSAndroid Build Coastguard Worker mMixType = parcel->readInt32();
89*ec779b8eSAndroid Build Coastguard Worker mFormat.sample_rate = (uint32_t)parcel->readInt32();
90*ec779b8eSAndroid Build Coastguard Worker mFormat.channel_mask = (audio_channel_mask_t)parcel->readInt32();
91*ec779b8eSAndroid Build Coastguard Worker mFormat.format = (audio_format_t)parcel->readInt32();
92*ec779b8eSAndroid Build Coastguard Worker mRouteFlags = parcel->readInt32();
93*ec779b8eSAndroid Build Coastguard Worker mDeviceType = (audio_devices_t) parcel->readInt32();
94*ec779b8eSAndroid Build Coastguard Worker mDeviceAddress = parcel->readString8();
95*ec779b8eSAndroid Build Coastguard Worker mCbFlags = (uint32_t)parcel->readInt32();
96*ec779b8eSAndroid Build Coastguard Worker mAllowPrivilegedMediaPlaybackCapture = parcel->readBool();
97*ec779b8eSAndroid Build Coastguard Worker mVoiceCommunicationCaptureAllowed = parcel->readBool();
98*ec779b8eSAndroid Build Coastguard Worker size_t size = (size_t)parcel->readInt32();
99*ec779b8eSAndroid Build Coastguard Worker if (size > MAX_CRITERIA_PER_MIX) {
100*ec779b8eSAndroid Build Coastguard Worker size = MAX_CRITERIA_PER_MIX;
101*ec779b8eSAndroid Build Coastguard Worker }
102*ec779b8eSAndroid Build Coastguard Worker mCriteria.reserve(size);
103*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < size; i++) {
104*ec779b8eSAndroid Build Coastguard Worker AudioMixMatchCriterion criterion;
105*ec779b8eSAndroid Build Coastguard Worker if (criterion.readFromParcel(parcel) == NO_ERROR) {
106*ec779b8eSAndroid Build Coastguard Worker mCriteria.push_back(criterion);
107*ec779b8eSAndroid Build Coastguard Worker }
108*ec779b8eSAndroid Build Coastguard Worker }
109*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
110*ec779b8eSAndroid Build Coastguard Worker }
111*ec779b8eSAndroid Build Coastguard Worker
writeToParcel(Parcel * parcel) const112*ec779b8eSAndroid Build Coastguard Worker status_t AudioMix::writeToParcel(Parcel *parcel) const
113*ec779b8eSAndroid Build Coastguard Worker {
114*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(mMixType);
115*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(mFormat.sample_rate);
116*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(mFormat.channel_mask);
117*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(mFormat.format);
118*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(mRouteFlags);
119*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(mDeviceType);
120*ec779b8eSAndroid Build Coastguard Worker parcel->writeString8(mDeviceAddress);
121*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(mCbFlags);
122*ec779b8eSAndroid Build Coastguard Worker parcel->writeBool(mAllowPrivilegedMediaPlaybackCapture);
123*ec779b8eSAndroid Build Coastguard Worker parcel->writeBool(mVoiceCommunicationCaptureAllowed);
124*ec779b8eSAndroid Build Coastguard Worker size_t size = mCriteria.size();
125*ec779b8eSAndroid Build Coastguard Worker if (size > MAX_CRITERIA_PER_MIX) {
126*ec779b8eSAndroid Build Coastguard Worker size = MAX_CRITERIA_PER_MIX;
127*ec779b8eSAndroid Build Coastguard Worker }
128*ec779b8eSAndroid Build Coastguard Worker size_t sizePosition = parcel->dataPosition();
129*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(size);
130*ec779b8eSAndroid Build Coastguard Worker size_t finalSize = size;
131*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < size; i++) {
132*ec779b8eSAndroid Build Coastguard Worker size_t position = parcel->dataPosition();
133*ec779b8eSAndroid Build Coastguard Worker if (mCriteria[i].writeToParcel(parcel) != NO_ERROR) {
134*ec779b8eSAndroid Build Coastguard Worker parcel->setDataPosition(position);
135*ec779b8eSAndroid Build Coastguard Worker finalSize--;
136*ec779b8eSAndroid Build Coastguard Worker }
137*ec779b8eSAndroid Build Coastguard Worker }
138*ec779b8eSAndroid Build Coastguard Worker if (size != finalSize) {
139*ec779b8eSAndroid Build Coastguard Worker size_t position = parcel->dataPosition();
140*ec779b8eSAndroid Build Coastguard Worker parcel->setDataPosition(sizePosition);
141*ec779b8eSAndroid Build Coastguard Worker parcel->writeInt32(finalSize);
142*ec779b8eSAndroid Build Coastguard Worker parcel->setDataPosition(position);
143*ec779b8eSAndroid Build Coastguard Worker }
144*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
145*ec779b8eSAndroid Build Coastguard Worker }
146*ec779b8eSAndroid Build Coastguard Worker
setExcludeUid(uid_t uid)147*ec779b8eSAndroid Build Coastguard Worker void AudioMix::setExcludeUid(uid_t uid) {
148*ec779b8eSAndroid Build Coastguard Worker AudioMixMatchCriterion crit;
149*ec779b8eSAndroid Build Coastguard Worker crit.mRule = RULE_EXCLUDE_UID;
150*ec779b8eSAndroid Build Coastguard Worker crit.mValue.mUid = uid;
151*ec779b8eSAndroid Build Coastguard Worker mCriteria.push_back(crit);
152*ec779b8eSAndroid Build Coastguard Worker }
153*ec779b8eSAndroid Build Coastguard Worker
setMatchUid(uid_t uid)154*ec779b8eSAndroid Build Coastguard Worker void AudioMix::setMatchUid(uid_t uid) {
155*ec779b8eSAndroid Build Coastguard Worker AudioMixMatchCriterion crit;
156*ec779b8eSAndroid Build Coastguard Worker crit.mRule = RULE_MATCH_UID;
157*ec779b8eSAndroid Build Coastguard Worker crit.mValue.mUid = uid;
158*ec779b8eSAndroid Build Coastguard Worker mCriteria.push_back(crit);
159*ec779b8eSAndroid Build Coastguard Worker }
160*ec779b8eSAndroid Build Coastguard Worker
hasUidRule(bool match,uid_t uid) const161*ec779b8eSAndroid Build Coastguard Worker bool AudioMix::hasUidRule(bool match, uid_t uid) const {
162*ec779b8eSAndroid Build Coastguard Worker const uint32_t rule = match ? RULE_MATCH_UID : RULE_EXCLUDE_UID;
163*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < mCriteria.size(); i++) {
164*ec779b8eSAndroid Build Coastguard Worker if (mCriteria[i].mRule == rule
165*ec779b8eSAndroid Build Coastguard Worker && mCriteria[i].mValue.mUid == uid) {
166*ec779b8eSAndroid Build Coastguard Worker return true;
167*ec779b8eSAndroid Build Coastguard Worker }
168*ec779b8eSAndroid Build Coastguard Worker }
169*ec779b8eSAndroid Build Coastguard Worker return false;
170*ec779b8eSAndroid Build Coastguard Worker }
171*ec779b8eSAndroid Build Coastguard Worker
hasMatchUidRule() const172*ec779b8eSAndroid Build Coastguard Worker bool AudioMix::hasMatchUidRule() const {
173*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < mCriteria.size(); i++) {
174*ec779b8eSAndroid Build Coastguard Worker if (mCriteria[i].mRule == RULE_MATCH_UID) {
175*ec779b8eSAndroid Build Coastguard Worker return true;
176*ec779b8eSAndroid Build Coastguard Worker }
177*ec779b8eSAndroid Build Coastguard Worker }
178*ec779b8eSAndroid Build Coastguard Worker return false;
179*ec779b8eSAndroid Build Coastguard Worker }
180*ec779b8eSAndroid Build Coastguard Worker
setExcludeUserId(int userId)181*ec779b8eSAndroid Build Coastguard Worker void AudioMix::setExcludeUserId(int userId) {
182*ec779b8eSAndroid Build Coastguard Worker AudioMixMatchCriterion crit;
183*ec779b8eSAndroid Build Coastguard Worker crit.mRule = RULE_EXCLUDE_USERID;
184*ec779b8eSAndroid Build Coastguard Worker crit.mValue.mUserId = userId;
185*ec779b8eSAndroid Build Coastguard Worker mCriteria.push_back(crit);
186*ec779b8eSAndroid Build Coastguard Worker }
187*ec779b8eSAndroid Build Coastguard Worker
setMatchUserId(int userId)188*ec779b8eSAndroid Build Coastguard Worker void AudioMix::setMatchUserId(int userId) {
189*ec779b8eSAndroid Build Coastguard Worker AudioMixMatchCriterion crit;
190*ec779b8eSAndroid Build Coastguard Worker crit.mRule = RULE_MATCH_USERID;
191*ec779b8eSAndroid Build Coastguard Worker crit.mValue.mUserId = userId;
192*ec779b8eSAndroid Build Coastguard Worker mCriteria.push_back(crit);
193*ec779b8eSAndroid Build Coastguard Worker }
194*ec779b8eSAndroid Build Coastguard Worker
hasUserIdRule(bool match,int userId) const195*ec779b8eSAndroid Build Coastguard Worker bool AudioMix::hasUserIdRule(bool match, int userId) const {
196*ec779b8eSAndroid Build Coastguard Worker const uint32_t rule = match ? RULE_MATCH_USERID : RULE_EXCLUDE_USERID;
197*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < mCriteria.size(); i++) {
198*ec779b8eSAndroid Build Coastguard Worker if (mCriteria[i].mRule == rule
199*ec779b8eSAndroid Build Coastguard Worker && mCriteria[i].mValue.mUserId == userId) {
200*ec779b8eSAndroid Build Coastguard Worker return true;
201*ec779b8eSAndroid Build Coastguard Worker }
202*ec779b8eSAndroid Build Coastguard Worker }
203*ec779b8eSAndroid Build Coastguard Worker return false;
204*ec779b8eSAndroid Build Coastguard Worker }
205*ec779b8eSAndroid Build Coastguard Worker
hasUserIdRule(bool match) const206*ec779b8eSAndroid Build Coastguard Worker bool AudioMix::hasUserIdRule(bool match) const {
207*ec779b8eSAndroid Build Coastguard Worker const uint32_t rule = match ? RULE_MATCH_USERID : RULE_EXCLUDE_USERID;
208*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < mCriteria.size(); i++) {
209*ec779b8eSAndroid Build Coastguard Worker if (mCriteria[i].mRule == rule) {
210*ec779b8eSAndroid Build Coastguard Worker return true;
211*ec779b8eSAndroid Build Coastguard Worker }
212*ec779b8eSAndroid Build Coastguard Worker }
213*ec779b8eSAndroid Build Coastguard Worker return false;
214*ec779b8eSAndroid Build Coastguard Worker }
215*ec779b8eSAndroid Build Coastguard Worker
isDeviceAffinityCompatible() const216*ec779b8eSAndroid Build Coastguard Worker bool AudioMix::isDeviceAffinityCompatible() const {
217*ec779b8eSAndroid Build Coastguard Worker return ((mMixType == MIX_TYPE_PLAYERS)
218*ec779b8eSAndroid Build Coastguard Worker && ((mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER));
219*ec779b8eSAndroid Build Coastguard Worker }
220*ec779b8eSAndroid Build Coastguard Worker
221*ec779b8eSAndroid Build Coastguard Worker } // namespace android
222