1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef AUDIO_DEVICE_INFO_H
16 #define AUDIO_DEVICE_INFO_H
17 
18 #include <parcel.h>
19 #include <audio_stream_info.h>
20 #include <set>
21 #include <limits>
22 #include <unordered_set>
23 
24 namespace OHOS {
25 namespace AudioStandard {
26 constexpr size_t AUDIO_DEVICE_INFO_SIZE_LIMIT = 30;
27 constexpr int32_t INVALID_GROUP_ID = -1;
28 
29 const std::string LOCAL_NETWORK_ID = "LocalDevice";
30 const std::string REMOTE_NETWORK_ID = "RemoteDevice";
31 
32 enum API_VERSION {
33     API_7 = 7,
34     API_8,
35     API_9,
36     API_10,
37     API_11,
38     API_MAX = 1000
39 };
40 
41 enum DeviceFlag {
42     /**
43      * Device flag none.
44      */
45     NONE_DEVICES_FLAG = 0,
46     /**
47      * Indicates all output audio devices.
48      */
49     OUTPUT_DEVICES_FLAG = 1,
50     /**
51      * Indicates all input audio devices.
52      */
53     INPUT_DEVICES_FLAG = 2,
54     /**
55      * Indicates all audio devices.
56      */
57     ALL_DEVICES_FLAG = 3,
58     /**
59      * Indicates all distributed output audio devices.
60      */
61     DISTRIBUTED_OUTPUT_DEVICES_FLAG = 4,
62     /**
63      * Indicates all distributed input audio devices.
64      */
65     DISTRIBUTED_INPUT_DEVICES_FLAG = 8,
66     /**
67      * Indicates all distributed audio devices.
68      */
69     ALL_DISTRIBUTED_DEVICES_FLAG = 12,
70     /**
71      * Indicates all local and distributed audio devices.
72      */
73     ALL_L_D_DEVICES_FLAG = 15,
74     /**
75      * Device flag max count.
76      */
77     DEVICE_FLAG_MAX
78 };
79 
80 enum DeviceRole {
81     /**
82      * Device role none.
83      */
84     DEVICE_ROLE_NONE = -1,
85     /**
86      * Input device role.
87      */
88     INPUT_DEVICE = 1,
89     /**
90      * Output device role.
91      */
92     OUTPUT_DEVICE = 2,
93     /**
94      * Device role max count.
95      */
96     DEVICE_ROLE_MAX
97 };
98 
99 enum DeviceType {
100     /**
101      * Indicates device type none.
102      */
103     DEVICE_TYPE_NONE = -1,
104     /**
105      * Indicates invalid device
106      */
107     DEVICE_TYPE_INVALID = 0,
108     /**
109      * Indicates a built-in earpiece device
110      */
111     DEVICE_TYPE_EARPIECE = 1,
112     /**
113      * Indicates a speaker built in a device.
114      */
115     DEVICE_TYPE_SPEAKER = 2,
116     /**
117      * Indicates a headset, which is the combination of a pair of headphones and a microphone.
118      */
119     DEVICE_TYPE_WIRED_HEADSET = 3,
120     /**
121      * Indicates a pair of wired headphones.
122      */
123     DEVICE_TYPE_WIRED_HEADPHONES = 4,
124     /**
125      * Indicates a Bluetooth device used for telephony.
126      */
127     DEVICE_TYPE_BLUETOOTH_SCO = 7,
128     /**
129      * Indicates a Bluetooth device supporting the Advanced Audio Distribution Profile (A2DP).
130      */
131     DEVICE_TYPE_BLUETOOTH_A2DP = 8,
132     /**
133      * Indicates a microphone built in a device.
134      */
135     DEVICE_TYPE_MIC = 15,
136     /**
137      * Indicates a microphone built in a device.
138      */
139     DEVICE_TYPE_WAKEUP = 16,
140     /**
141      * Indicates a microphone built in a device.
142      */
143     DEVICE_TYPE_USB_HEADSET = 22,
144     /**
145      * Indicates a display device.
146      */
147     DEVICE_TYPE_DP = 23,
148     /**
149      * Indicates a virtual remote cast device
150      */
151     DEVICE_TYPE_REMOTE_CAST = 24,
152     /**
153      * Indicates a debug sink device
154      */
155     DEVICE_TYPE_FILE_SINK = 50,
156     /**
157      * Indicates a debug source device
158      */
159     DEVICE_TYPE_FILE_SOURCE = 51,
160     /**
161      * Indicates any headset/headphone for disconnect
162      */
163     DEVICE_TYPE_EXTERN_CABLE = 100,
164     /**
165      * Indicates default device
166      */
167     DEVICE_TYPE_DEFAULT = 1000,
168     /**
169      * Indicates a usb-arm device.
170      */
171     DEVICE_TYPE_USB_ARM_HEADSET = 1001,
172     /**
173      * Indicates device type max count.
174      */
175     DEVICE_TYPE_MAX
176 };
177 
178 inline const std::unordered_set<DeviceType> INPUT_DEVICE_TYPE_SET = {
179     DeviceType::DEVICE_TYPE_WIRED_HEADSET,
180     DeviceType::DEVICE_TYPE_BLUETOOTH_SCO,
181     DeviceType::DEVICE_TYPE_MIC,
182     DeviceType::DEVICE_TYPE_WAKEUP,
183     DeviceType::DEVICE_TYPE_USB_HEADSET,
184     DeviceType::DEVICE_TYPE_USB_ARM_HEADSET,
185     DeviceType::DEVICE_TYPE_FILE_SOURCE,
186 };
187 
IsInputDevice(DeviceType deviceType)188 inline bool IsInputDevice(DeviceType deviceType)
189 {
190     return INPUT_DEVICE_TYPE_SET.count(deviceType) > 0;
191 }
192 
IsInputDevice(DeviceType deviceType,DeviceRole deviceRole)193 inline bool IsInputDevice(DeviceType deviceType, DeviceRole deviceRole)
194 {
195     // Arm usb device distinguishes input and output through device roles.
196     if (deviceType == DEVICE_TYPE_USB_ARM_HEADSET) {
197         return deviceRole == INPUT_DEVICE || deviceRole == DEVICE_ROLE_MAX;
198     } else {
199         return INPUT_DEVICE_TYPE_SET.count(deviceType) > 0;
200     }
201 }
202 
203 inline const std::unordered_set<DeviceType> OUTPUT_DEVICE_TYPE_SET = {
204     DeviceType::DEVICE_TYPE_EARPIECE,
205     DeviceType::DEVICE_TYPE_SPEAKER,
206     DeviceType::DEVICE_TYPE_WIRED_HEADSET,
207     DeviceType::DEVICE_TYPE_WIRED_HEADPHONES,
208     DeviceType::DEVICE_TYPE_BLUETOOTH_SCO,
209     DeviceType::DEVICE_TYPE_BLUETOOTH_A2DP,
210     DeviceType::DEVICE_TYPE_USB_HEADSET,
211     DeviceType::DEVICE_TYPE_DP,
212     DeviceType::DEVICE_TYPE_USB_ARM_HEADSET,
213     DeviceType::DEVICE_TYPE_FILE_SINK,
214     DeviceType::DEVICE_TYPE_REMOTE_CAST,
215 };
216 
IsOutputDevice(DeviceType deviceType)217 inline bool IsOutputDevice(DeviceType deviceType)
218 {
219     return OUTPUT_DEVICE_TYPE_SET.count(deviceType) > 0;
220 }
221 
IsOutputDevice(DeviceType deviceType,DeviceRole deviceRole)222 inline bool IsOutputDevice(DeviceType deviceType, DeviceRole deviceRole)
223 {
224     // Arm usb device distinguishes input and output through device roles.
225     if (deviceType == DEVICE_TYPE_USB_ARM_HEADSET) {
226         return deviceRole == OUTPUT_DEVICE || deviceRole == DEVICE_ROLE_MAX;
227     } else {
228         return OUTPUT_DEVICE_TYPE_SET.count(deviceType) > 0;
229     }
230 }
231 
232 enum DeviceBlockStatus {
233     DEVICE_UNBLOCKED = 0,
234     DEVICE_BLOCKED = 1,
235 };
236 
237 enum DeviceChangeType {
238     CONNECT = 0,
239     DISCONNECT = 1,
240 };
241 
242 enum DeviceVolumeType {
243     EARPIECE_VOLUME_TYPE = 0,
244     SPEAKER_VOLUME_TYPE = 1,
245     HEADSET_VOLUME_TYPE = 2,
246 };
247 
248 enum ActiveDeviceType {
249     ACTIVE_DEVICE_TYPE_NONE = -1,
250     EARPIECE = 1,
251     SPEAKER = 2,
252     BLUETOOTH_SCO = 7,
253     USB_HEADSET = 22,
254     FILE_SINK_DEVICE = 50,
255     ACTIVE_DEVICE_TYPE_MAX
256 };
257 
258 enum CommunicationDeviceType {
259     /**
260      * Speaker.
261      * @since 7
262      * @syscap SystemCapability.Multimedia.Audio.Communication
263      */
264     COMMUNICATION_SPEAKER = 2
265 };
266 
267 enum AudioDeviceManagerType {
268     DEV_MGR_UNKNOW = 0,
269     LOCAL_DEV_MGR,
270     REMOTE_DEV_MGR,
271     BLUETOOTH_DEV_MGR,
272 };
273 
274 enum AudioDevicePrivacyType {
275     TYPE_PRIVACY,
276     TYPE_PUBLIC,
277     TYPE_NEGATIVE,
278 };
279 
280 enum DeviceCategory {
281     CATEGORY_DEFAULT = 0,
282     BT_HEADPHONE = 1 << 0,
283     BT_SOUNDBOX = 1 << 1,
284     BT_CAR = 1 << 2,
285     BT_GLASSES = 1 << 3,
286     BT_WATCH = 1 << 4,
287     BT_HEARAID = 1 << 5,
288     BT_UNWEAR_HEADPHONE = 1 << 6,
289 };
290 
291 enum DeviceUsage {
292     MEDIA = 1 << 0,
293     VOICE = 1 << 1,
294     RECOGNITION = 1 << 2,
295     ALL_USAGE = (1 << 3) - 1, // Represents the bitwise OR of all the above usages.
296 };
297 
298 enum DeviceInfoUpdateCommand {
299     CATEGORY_UPDATE = 1,
300     CONNECTSTATE_UPDATE,
301     ENABLE_UPDATE,
302     EXCEPTION_FLAG_UPDATE,
303 };
304 
305 enum ConnectState {
306     CONNECTED,
307     SUSPEND_CONNECTED,
308     VIRTUAL_CONNECTED,
309     DEACTIVE_CONNECTED
310 };
311 
312 enum PreferredType {
313     AUDIO_MEDIA_RENDER = 0,
314     AUDIO_CALL_RENDER = 1,
315     AUDIO_CALL_CAPTURE = 2,
316     AUDIO_RING_RENDER = 3,
317     AUDIO_RECORD_CAPTURE = 4,
318     AUDIO_TONE_RENDER = 5,
319 };
320 
321 enum BluetoothOffloadState {
322     NO_A2DP_DEVICE = 0,
323     A2DP_NOT_OFFLOAD = 1,
324     A2DP_OFFLOAD = 2,
325 };
326 
327 struct DevicePrivacyInfo {
328     std::string deviceName;
329     DeviceType deviceType;
330     DeviceRole deviceRole;
331     DeviceCategory deviceCategory;
332     DeviceUsage deviceUsage;
333 };
334 
MarshallingSetInt32(const std::set<T> & value,Parcel & parcel)335 template<typename T> bool MarshallingSetInt32(const std::set<T> &value, Parcel &parcel)
336 {
337     size_t size = value.size();
338     if (!parcel.WriteUint64(size)) {
339         return false;
340     }
341     for (const auto &i : value) {
342         if (!parcel.WriteInt32(i)) {
343             return false;
344         }
345     }
346     return true;
347 }
348 
349 template<typename T> std::set<T> UnmarshallingSetInt32(Parcel &parcel,
350     const size_t maxSize = std::numeric_limits<size_t>::max())
351 {
352     size_t size = parcel.ReadUint64();
353     // due to security concerns, sizelimit has been imposed
354     if (size > maxSize) {
355         size = maxSize;
356     }
357 
358     std::set<T> res;
359     for (size_t i = 0; i < size; i++) {
360         res.insert(static_cast<T>(parcel.ReadInt32()));
361     }
362     return res;
363 }
364 
365 struct DeviceStreamInfo {
366     AudioEncodingType encoding = AudioEncodingType::ENCODING_PCM;
367     AudioSampleFormat format = AudioSampleFormat::INVALID_WIDTH;
368     AudioChannelLayout channelLayout  = AudioChannelLayout::CH_LAYOUT_UNKNOWN;
369     std::set<AudioSamplingRate> samplingRate;
370     std::set<AudioChannel> channels;
371 
DeviceStreamInfoDeviceStreamInfo372     DeviceStreamInfo(AudioSamplingRate samplingRate_, AudioEncodingType encoding_, AudioSampleFormat format_,
373         AudioChannel channels_) : encoding(encoding_), format(format_),
374         samplingRate({samplingRate_}), channels({channels_})
375     {}
DeviceStreamInfoDeviceStreamInfo376     DeviceStreamInfo(AudioStreamInfo audioStreamInfo) : DeviceStreamInfo(audioStreamInfo.samplingRate,
377         audioStreamInfo.encoding, audioStreamInfo.format, audioStreamInfo.channels)
378     {}
379     DeviceStreamInfo() = default;
380 
MarshallingDeviceStreamInfo381     bool Marshalling(Parcel &parcel) const
382     {
383         return parcel.WriteInt32(static_cast<int32_t>(encoding))
384             && parcel.WriteInt32(static_cast<int32_t>(format))
385             && MarshallingSetInt32(samplingRate, parcel)
386             && MarshallingSetInt32(channels, parcel);
387     }
UnmarshallingDeviceStreamInfo388     void Unmarshalling(Parcel &parcel)
389     {
390         encoding = static_cast<AudioEncodingType>(parcel.ReadInt32());
391         format = static_cast<AudioSampleFormat>(parcel.ReadInt32());
392         samplingRate = UnmarshallingSetInt32<AudioSamplingRate>(parcel, AUDIO_DEVICE_INFO_SIZE_LIMIT);
393         channels = UnmarshallingSetInt32<AudioChannel>(parcel, AUDIO_DEVICE_INFO_SIZE_LIMIT);
394     }
395 
CheckParamsDeviceStreamInfo396     bool CheckParams()
397     {
398         if (samplingRate.size() == 0) {
399             return false;
400         }
401         if (channels.size() == 0) {
402             return false;
403         }
404         return true;
405     }
406 };
407 
408 class DeviceInfo {
409 public:
410     DeviceType deviceType = DEVICE_TYPE_INVALID;
411     DeviceRole deviceRole = DEVICE_ROLE_NONE;
412     int32_t deviceId = -1;
413     int32_t channelMasks = 0;
414     int32_t channelIndexMasks = 0;
415     std::string deviceName = "";
416     std::string macAddress = "";
417     DeviceStreamInfo audioStreamInfo;
418     std::string networkId = LOCAL_NETWORK_ID;
419     std::string displayName = "";
420     int32_t interruptGroupId = 0;
421     int32_t volumeGroupId = 0;
422     bool isLowLatencyDevice = false;
423     int32_t a2dpOffloadFlag = NO_A2DP_DEVICE;
424     ConnectState connectState = CONNECTED;
425     DeviceCategory deviceCategory = CATEGORY_DEFAULT;
426 
427     DeviceInfo() = default;
428     ~DeviceInfo() = default;
Marshalling(Parcel & parcel)429     bool Marshalling(Parcel &parcel) const
430     {
431         return parcel.WriteInt32(static_cast<int32_t>(deviceType))
432             && parcel.WriteInt32(static_cast<int32_t>(deviceRole))
433             && parcel.WriteInt32(deviceId)
434             && parcel.WriteInt32(channelMasks)
435             && parcel.WriteInt32(channelIndexMasks)
436             && parcel.WriteString(deviceName)
437             && parcel.WriteString(macAddress)
438             && audioStreamInfo.Marshalling(parcel)
439             && parcel.WriteString(networkId)
440             && parcel.WriteString(displayName)
441             && parcel.WriteInt32(interruptGroupId)
442             && parcel.WriteInt32(volumeGroupId)
443             && parcel.WriteBool(isLowLatencyDevice)
444             && parcel.WriteInt32(a2dpOffloadFlag)
445             && parcel.WriteInt32(static_cast<int32_t>(deviceCategory));
446     }
Marshalling(Parcel & parcel,bool hasBTPermission,bool hasSystemPermission,int32_t apiVersion)447     bool Marshalling(Parcel &parcel, bool hasBTPermission, bool hasSystemPermission, int32_t apiVersion) const
448     {
449         DeviceType devType = deviceType;
450         int32_t devId = deviceId;
451         DeviceStreamInfo streamInfo = audioStreamInfo;
452 
453         // If api target version < 11 && does not set deviceType, fix api compatibility.
454         if (apiVersion < API_11 && (deviceType == DEVICE_TYPE_NONE || deviceType == DEVICE_TYPE_INVALID)) {
455             // DeviceType use speaker or mic instead.
456             if (deviceRole == OUTPUT_DEVICE) {
457                 devType = DEVICE_TYPE_SPEAKER;
458                 devId = 1; // 1 default speaker device id.
459             } else if (deviceRole == INPUT_DEVICE) {
460                 devType = DEVICE_TYPE_MIC;
461                 devId = 2; // 2 default mic device id.
462             }
463 
464             //If does not set sampleRates use SAMPLE_RATE_44100 instead.
465             if (streamInfo.samplingRate.empty()) {
466                 streamInfo.samplingRate.insert(SAMPLE_RATE_44100);
467             }
468             // If does not set channelCounts use STEREO instead.
469             if (streamInfo.channels.empty()) {
470                 streamInfo.channels.insert(STEREO);
471             }
472         }
473 
474         return parcel.WriteInt32(static_cast<int32_t>(devType))
475             && parcel.WriteInt32(static_cast<int32_t>(deviceRole))
476             && parcel.WriteInt32(devId)
477             && parcel.WriteInt32(channelMasks)
478             && parcel.WriteInt32(channelIndexMasks)
479             && parcel.WriteString((!hasBTPermission && (deviceType == DEVICE_TYPE_BLUETOOTH_A2DP
480                 || deviceType == DEVICE_TYPE_BLUETOOTH_SCO)) ? "" : deviceName)
481             && parcel.WriteString((!hasBTPermission && (deviceType == DEVICE_TYPE_BLUETOOTH_A2DP
482                 || deviceType == DEVICE_TYPE_BLUETOOTH_SCO)) ? "" : macAddress)
483             && streamInfo.Marshalling(parcel)
484             && parcel.WriteString(hasSystemPermission ? networkId : "")
485             && parcel.WriteString(displayName)
486             && parcel.WriteInt32(hasSystemPermission ? interruptGroupId : INVALID_GROUP_ID)
487             && parcel.WriteInt32(hasSystemPermission ? volumeGroupId : INVALID_GROUP_ID)
488             && parcel.WriteBool(isLowLatencyDevice)
489             && parcel.WriteInt32(a2dpOffloadFlag)
490             && parcel.WriteInt32(static_cast<int32_t>(deviceCategory));
491     }
Unmarshalling(Parcel & parcel)492     void Unmarshalling(Parcel &parcel)
493     {
494         deviceType = static_cast<DeviceType>(parcel.ReadInt32());
495         deviceRole = static_cast<DeviceRole>(parcel.ReadInt32());
496         deviceId = parcel.ReadInt32();
497         channelMasks = parcel.ReadInt32();
498         channelIndexMasks = parcel.ReadInt32();
499         deviceName = parcel.ReadString();
500         macAddress = parcel.ReadString();
501         audioStreamInfo.Unmarshalling(parcel);
502         networkId = parcel.ReadString();
503         displayName = parcel.ReadString();
504         interruptGroupId = parcel.ReadInt32();
505         volumeGroupId = parcel.ReadInt32();
506         isLowLatencyDevice = parcel.ReadBool();
507         a2dpOffloadFlag = parcel.ReadInt32();
508         deviceCategory = static_cast<DeviceCategory>(parcel.ReadInt32());
509     }
510 
IsSameDeviceInfo(const DeviceInfo & deviceInfo)511     bool IsSameDeviceInfo(const DeviceInfo &deviceInfo) const
512     {
513         return deviceType == deviceInfo.deviceType &&
514             deviceRole == deviceInfo.deviceRole &&
515             macAddress == deviceInfo.macAddress &&
516             networkId == deviceInfo.networkId;
517     }
518 };
519 
520 enum class AudioStreamDeviceChangeReason {
521     UNKNOWN = 0,
522     NEW_DEVICE_AVAILABLE = 1,
523     OLD_DEVICE_UNAVALIABLE = 2,
524     OVERRODE = 3
525 };
526 
527 class AudioStreamDeviceChangeReasonExt {
528 public:
529     enum class ExtEnum {
530         UNKNOWN = 0,
531         NEW_DEVICE_AVAILABLE = 1,
532         OLD_DEVICE_UNAVALIABLE = 2,
533         OVERRODE = 3,
534         MIN = 1000,
535         OLD_DEVICE_UNAVALIABLE_EXT = 1000,
536         SET_AUDIO_SCENE = 1001,
537     };
538 
AudioStreamDeviceChangeReason()539     operator AudioStreamDeviceChangeReason() const
540     {
541         if (reason_ < ExtEnum::MIN) {
542             return static_cast<AudioStreamDeviceChangeReason>(reason_);
543         } else {
544             return AudioStreamDeviceChangeReason::UNKNOWN;
545         }
546     }
547 
548     operator int() const
549     {
550         return static_cast<int>(reason_);
551     }
552 
AudioStreamDeviceChangeReasonExt(const AudioStreamDeviceChangeReason & reason)553     AudioStreamDeviceChangeReasonExt(const AudioStreamDeviceChangeReason &reason)
554         : reason_(static_cast<ExtEnum>(reason)) {}
555 
AudioStreamDeviceChangeReasonExt(const ExtEnum & reason)556     AudioStreamDeviceChangeReasonExt(const ExtEnum &reason) : reason_(reason) {}
557 
IsOldDeviceUnavaliable()558     bool IsOldDeviceUnavaliable() const
559     {
560         return reason_ == ExtEnum::OLD_DEVICE_UNAVALIABLE;
561     }
562 
IsOldDeviceUnavaliableExt()563     bool IsOldDeviceUnavaliableExt() const
564     {
565         return reason_ == ExtEnum::OLD_DEVICE_UNAVALIABLE_EXT;
566     }
567 
isOverride()568     bool isOverride() const
569     {
570         return reason_ == ExtEnum::OVERRODE;
571     }
572 
isSetAudioScene()573     bool isSetAudioScene() const
574     {
575         return reason_ == ExtEnum::SET_AUDIO_SCENE;
576     }
577 private:
578     ExtEnum reason_;
579 };
580 } // namespace AudioStandard
581 } // namespace OHOS
582 #endif // AUDIO_DEVICE_INFO_H