xref: /aosp_15_r20/frameworks/av/media/libaudiousecasevalidation/UsecaseValidator.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2022 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 #define LOG_TAG "UsecaseValidator"
17*ec779b8eSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker 
19*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
20*ec779b8eSAndroid Build Coastguard Worker 
21*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
22*ec779b8eSAndroid Build Coastguard Worker 
23*ec779b8eSAndroid Build Coastguard Worker #include "media/UsecaseValidator.h"
24*ec779b8eSAndroid Build Coastguard Worker #include "media/UsecaseLookup.h"
25*ec779b8eSAndroid Build Coastguard Worker 
26*ec779b8eSAndroid Build Coastguard Worker namespace android {
27*ec779b8eSAndroid Build Coastguard Worker namespace media {
28*ec779b8eSAndroid Build Coastguard Worker namespace {
29*ec779b8eSAndroid Build Coastguard Worker 
30*ec779b8eSAndroid Build Coastguard Worker class UsecaseValidatorImpl : public UsecaseValidator {
31*ec779b8eSAndroid Build Coastguard Worker  public:
UsecaseValidatorImpl()32*ec779b8eSAndroid Build Coastguard Worker     UsecaseValidatorImpl() {}
33*ec779b8eSAndroid Build Coastguard Worker 
34*ec779b8eSAndroid Build Coastguard Worker     /**
35*ec779b8eSAndroid Build Coastguard Worker      * Register a new mixer/stream.
36*ec779b8eSAndroid Build Coastguard Worker      * Called when the stream is opened at the HAL and communicates
37*ec779b8eSAndroid Build Coastguard Worker      * immutable stream attributes like flags, sampling rate, format.
38*ec779b8eSAndroid Build Coastguard Worker      */
registerStream(audio_io_handle_t streamId,const audio_config_base_t & audioConfig,const audio_output_flags_t outputFlags)39*ec779b8eSAndroid Build Coastguard Worker     status_t registerStream(audio_io_handle_t streamId,
40*ec779b8eSAndroid Build Coastguard Worker                             const audio_config_base_t& audioConfig __attribute__((unused)),
41*ec779b8eSAndroid Build Coastguard Worker                             const audio_output_flags_t outputFlags) override {
42*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s output: %d flags: %#x", __func__, streamId, outputFlags);
43*ec779b8eSAndroid Build Coastguard Worker 
44*ec779b8eSAndroid Build Coastguard Worker         // Check if FAST or MMAP output flag has been set.
45*ec779b8eSAndroid Build Coastguard Worker         bool outputFlagGame = outputFlags & (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ);
46*ec779b8eSAndroid Build Coastguard Worker         m_lookup.addStream(streamId, outputFlagGame);
47*ec779b8eSAndroid Build Coastguard Worker         return OK;
48*ec779b8eSAndroid Build Coastguard Worker     };
49*ec779b8eSAndroid Build Coastguard Worker 
50*ec779b8eSAndroid Build Coastguard Worker     /**
51*ec779b8eSAndroid Build Coastguard Worker      * Unregister a stream/mixer.
52*ec779b8eSAndroid Build Coastguard Worker      * Called when the stream is closed.
53*ec779b8eSAndroid Build Coastguard Worker      */
unregisterStream(audio_io_handle_t streamId)54*ec779b8eSAndroid Build Coastguard Worker     status_t unregisterStream(audio_io_handle_t streamId) override {
55*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s output: %d", __func__, streamId);
56*ec779b8eSAndroid Build Coastguard Worker 
57*ec779b8eSAndroid Build Coastguard Worker         m_lookup.removeStream(streamId);
58*ec779b8eSAndroid Build Coastguard Worker         return OK;
59*ec779b8eSAndroid Build Coastguard Worker     };
60*ec779b8eSAndroid Build Coastguard Worker 
61*ec779b8eSAndroid Build Coastguard Worker     /**
62*ec779b8eSAndroid Build Coastguard Worker      * Indicates that some playback activity started on the stream.
63*ec779b8eSAndroid Build Coastguard Worker      * Called each time an audio track starts or resumes.
64*ec779b8eSAndroid Build Coastguard Worker      */
startClient(audio_io_handle_t streamId,audio_port_handle_t portId,const content::AttributionSourceState & attributionSource,const audio_attributes_t & attributes,const AttributesChangedCallback * callback)65*ec779b8eSAndroid Build Coastguard Worker     error::Result<audio_attributes_t> startClient(audio_io_handle_t streamId,
66*ec779b8eSAndroid Build Coastguard Worker             audio_port_handle_t portId, const content::AttributionSourceState& attributionSource,
67*ec779b8eSAndroid Build Coastguard Worker             const audio_attributes_t& attributes,
68*ec779b8eSAndroid Build Coastguard Worker             const AttributesChangedCallback *callback __attribute__((unused))) override {
69*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s output: %d portId: %d usage: %d pid: %d package: %s",
70*ec779b8eSAndroid Build Coastguard Worker                 __func__, streamId, portId, attributes.usage, attributionSource.pid,
71*ec779b8eSAndroid Build Coastguard Worker                 attributionSource.packageName.value_or("").c_str());
72*ec779b8eSAndroid Build Coastguard Worker 
73*ec779b8eSAndroid Build Coastguard Worker         m_lookup.addTrack(streamId, portId);
74*ec779b8eSAndroid Build Coastguard Worker 
75*ec779b8eSAndroid Build Coastguard Worker         return verifyAudioAttributes(streamId, attributionSource, attributes);
76*ec779b8eSAndroid Build Coastguard Worker     };
77*ec779b8eSAndroid Build Coastguard Worker 
78*ec779b8eSAndroid Build Coastguard Worker     /**
79*ec779b8eSAndroid Build Coastguard Worker      * Indicates that some playback activity stopped on the stream.
80*ec779b8eSAndroid Build Coastguard Worker      * Called each time an audio track stops or pauses.
81*ec779b8eSAndroid Build Coastguard Worker      */
stopClient(audio_io_handle_t streamId,audio_port_handle_t portId)82*ec779b8eSAndroid Build Coastguard Worker     status_t stopClient(audio_io_handle_t streamId, audio_port_handle_t portId) override {
83*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s output: %d portId: %d", __func__, streamId, portId);
84*ec779b8eSAndroid Build Coastguard Worker 
85*ec779b8eSAndroid Build Coastguard Worker         m_lookup.removeTrack(streamId, portId);
86*ec779b8eSAndroid Build Coastguard Worker         return OK;
87*ec779b8eSAndroid Build Coastguard Worker     };
88*ec779b8eSAndroid Build Coastguard Worker 
89*ec779b8eSAndroid Build Coastguard Worker     /**
90*ec779b8eSAndroid Build Coastguard Worker      * Called to verify and update audio attributes for a track that is connected
91*ec779b8eSAndroid Build Coastguard Worker      * to the specified stream.
92*ec779b8eSAndroid Build Coastguard Worker      */
verifyAudioAttributes(audio_io_handle_t streamId,const content::AttributionSourceState & attributionSource,const audio_attributes_t & attributes)93*ec779b8eSAndroid Build Coastguard Worker     error::Result<audio_attributes_t> verifyAudioAttributes(audio_io_handle_t streamId,
94*ec779b8eSAndroid Build Coastguard Worker             const content::AttributionSourceState& attributionSource,
95*ec779b8eSAndroid Build Coastguard Worker             const audio_attributes_t& attributes) override {
96*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s output: %d usage: %d pid: %d package: %s",
97*ec779b8eSAndroid Build Coastguard Worker                 __func__, streamId, attributes.usage, attributionSource.pid,
98*ec779b8eSAndroid Build Coastguard Worker                 attributionSource.packageName.value_or("").c_str());
99*ec779b8eSAndroid Build Coastguard Worker 
100*ec779b8eSAndroid Build Coastguard Worker         audio_attributes_t attrRet = attributes;
101*ec779b8eSAndroid Build Coastguard Worker 
102*ec779b8eSAndroid Build Coastguard Worker         if (isUsageValid(attributes.usage) && isContentTypeValid(attributes.content_type)
103*ec779b8eSAndroid Build Coastguard Worker                 && areFlagsValid(attributes.flags) && m_lookup.isGameStream(streamId)) {
104*ec779b8eSAndroid Build Coastguard Worker             ALOGI("%s update usage: %d to AUDIO_USAGE_GAME for output: %d pid: %d package: %s",
105*ec779b8eSAndroid Build Coastguard Worker                     __func__, attributes.usage, streamId, attributionSource.pid,
106*ec779b8eSAndroid Build Coastguard Worker                     attributionSource.packageName.value_or("").c_str());
107*ec779b8eSAndroid Build Coastguard Worker             // Set attribute usage Game.
108*ec779b8eSAndroid Build Coastguard Worker             attrRet.usage = AUDIO_USAGE_GAME;
109*ec779b8eSAndroid Build Coastguard Worker         }
110*ec779b8eSAndroid Build Coastguard Worker 
111*ec779b8eSAndroid Build Coastguard Worker         return {attrRet};
112*ec779b8eSAndroid Build Coastguard Worker     };
113*ec779b8eSAndroid Build Coastguard Worker 
114*ec779b8eSAndroid Build Coastguard Worker  protected:
115*ec779b8eSAndroid Build Coastguard Worker     /**
116*ec779b8eSAndroid Build Coastguard Worker      * Check if attribute usage valid.
117*ec779b8eSAndroid Build Coastguard Worker      */
isUsageValid(audio_usage_t usage)118*ec779b8eSAndroid Build Coastguard Worker     bool isUsageValid(audio_usage_t usage) {
119*ec779b8eSAndroid Build Coastguard Worker         ALOGV("isUsageValid usage: %d", usage);
120*ec779b8eSAndroid Build Coastguard Worker         switch (usage) {
121*ec779b8eSAndroid Build Coastguard Worker             case AUDIO_USAGE_MEDIA:
122*ec779b8eSAndroid Build Coastguard Worker             case AUDIO_USAGE_UNKNOWN:
123*ec779b8eSAndroid Build Coastguard Worker                 return true;
124*ec779b8eSAndroid Build Coastguard Worker             default:
125*ec779b8eSAndroid Build Coastguard Worker                 break;
126*ec779b8eSAndroid Build Coastguard Worker         }
127*ec779b8eSAndroid Build Coastguard Worker         return false;
128*ec779b8eSAndroid Build Coastguard Worker     }
129*ec779b8eSAndroid Build Coastguard Worker 
isContentTypeValid(audio_content_type_t contentType)130*ec779b8eSAndroid Build Coastguard Worker     bool isContentTypeValid(audio_content_type_t contentType) {
131*ec779b8eSAndroid Build Coastguard Worker         ALOGV("isContentTypeValid contentType: %d", contentType);
132*ec779b8eSAndroid Build Coastguard Worker         switch (contentType) {
133*ec779b8eSAndroid Build Coastguard Worker             case AUDIO_CONTENT_TYPE_MUSIC:
134*ec779b8eSAndroid Build Coastguard Worker             case AUDIO_CONTENT_TYPE_MOVIE:
135*ec779b8eSAndroid Build Coastguard Worker             case AUDIO_CONTENT_TYPE_UNKNOWN:
136*ec779b8eSAndroid Build Coastguard Worker                 return true;
137*ec779b8eSAndroid Build Coastguard Worker             default:
138*ec779b8eSAndroid Build Coastguard Worker                 break;
139*ec779b8eSAndroid Build Coastguard Worker         }
140*ec779b8eSAndroid Build Coastguard Worker         return false;
141*ec779b8eSAndroid Build Coastguard Worker     }
142*ec779b8eSAndroid Build Coastguard Worker 
areFlagsValid(audio_flags_mask_t flags)143*ec779b8eSAndroid Build Coastguard Worker     bool areFlagsValid(audio_flags_mask_t flags) {
144*ec779b8eSAndroid Build Coastguard Worker         ALOGV("areFlagsValid flags: %#x", flags);
145*ec779b8eSAndroid Build Coastguard Worker         if ((flags & (AUDIO_FLAG_SCO|AUDIO_FLAG_AUDIBILITY_ENFORCED|AUDIO_FLAG_BEACON)) != 0) {
146*ec779b8eSAndroid Build Coastguard Worker             return false;
147*ec779b8eSAndroid Build Coastguard Worker         }
148*ec779b8eSAndroid Build Coastguard Worker         if ((flags & AUDIO_FLAG_LOW_LATENCY) != 0) {
149*ec779b8eSAndroid Build Coastguard Worker             return true;
150*ec779b8eSAndroid Build Coastguard Worker         }
151*ec779b8eSAndroid Build Coastguard Worker         return false;
152*ec779b8eSAndroid Build Coastguard Worker     }
153*ec779b8eSAndroid Build Coastguard Worker 
154*ec779b8eSAndroid Build Coastguard Worker  protected:
155*ec779b8eSAndroid Build Coastguard Worker     UsecaseLookup m_lookup;
156*ec779b8eSAndroid Build Coastguard Worker };
157*ec779b8eSAndroid Build Coastguard Worker 
158*ec779b8eSAndroid Build Coastguard Worker }  // namespace
159*ec779b8eSAndroid Build Coastguard Worker 
createUsecaseValidator()160*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<UsecaseValidator> createUsecaseValidator() {
161*ec779b8eSAndroid Build Coastguard Worker     return std::make_unique<UsecaseValidatorImpl>();
162*ec779b8eSAndroid Build Coastguard Worker }
163*ec779b8eSAndroid Build Coastguard Worker 
164*ec779b8eSAndroid Build Coastguard Worker }  // namespace media
165*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
166