1 /* 2 * Copyright (C) 2015 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 #pragma once 18 19 #define __STDC_LIMIT_MACROS 20 #include <inttypes.h> 21 22 #include <sys/types.h> 23 24 #include <utils/Errors.h> 25 #include <utils/Timers.h> 26 #include <utils/KeyedVector.h> 27 #include <system/audio.h> 28 #include "AudioIODescriptorInterface.h" 29 #include "AudioPort.h" 30 #include "ClientDescriptor.h" 31 #include "DeviceDescriptor.h" 32 #include <vector> 33 34 namespace android { 35 36 class IOProfile; 37 class AudioPolicyMix; 38 class AudioPolicyClientInterface; 39 40 class ActivityTracking 41 { 42 public: 43 virtual ~ActivityTracking() = default; 44 bool isActive(uint32_t inPastMs = 0, nsecs_t sysTime = 0) const 45 { 46 if (mActivityCount > 0) { 47 return true; 48 } 49 if (inPastMs == 0) { 50 return false; 51 } 52 if (sysTime == 0) { 53 sysTime = systemTime(); 54 } 55 if (ns2ms(sysTime - mStopTime) < inPastMs) { 56 return true; 57 } 58 return false; 59 } 60 void changeActivityCount(int delta) 61 { 62 if ((delta + (int)mActivityCount) < 0) { 63 LOG_ALWAYS_FATAL("%s: invalid delta %d, refCount %d", __func__, delta, mActivityCount); 64 } 65 mActivityCount += delta; 66 if (!mActivityCount) { 67 setStopTime(systemTime()); 68 } 69 } 70 uint32_t getActivityCount() const { return mActivityCount; } 71 nsecs_t getStopTime() const { return mStopTime; } 72 void setStopTime(nsecs_t stopTime) { mStopTime = stopTime; } 73 74 virtual void dump(String8 *dst, int spaces) const 75 { 76 dst->appendFormat("%*s- ActivityCount: %d, StopTime: %" PRId64 ", ", spaces, "", 77 getActivityCount(), getStopTime()); 78 } 79 private: 80 uint32_t mActivityCount = 0; 81 nsecs_t mStopTime = 0; 82 }; 83 84 /** 85 * @brief VolumeActivity: it tracks the activity for volume policy (volume index, mute, 86 * memorize previous stop, and store mute if incompatible device with another strategy. 87 */ 88 class VolumeActivity : public ActivityTracking 89 { 90 public: 91 bool isMuted() const { return mMuteCount > 0; } 92 int getMuteCount() const { return mMuteCount; } 93 int incMuteCount() { return ++mMuteCount; } 94 int decMuteCount() { return mMuteCount > 0 ? --mMuteCount : -1; } 95 96 void dump(String8 *dst, int spaces) const override 97 { 98 ActivityTracking::dump(dst, spaces); 99 dst->appendFormat(", Volume: %.03f, MuteCount: %02d\n", mCurVolumeDb, mMuteCount); 100 } 101 void setVolume(float volumeDb) { mCurVolumeDb = volumeDb; } 102 float getVolume() const { return mCurVolumeDb; } 103 104 private: 105 int mMuteCount = 0; /**< mute request counter */ 106 float mCurVolumeDb = NAN; /**< current volume in dB. */ 107 }; 108 /** 109 * Note: volume activities shall be indexed by CurvesId if we want to allow multiple 110 * curves per volume source, inferring a mute management or volume balancing between HW and SW is 111 * done 112 */ 113 using VolumeActivities = std::map<VolumeSource, VolumeActivity>; 114 115 /** 116 * @brief The Activity class: it tracks the activity for volume policy (volume index, mute, 117 * memorize previous stop, and store mute if incompatible device with another strategy. 118 * Having this class prevents from looping on all attributes (legacy streams) of the strategy 119 */ 120 class RoutingActivity : public ActivityTracking 121 { 122 public: 123 void setMutedByDevice( bool isMuted) { mIsMutedByDevice = isMuted; } 124 bool isMutedByDevice() const { return mIsMutedByDevice; } 125 126 void dump(String8 *dst, int spaces) const override { 127 ActivityTracking::dump(dst, spaces); 128 dst->appendFormat("\n"); 129 } 130 private: 131 /** 132 * strategies muted because of incompatible device selection. 133 * See AudioPolicyManager::checkDeviceMuteStrategies() 134 */ 135 bool mIsMutedByDevice = false; 136 }; 137 using RoutingActivities = std::map<product_strategy_t, RoutingActivity>; 138 139 // descriptor for audio outputs. Used to maintain current configuration of each opened audio output 140 // and keep track of the usage of this output by each audio stream type. 141 class AudioOutputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface 142 , public ClientMapHandler<TrackClientDescriptor> 143 { 144 public: 145 AudioOutputDescriptor(const sp<AudioPort>& port, 146 AudioPolicyClientInterface *clientInterface); 147 virtual ~AudioOutputDescriptor() {} 148 149 void dump(String8 *dst) const override; 150 void log(const char* indent); 151 152 audio_port_handle_t getId() const; 153 virtual DeviceVector devices() const { return mDevices; } 154 bool sharesHwModuleWith(const sp<AudioOutputDescriptor>& outputDesc); 155 virtual DeviceVector supportedDevices() const { return mDevices; } 156 virtual bool isDuplicated() const { return false; } 157 virtual uint32_t latency() { return 0; } 158 virtual bool isFixedVolume(audio_devices_t device); 159 virtual bool setVolume(float volumeDb, 160 VolumeSource volumeSource, const StreamTypeVector &streams, 161 audio_devices_t device, 162 uint32_t delayMs, 163 bool force); 164 165 /** 166 * @brief setStopTime set the stop time due to the client stoppage or a re routing of this 167 * client 168 * @param client to be considered 169 * @param sysTime when the client stopped/was rerouted 170 */ 171 void setStopTime(const sp<TrackClientDescriptor>& client, nsecs_t sysTime); 172 173 /** 174 * Changes the client->active() state and the output descriptor's global active count, 175 * along with the stream active count and mActiveClients. 176 * The client must be previously added by the base class addClient(). 177 * In case of duplicating thread, client shall be added on the duplicated thread, not on the 178 * involved outputs but setClientActive will be called on all output to track strategy and 179 * active client for a given output. 180 * Active ref count of the client will be incremented/decremented through setActive API 181 */ 182 virtual void setClientActive(const sp<TrackClientDescriptor>& client, bool active); 183 184 bool isActive(uint32_t inPastMs) const; 185 bool isActive(VolumeSource volumeSource = VOLUME_SOURCE_NONE, 186 uint32_t inPastMs = 0, 187 nsecs_t sysTime = 0) const; 188 bool isAnyActive(VolumeSource volumeSourceToIgnore) const; 189 190 std::vector<VolumeSource> getActiveVolumeSources() const { 191 std::vector<VolumeSource> activeList; 192 for (const auto &iter : mVolumeActivities) { 193 if (iter.second.isActive()) { 194 activeList.push_back(iter.first); 195 } 196 } 197 return activeList; 198 } 199 uint32_t getActivityCount(VolumeSource vs) const 200 { 201 return mVolumeActivities.find(vs) != std::end(mVolumeActivities)? 202 mVolumeActivities.at(vs).getActivityCount() : 0; 203 } 204 bool isMuted(VolumeSource vs) const 205 { 206 return mVolumeActivities.find(vs) != std::end(mVolumeActivities)? 207 mVolumeActivities.at(vs).isMuted() : false; 208 } 209 int getMuteCount(VolumeSource vs) const 210 { 211 return mVolumeActivities.find(vs) != std::end(mVolumeActivities)? 212 mVolumeActivities.at(vs).getMuteCount() : 0; 213 } 214 int incMuteCount(VolumeSource vs) 215 { 216 return mVolumeActivities[vs].incMuteCount(); 217 } 218 int decMuteCount(VolumeSource vs) 219 { 220 return mVolumeActivities[vs].decMuteCount(); 221 } 222 void setCurVolume(VolumeSource vs, float volumeDb) 223 { 224 // Even if not activity for this source registered, need to create anyway 225 mVolumeActivities[vs].setVolume(volumeDb); 226 } 227 float getCurVolume(VolumeSource vs) const 228 { 229 return mVolumeActivities.find(vs) != std::end(mVolumeActivities) ? 230 mVolumeActivities.at(vs).getVolume() : NAN; 231 } 232 233 bool isStrategyActive(product_strategy_t ps, uint32_t inPastMs = 0, nsecs_t sysTime = 0) const 234 { 235 return mRoutingActivities.find(ps) != std::end(mRoutingActivities)? 236 mRoutingActivities.at(ps).isActive(inPastMs, sysTime) : false; 237 } 238 bool isStrategyMutedByDevice(product_strategy_t ps) const 239 { 240 return mRoutingActivities.find(ps) != std::end(mRoutingActivities)? 241 mRoutingActivities.at(ps).isMutedByDevice() : false; 242 } 243 void setStrategyMutedByDevice(product_strategy_t ps, bool isMuted) 244 { 245 mRoutingActivities[ps].setMutedByDevice(isMuted); 246 } 247 248 virtual void toAudioPortConfig(struct audio_port_config *dstConfig, 249 const struct audio_port_config *srcConfig = NULL) const; 250 virtual sp<AudioPort> getAudioPort() const { return mPort; } 251 virtual void toAudioPort(struct audio_port *port) const; 252 253 audio_module_handle_t getModuleHandle() const; 254 255 // implementation of AudioIODescriptorInterface 256 audio_config_base_t getConfig() const override; 257 audio_patch_handle_t getPatchHandle() const override; 258 void setPatchHandle(audio_patch_handle_t handle) override; 259 260 TrackClientVector clientsList(bool activeOnly = false, 261 product_strategy_t strategy = PRODUCT_STRATEGY_NONE, 262 bool preferredDeviceOnly = false) const; 263 264 // override ClientMapHandler to abort when removing a client when active. 265 void removeClient(audio_port_handle_t portId) override { 266 auto client = getClient(portId); 267 LOG_ALWAYS_FATAL_IF(client.get() == nullptr, 268 "%s(%d): nonexistent client portId %d", __func__, mId, portId); 269 // it is possible that when a client is removed, we could remove its 270 // associated active count by calling changeStreamActiveCount(), 271 // but that would be hiding a problem, so we log fatal instead. 272 auto clientIter = std::find(begin(mActiveClients), end(mActiveClients), client); 273 LOG_ALWAYS_FATAL_IF(clientIter != mActiveClients.end(), 274 "%s(%d) removing client portId %d which is active (count %d)", 275 __func__, mId, portId, client->getActivityCount()); 276 ClientMapHandler<TrackClientDescriptor>::removeClient(portId); 277 } 278 279 const TrackClientVector& getActiveClients() const { 280 return mActiveClients; 281 } 282 283 bool useHwGain() const 284 { 285 return !devices().isEmpty() ? devices().itemAt(0)->hasGainController() : false; 286 } 287 288 DeviceVector mDevices; /**< current devices this output is routed to */ 289 wp<AudioPolicyMix> mPolicyMix; // non NULL when used by a dynamic policy 290 291 protected: 292 const sp<AudioPort> mPort; 293 AudioPolicyClientInterface * const mClientInterface; 294 uint32_t mGlobalActiveCount = 0; // non-client-specific active count 295 audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE; 296 audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE; 297 298 // The ActiveClients shows the clients that contribute to the @VolumeSource counts 299 // and may include upstream clients from a duplicating thread. 300 // Compare with the ClientMap (mClients) which are external AudioTrack clients of the 301 // output descriptor (and do not count internal PatchTracks). 302 TrackClientVector mActiveClients; 303 304 RoutingActivities mRoutingActivities; /**< track routing activity on this ouput.*/ 305 306 VolumeActivities mVolumeActivities; /**< track volume activity on this ouput.*/ 307 }; 308 309 // Audio output driven by a software mixer in audio flinger. 310 class SwAudioOutputDescriptor: public AudioOutputDescriptor 311 { 312 public: 313 SwAudioOutputDescriptor(const sp<IOProfile>& profile, 314 AudioPolicyClientInterface *clientInterface); 315 virtual ~SwAudioOutputDescriptor() {} 316 317 void dump(String8 *dst) const override; 318 virtual DeviceVector devices() const; 319 void setDevices(const DeviceVector &devices) { mDevices = devices; } 320 bool sharesHwModuleWith(const sp<SwAudioOutputDescriptor>& outputDesc); 321 virtual DeviceVector supportedDevices() const; 322 virtual bool deviceSupportsEncodedFormats(audio_devices_t device); 323 virtual uint32_t latency(); 324 virtual bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); } 325 virtual bool isFixedVolume(audio_devices_t device); 326 sp<SwAudioOutputDescriptor> subOutput1() { return mOutput1; } 327 sp<SwAudioOutputDescriptor> subOutput2() { return mOutput2; } 328 void setClientActive(const sp<TrackClientDescriptor>& client, bool active) override; 329 void setAllClientsInactive() 330 { 331 for (const auto &client : clientsList(true)) { 332 setClientActive(client, false); 333 } 334 } 335 virtual bool setVolume(float volumeDb, 336 VolumeSource volumeSource, const StreamTypeVector &streams, 337 audio_devices_t device, 338 uint32_t delayMs, 339 bool force); 340 341 virtual void toAudioPortConfig(struct audio_port_config *dstConfig, 342 const struct audio_port_config *srcConfig = NULL) const; 343 virtual void toAudioPort(struct audio_port *port) const; 344 345 status_t open(const audio_config_t *config, 346 const DeviceVector &devices, 347 audio_stream_type_t stream, 348 audio_output_flags_t flags, 349 audio_io_handle_t *output); 350 351 // Called when a stream is about to be started 352 // Note: called before setClientActive(true); 353 status_t start(); 354 // Called after a stream is stopped. 355 // Note: called after setClientActive(false); 356 void stop(); 357 void close(); 358 status_t openDuplicating(const sp<SwAudioOutputDescriptor>& output1, 359 const sp<SwAudioOutputDescriptor>& output2, 360 audio_io_handle_t *ioHandle); 361 362 /** 363 * @brief supportsDevice 364 * @param device to be checked against 365 * @return true if the device is supported by type (for non bus / remote submix devices), 366 * true if the device is supported (both type and address) for bus / remote submix 367 * false otherwise 368 */ 369 bool supportsDevice(const sp<DeviceDescriptor> &device) const; 370 371 /** 372 * @brief supportsAllDevices 373 * @param devices to be checked against 374 * @return true if the device is weakly supported by type (e.g. for non bus / rsubmix devices), 375 * true if the device is supported (both type and address) for bus / remote submix 376 * false otherwise 377 */ 378 bool supportsAllDevices(const DeviceVector &devices) const; 379 380 /** 381 * @brief filterSupportedDevices takes a vector of devices and filters them according to the 382 * device supported by this output (the profile from which this output derives from) 383 * @param devices reference device vector to be filtered 384 * @return vector of devices filtered from the supported devices of this output (weakly or not 385 * depending on the device type) 386 */ 387 DeviceVector filterSupportedDevices(const DeviceVector &devices) const; 388 389 const sp<IOProfile> mProfile; // I/O profile this output derives from 390 audio_io_handle_t mIoHandle; // output handle 391 uint32_t mLatency; // 392 audio_output_flags_t mFlags; // 393 sp<SwAudioOutputDescriptor> mOutput1; // used by duplicated outputs: first output 394 sp<SwAudioOutputDescriptor> mOutput2; // used by duplicated outputs: second output 395 uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only) 396 audio_session_t mDirectClientSession; // session id of the direct output client 397 }; 398 399 // Audio output driven by an input device directly. 400 class HwAudioOutputDescriptor: public AudioOutputDescriptor 401 { 402 public: 403 HwAudioOutputDescriptor(const sp<SourceClientDescriptor>& source, 404 AudioPolicyClientInterface *clientInterface); 405 virtual ~HwAudioOutputDescriptor() {} 406 407 void dump(String8 *dst) const override; 408 409 virtual bool setVolume(float volumeDb, 410 VolumeSource volumeSource, const StreamTypeVector &streams, 411 audio_devices_t device, 412 uint32_t delayMs, 413 bool force); 414 415 virtual void toAudioPortConfig(struct audio_port_config *dstConfig, 416 const struct audio_port_config *srcConfig = NULL) const; 417 virtual void toAudioPort(struct audio_port *port) const; 418 419 const sp<SourceClientDescriptor> mSource; 420 421 }; 422 423 class SwAudioOutputCollection : 424 public DefaultKeyedVector< audio_io_handle_t, sp<SwAudioOutputDescriptor> > 425 { 426 public: 427 bool isActive(VolumeSource volumeSource, uint32_t inPastMs = 0) const; 428 429 /** 430 * return whether any source contributing to VolumeSource is playing remotely, override 431 * to change the definition of 432 * local/remote playback, used for instance by notification manager to not make 433 * media players lose audio focus when not playing locally 434 * For the base implementation, "remotely" means playing during screen mirroring which 435 * uses an output for playback with a non-empty, non "0" address. 436 */ 437 bool isActiveRemotely(VolumeSource volumeSource, uint32_t inPastMs = 0) const; 438 439 /** 440 * return whether any source contributing to VolumeSource is playing, but not on a "remote" 441 * device. 442 * Override to change the definition of a local/remote playback. 443 * Used for instance by policy manager to alter the speaker playback ("speaker safe" behavior) 444 * when media plays or not locally. 445 * For the base implementation, "remotely" means playing during screen mirroring. 446 */ 447 bool isActiveLocally(VolumeSource volumeSource, uint32_t inPastMs = 0) const; 448 449 /** 450 * @brief isStrategyActiveOnSameModule checks if the given strategy is active (or was active 451 * in the past) on the given output and all the outputs belonging to the same HW Module 452 * the same module than the given output 453 * @param outputDesc to be considered 454 * @param ps product strategy to be checked upon activity status 455 * @param inPastMs if 0, check currently, otherwise, check in the past 456 * @param sysTime shall be set if request is done for the past activity. 457 * @return true if an output following the strategy is active on the same module than desc, 458 * false otherwise 459 */ 460 bool isStrategyActiveOnSameModule(product_strategy_t ps, 461 const sp<SwAudioOutputDescriptor>& desc, 462 uint32_t inPastMs = 0, nsecs_t sysTime = 0) const; 463 464 /** 465 * @brief clearSessionRoutesForDevice: when a device is disconnected, and if this device has 466 * been chosen as the preferred device by any client, the policy manager shall 467 * prevent from using this device any more by clearing all the session routes involving this 468 * device. 469 * In other words, the preferred device port id of these clients will be resetted to NONE. 470 * @param disconnectedDevice device to be disconnected 471 */ 472 void clearSessionRoutesForDevice(const sp<DeviceDescriptor> &disconnectedDevice); 473 474 /** 475 * returns the A2DP output handle if it is open or 0 otherwise 476 */ 477 audio_io_handle_t getA2dpOutput() const; 478 479 /** 480 * returns true if primary HAL supports A2DP Offload 481 */ 482 bool isA2dpOffloadedOnPrimary() const; 483 484 /** 485 * returns true if A2DP is supported (either via hardware offload or software encoding) 486 */ 487 bool isA2dpSupported() const; 488 489 sp<SwAudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const; 490 491 sp<SwAudioOutputDescriptor> getPrimaryOutput() const; 492 493 /** 494 * @brief isAnyOutputActive checks if any output is active (aka playing) except the one(s) that 495 * hold the volume source to be ignored 496 * @param volumeSourceToIgnore source not to be considered in the activity detection 497 * @return true if any output is active for any volume source except the one to be ignored 498 */ 499 bool isAnyOutputActive(VolumeSource volumeSourceToIgnore) const 500 { 501 for (size_t i = 0; i < size(); i++) { 502 const sp<AudioOutputDescriptor> &outputDesc = valueAt(i); 503 if (outputDesc->isAnyActive(volumeSourceToIgnore)) { 504 return true; 505 } 506 } 507 return false; 508 } 509 510 audio_devices_t getSupportedDevices(audio_io_handle_t handle) const; 511 512 sp<SwAudioOutputDescriptor> getOutputForClient(audio_port_handle_t portId); 513 514 void dump(String8 *dst) const; 515 }; 516 517 class HwAudioOutputCollection : 518 public DefaultKeyedVector< audio_io_handle_t, sp<HwAudioOutputDescriptor> > 519 { 520 public: 521 bool isActive(VolumeSource volumeSource, uint32_t inPastMs = 0) const; 522 523 /** 524 * @brief isAnyOutputActive checks if any output is active (aka playing) except the one(s) that 525 * hold the volume source to be ignored 526 * @param volumeSourceToIgnore source not to be considered in the activity detection 527 * @return true if any output is active for any volume source except the one to be ignored 528 */ 529 bool isAnyOutputActive(VolumeSource volumeSourceToIgnore) const 530 { 531 for (size_t i = 0; i < size(); i++) { 532 const sp<AudioOutputDescriptor> &outputDesc = valueAt(i); 533 if (outputDesc->isAnyActive(volumeSourceToIgnore)) { 534 return true; 535 } 536 } 537 return false; 538 } 539 540 void dump(String8 *dst) const; 541 }; 542 543 544 } // namespace android 545