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