1 /* 2 * Copyright (C) 2019 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 package com.android.car.audio; 17 18 19 import static android.car.media.CarAudioManager.PRIMARY_AUDIO_ZONE; 20 import static android.media.AudioDeviceInfo.TYPE_BUILTIN_MIC; 21 22 import android.media.AudioDeviceAttributes; 23 import android.util.SparseArray; 24 25 import com.android.internal.util.Preconditions; 26 27 import java.util.HashSet; 28 import java.util.List; 29 import java.util.Set; 30 31 final class CarAudioZonesValidator { CarAudioZonesValidator()32 private CarAudioZonesValidator() { 33 } 34 validate(SparseArray<CarAudioZone> carAudioZones)35 static void validate(SparseArray<CarAudioZone> carAudioZones) { 36 validateAtLeastOneZoneDefined(carAudioZones); 37 validateVolumeGroupsForEachZone(carAudioZones); 38 validateEachAddressAppearsAtMostOnce(carAudioZones); 39 validatePrimaryZoneHasInputDevice(carAudioZones); 40 } 41 validatePrimaryZoneHasInputDevice(SparseArray<CarAudioZone> carAudioZones)42 private static void validatePrimaryZoneHasInputDevice(SparseArray<CarAudioZone> carAudioZones) { 43 CarAudioZone primaryZone = carAudioZones.get(PRIMARY_AUDIO_ZONE); 44 List<AudioDeviceAttributes> devices = primaryZone.getInputAudioDevices(); 45 Preconditions.checkCollectionNotEmpty(devices, "Primary Zone Input Devices"); 46 for (int index = 0; index < devices.size(); index++) { 47 AudioDeviceAttributes device = devices.get(index); 48 if (device.getType() == TYPE_BUILTIN_MIC) { 49 return; 50 } 51 } 52 throw new RuntimeException("Primary Zone must have at least one microphone input device"); 53 } 54 validateAtLeastOneZoneDefined(SparseArray<CarAudioZone> carAudioZones)55 private static void validateAtLeastOneZoneDefined(SparseArray<CarAudioZone> carAudioZones) { 56 if (carAudioZones.size() == 0) { 57 throw new RuntimeException("At least one zone should be defined"); 58 } 59 } 60 validateVolumeGroupsForEachZone(SparseArray<CarAudioZone> carAudioZones)61 private static void validateVolumeGroupsForEachZone(SparseArray<CarAudioZone> carAudioZones) { 62 for (int i = 0; i < carAudioZones.size(); i++) { 63 CarAudioZone zone = carAudioZones.valueAt(i); 64 if (!zone.validateVolumeGroups()) { 65 throw new RuntimeException( 66 "Invalid volume groups configuration for zone " + zone.getId()); 67 } 68 } 69 } 70 validateEachAddressAppearsAtMostOnce( SparseArray<CarAudioZone> carAudioZones)71 private static void validateEachAddressAppearsAtMostOnce( 72 SparseArray<CarAudioZone> carAudioZones) { 73 Set<String> addresses = new HashSet<>(); 74 for (int i = 0; i < carAudioZones.size(); i++) { 75 CarAudioZone zone = carAudioZones.valueAt(i); 76 for (CarVolumeGroup carVolumeGroup : zone.getVolumeGroups()) { 77 for (String address : carVolumeGroup.getAddresses()) { 78 if (!addresses.add(address)) { 79 throw new RuntimeException("Device with address " 80 + address + " appears in multiple volume groups or audio zones"); 81 } 82 } 83 } 84 } 85 } 86 } 87