1 /*
2  * Copyright (C) 2014 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 #define LOG_TAG "AudioPolicy"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 #include <media/AudioPolicy.h>
21 
22 namespace android {
23 
24 //
25 //  AudioMixMatchCriterion implementation
26 //
AudioMixMatchCriterion(audio_usage_t usage,audio_source_t source,uint32_t rule)27 AudioMixMatchCriterion::AudioMixMatchCriterion(audio_usage_t usage,
28                                                  audio_source_t source,
29                                                  uint32_t rule)
30 : mRule(rule)
31 {
32     if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
33             mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
34         mValue.mUsage = usage;
35     } else {
36         mValue.mSource = source;
37     }
38 }
39 
readFromParcel(Parcel * parcel)40 status_t AudioMixMatchCriterion::readFromParcel(Parcel *parcel)
41 {
42     mRule = parcel->readInt32();
43     switch (mRule) {
44     case RULE_MATCH_ATTRIBUTE_USAGE:
45     case RULE_EXCLUDE_ATTRIBUTE_USAGE:
46         mValue.mUsage = (audio_usage_t) parcel->readInt32();
47         break;
48     case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
49     case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET:
50         mValue.mSource = (audio_source_t) parcel->readInt32();
51         break;
52     case RULE_MATCH_UID:
53     case RULE_EXCLUDE_UID:
54         mValue.mUid = (uid_t) parcel->readInt32();
55         break;
56     default:
57         ALOGE("Trying to build AudioMixMatchCriterion from unknown rule %d", mRule);
58         return BAD_VALUE;
59     }
60     return NO_ERROR;
61 }
62 
writeToParcel(Parcel * parcel) const63 status_t AudioMixMatchCriterion::writeToParcel(Parcel *parcel) const
64 {
65     parcel->writeInt32(mRule);
66     parcel->writeInt32(mValue.mUsage);
67     return NO_ERROR;
68 }
69 
70 //
71 //  AudioMix implementation
72 //
73 
readFromParcel(Parcel * parcel)74 status_t AudioMix::readFromParcel(Parcel *parcel)
75 {
76     mMixType = parcel->readInt32();
77     mFormat.sample_rate = (uint32_t)parcel->readInt32();
78     mFormat.channel_mask = (audio_channel_mask_t)parcel->readInt32();
79     mFormat.format = (audio_format_t)parcel->readInt32();
80     mRouteFlags = parcel->readInt32();
81     mDeviceType = (audio_devices_t) parcel->readInt32();
82     mDeviceAddress = parcel->readString8();
83     mCbFlags = (uint32_t)parcel->readInt32();
84     mAllowPrivilegedPlaybackCapture = parcel->readBool();
85     size_t size = (size_t)parcel->readInt32();
86     if (size > MAX_CRITERIA_PER_MIX) {
87         size = MAX_CRITERIA_PER_MIX;
88     }
89     for (size_t i = 0; i < size; i++) {
90         AudioMixMatchCriterion criterion;
91         if (criterion.readFromParcel(parcel) == NO_ERROR) {
92             mCriteria.add(criterion);
93         }
94     }
95     return NO_ERROR;
96 }
97 
writeToParcel(Parcel * parcel) const98 status_t AudioMix::writeToParcel(Parcel *parcel) const
99 {
100     parcel->writeInt32(mMixType);
101     parcel->writeInt32(mFormat.sample_rate);
102     parcel->writeInt32(mFormat.channel_mask);
103     parcel->writeInt32(mFormat.format);
104     parcel->writeInt32(mRouteFlags);
105     parcel->writeInt32(mDeviceType);
106     parcel->writeString8(mDeviceAddress);
107     parcel->writeInt32(mCbFlags);
108     parcel->writeBool(mAllowPrivilegedPlaybackCapture);
109     size_t size = mCriteria.size();
110     if (size > MAX_CRITERIA_PER_MIX) {
111         size = MAX_CRITERIA_PER_MIX;
112     }
113     size_t sizePosition = parcel->dataPosition();
114     parcel->writeInt32(size);
115     size_t finalSize = size;
116     for (size_t i = 0; i < size; i++) {
117         size_t position = parcel->dataPosition();
118         if (mCriteria[i].writeToParcel(parcel) != NO_ERROR) {
119             parcel->setDataPosition(position);
120             finalSize--;
121         }
122     }
123     if (size != finalSize) {
124         size_t position = parcel->dataPosition();
125         parcel->setDataPosition(sizePosition);
126         parcel->writeInt32(finalSize);
127         parcel->setDataPosition(position);
128     }
129     return NO_ERROR;
130 }
131 
setExcludeUid(uid_t uid) const132 void AudioMix::setExcludeUid(uid_t uid) const {
133     AudioMixMatchCriterion crit;
134     crit.mRule = RULE_EXCLUDE_UID;
135     crit.mValue.mUid = uid;
136     mCriteria.add(crit);
137 }
138 
setMatchUid(uid_t uid) const139 void AudioMix::setMatchUid(uid_t uid) const {
140     AudioMixMatchCriterion crit;
141     crit.mRule = RULE_MATCH_UID;
142     crit.mValue.mUid = uid;
143     mCriteria.add(crit);
144 }
145 
hasUidRule(bool match,uid_t uid) const146 bool AudioMix::hasUidRule(bool match, uid_t uid) const {
147     const uint32_t rule = match ? RULE_MATCH_UID : RULE_EXCLUDE_UID;
148     for (size_t i = 0; i < mCriteria.size(); i++) {
149         if (mCriteria[i].mRule == rule
150                 && mCriteria[i].mValue.mUid == uid) {
151             return true;
152         }
153     }
154     return false;
155 }
156 
hasMatchUidRule() const157 bool AudioMix::hasMatchUidRule() const {
158     for (size_t i = 0; i < mCriteria.size(); i++) {
159         if (mCriteria[i].mRule == RULE_MATCH_UID) {
160             return true;
161         }
162     }
163     return false;
164 }
165 
isDeviceAffinityCompatible() const166 bool AudioMix::isDeviceAffinityCompatible() const {
167     return ((mMixType == MIX_TYPE_PLAYERS)
168             && (mRouteFlags == MIX_ROUTE_FLAG_RENDER));
169 }
170 
171 } // namespace android
172