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 package com.android.car; 17 18 import android.car.media.CarAudioManager; 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.media.AudioAttributes; 22 import android.util.Log; 23 24 import java.io.PrintWriter; 25 import java.util.Arrays; 26 27 /** 28 * Holds audio routing policy from config.xml. R.array.audioRoutingPolicy can contain 29 * multiple policies and VEHICLE_PROPERTY_AUDIO_HW_VARIANT decide which one to use. 30 */ 31 public class AudioRoutingPolicy { 32 33 private final int USAGE_TYPE_INVALID = -1; 34 35 private static final String ROUTING_POLICY_FOR_MOCKED_TEST = 36 "0:call,media,radio,unknown#1:nav_guidance,voice_command,alarm,notification,system,safety"; 37 38 /** Physical stream to logical streams mapping */ 39 private final int[][] mLogicalStreams; 40 /** Logical stream to physical stream mapping */ 41 private final int[] mPhysicalStreamForLogicalStream; 42 create(Context context, int policyNumber)43 public static AudioRoutingPolicy create(Context context, int policyNumber) { 44 final Resources res = context.getResources(); 45 String[] policies = res.getStringArray(R.array.audioRoutingPolicy); 46 String policy; 47 if (policyNumber > (policies.length - 1)) { 48 Log.e(CarLog.TAG_AUDIO, "AudioRoutingPolicy.create got wrong policy number:" + 49 policyNumber + ", num of avaiable policies:" + policies.length); 50 policy = policies[0]; 51 } else if (policyNumber < 0) { // this is special case for mocked testing. 52 policy = ROUTING_POLICY_FOR_MOCKED_TEST; 53 } else { 54 policy = policies[policyNumber]; 55 } 56 return new AudioRoutingPolicy(policy); 57 } 58 getStreamType(String str)59 private static int getStreamType(String str) { 60 switch (str) { 61 case "call": 62 return CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL; 63 case "media": 64 return CarAudioManager.CAR_AUDIO_USAGE_MUSIC; 65 case "radio": 66 return CarAudioManager.CAR_AUDIO_USAGE_RADIO; 67 case "nav_guidance": 68 return CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE; 69 case "voice_command": 70 return CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND; 71 case "alarm": 72 return CarAudioManager.CAR_AUDIO_USAGE_ALARM; 73 case "notification": 74 return CarAudioManager.CAR_AUDIO_USAGE_NOTIFICATION; 75 case "system": 76 return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND; 77 case "safety": 78 return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT; 79 case "unknown": 80 return CarAudioManager.CAR_AUDIO_USAGE_DEFAULT; 81 } 82 throw new IllegalArgumentException("Wrong audioRoutingPolicy config, unknown stream type:" + 83 str); 84 } 85 AudioRoutingPolicy(String policy)86 private AudioRoutingPolicy(String policy) { 87 String[] streamPolicies = policy.split("#"); 88 final int nPhysicalStreams = streamPolicies.length; 89 mLogicalStreams = new int[nPhysicalStreams][]; 90 mPhysicalStreamForLogicalStream = new int[CarAudioManager.CAR_AUDIO_USAGE_MAX + 1]; 91 for (int i = 0; i < mPhysicalStreamForLogicalStream.length; i++) { 92 mPhysicalStreamForLogicalStream[i] = USAGE_TYPE_INVALID; 93 } 94 int defaultStreamType = USAGE_TYPE_INVALID; 95 for (String streamPolicy : streamPolicies) { 96 String[] numberVsStreams = streamPolicy.split(":"); 97 int physicalStream = Integer.parseInt(numberVsStreams[0]); 98 String[] logicalStreams = numberVsStreams[1].split(","); 99 int[] logicalStreamsInt = new int[logicalStreams.length]; 100 for (int i = 0; i < logicalStreams.length; i++) { 101 int logicalStreamNumber = getStreamType(logicalStreams[i]); 102 if (logicalStreamNumber == CarAudioManager.CAR_AUDIO_USAGE_DEFAULT) { 103 defaultStreamType = physicalStream; 104 } 105 logicalStreamsInt[i] = logicalStreamNumber; 106 mPhysicalStreamForLogicalStream[logicalStreamNumber] = physicalStream; 107 } 108 Arrays.sort(logicalStreamsInt); 109 mLogicalStreams[physicalStream] = logicalStreamsInt; 110 } 111 if (defaultStreamType == USAGE_TYPE_INVALID) { 112 Log.e(CarLog.TAG_AUDIO, "Audio routing policy did not include unknown"); 113 defaultStreamType = 0; 114 } 115 for (int i = 0; i < mPhysicalStreamForLogicalStream.length; i++) { 116 if (mPhysicalStreamForLogicalStream[i] == USAGE_TYPE_INVALID) { 117 Log.w(CarLog.TAG_AUDIO, "Audio routing policy did not cover logical stream " + i); 118 mPhysicalStreamForLogicalStream[i] = defaultStreamType; 119 } 120 } 121 } 122 getPhysicalStreamsCount()123 public int getPhysicalStreamsCount() { 124 return mLogicalStreams.length; 125 } 126 getLogicalStreamsForPhysicalStream(int physicalStreamNumber)127 public int[] getLogicalStreamsForPhysicalStream(int physicalStreamNumber) { 128 return mLogicalStreams[physicalStreamNumber]; 129 } 130 getPhysicalStreamForLogicalStream(int logicalStream)131 public int getPhysicalStreamForLogicalStream(int logicalStream) { 132 return mPhysicalStreamForLogicalStream[logicalStream]; 133 } 134 dump(PrintWriter writer)135 public void dump(PrintWriter writer) { 136 writer.println("*AudioRoutingPolicy*"); 137 writer.println("**Logical Streams**"); 138 for (int i = 0; i < mLogicalStreams.length; i++) { 139 writer.print("physical stream " + i + ":"); 140 for (int logicalStream : mLogicalStreams[i]) { 141 writer.print(Integer.toString(logicalStream) + ","); 142 } 143 writer.println(""); 144 } 145 } 146 } 147