blob: 9d341e207f1e2889d5de8f855880dc50fe487b21 [file] [log] [blame]
keunyoung5c7cb262015-10-19 10:47:45 -07001/*
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 */
16package com.android.car;
17
Keun-young Parke54ac272016-02-16 19:02:18 -080018import android.car.media.CarAudioManager;
keunyoung5c7cb262015-10-19 10:47:45 -070019import android.content.Context;
20import android.content.res.Resources;
keunyounga74b9ca2015-10-21 13:33:58 -070021import android.media.AudioAttributes;
keunyoung5c7cb262015-10-19 10:47:45 -070022import android.util.Log;
23
Keun-young Parke54ac272016-02-16 19:02:18 -080024import java.io.PrintWriter;
25import java.util.Arrays;
26
keunyounga74b9ca2015-10-21 13:33:58 -070027/**
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 */
keunyoung5c7cb262015-10-19 10:47:45 -070031public class AudioRoutingPolicy {
Keun-young Park5672e852016-02-09 19:53:48 -080032
33 private final int USAGE_TYPE_INVALID = -1;
keunyoung5c7cb262015-10-19 10:47:45 -070034
Keun-young Park32b63822016-08-02 11:22:29 -070035 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
keunyoung5c7cb262015-10-19 10:47:45 -070038 /** Physical stream to logical streams mapping */
39 private final int[][] mLogicalStreams;
40 /** Logical stream to physical stream mapping */
Keun-young Park5672e852016-02-09 19:53:48 -080041 private final int[] mPhysicalStreamForLogicalStream;
keunyoung5c7cb262015-10-19 10:47:45 -070042
43 public static AudioRoutingPolicy create(Context context, int policyNumber) {
44 final Resources res = context.getResources();
45 String[] policies = res.getStringArray(R.array.audioRoutingPolicy);
Keun-young Park32b63822016-08-02 11:22:29 -070046 String policy;
Keun-young Park4c6834a2016-06-28 12:58:23 -070047 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);
Keun-young Park32b63822016-08-02 11:22:29 -070050 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];
Keun-young Park4c6834a2016-06-28 12:58:23 -070055 }
Keun-young Park32b63822016-08-02 11:22:29 -070056 return new AudioRoutingPolicy(policy);
keunyoung5c7cb262015-10-19 10:47:45 -070057 }
58
59 private static int getStreamType(String str) {
60 switch (str) {
61 case "call":
Keun-young Park5672e852016-02-09 19:53:48 -080062 return CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL;
keunyoung5c7cb262015-10-19 10:47:45 -070063 case "media":
Keun-young Park5672e852016-02-09 19:53:48 -080064 return CarAudioManager.CAR_AUDIO_USAGE_MUSIC;
Keun-young Park3057ebd2016-03-28 18:12:09 -070065 case "radio":
66 return CarAudioManager.CAR_AUDIO_USAGE_RADIO;
keunyoung5c7cb262015-10-19 10:47:45 -070067 case "nav_guidance":
Keun-young Park5672e852016-02-09 19:53:48 -080068 return CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE;
keunyoung5c7cb262015-10-19 10:47:45 -070069 case "voice_command":
Keun-young Park5672e852016-02-09 19:53:48 -080070 return CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND;
keunyoung5c7cb262015-10-19 10:47:45 -070071 case "alarm":
Keun-young Park5672e852016-02-09 19:53:48 -080072 return CarAudioManager.CAR_AUDIO_USAGE_ALARM;
keunyoung5c7cb262015-10-19 10:47:45 -070073 case "notification":
Keun-young Park5672e852016-02-09 19:53:48 -080074 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;
keunyoung5c7cb262015-10-19 10:47:45 -070079 case "unknown":
Keun-young Park5672e852016-02-09 19:53:48 -080080 return CarAudioManager.CAR_AUDIO_USAGE_DEFAULT;
keunyoung5c7cb262015-10-19 10:47:45 -070081 }
82 throw new IllegalArgumentException("Wrong audioRoutingPolicy config, unknown stream type:" +
83 str);
84 }
85
86 private AudioRoutingPolicy(String policy) {
87 String[] streamPolicies = policy.split("#");
88 final int nPhysicalStreams = streamPolicies.length;
89 mLogicalStreams = new int[nPhysicalStreams][];
Keun-young Park5672e852016-02-09 19:53:48 -080090 mPhysicalStreamForLogicalStream = new int[CarAudioManager.CAR_AUDIO_USAGE_MAX + 1];
91 for (int i = 0; i < mPhysicalStreamForLogicalStream.length; i++) {
92 mPhysicalStreamForLogicalStream[i] = USAGE_TYPE_INVALID;
keunyounga74b9ca2015-10-21 13:33:58 -070093 }
Keun-young Park5672e852016-02-09 19:53:48 -080094 int defaultStreamType = USAGE_TYPE_INVALID;
keunyoung5c7cb262015-10-19 10:47:45 -070095 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]);
Keun-young Park5672e852016-02-09 19:53:48 -0800102 if (logicalStreamNumber == CarAudioManager.CAR_AUDIO_USAGE_DEFAULT) {
keunyounga74b9ca2015-10-21 13:33:58 -0700103 defaultStreamType = physicalStream;
104 }
keunyoung5c7cb262015-10-19 10:47:45 -0700105 logicalStreamsInt[i] = logicalStreamNumber;
Keun-young Park5672e852016-02-09 19:53:48 -0800106 mPhysicalStreamForLogicalStream[logicalStreamNumber] = physicalStream;
keunyoung5c7cb262015-10-19 10:47:45 -0700107 }
108 Arrays.sort(logicalStreamsInt);
109 mLogicalStreams[physicalStream] = logicalStreamsInt;
110 }
Keun-young Park5672e852016-02-09 19:53:48 -0800111 if (defaultStreamType == USAGE_TYPE_INVALID) {
keunyounga74b9ca2015-10-21 13:33:58 -0700112 Log.e(CarLog.TAG_AUDIO, "Audio routing policy did not include unknown");
113 defaultStreamType = 0;
114 }
Keun-young Park5672e852016-02-09 19:53:48 -0800115 for (int i = 0; i < mPhysicalStreamForLogicalStream.length; i++) {
116 if (mPhysicalStreamForLogicalStream[i] == USAGE_TYPE_INVALID) {
Keun-young Park3057ebd2016-03-28 18:12:09 -0700117 Log.w(CarLog.TAG_AUDIO, "Audio routing policy did not cover logical stream " + i);
118 mPhysicalStreamForLogicalStream[i] = defaultStreamType;
keunyounga74b9ca2015-10-21 13:33:58 -0700119 }
120 }
keunyoung5c7cb262015-10-19 10:47:45 -0700121 }
122
123 public int getPhysicalStreamsCount() {
124 return mLogicalStreams.length;
125 }
126
127 public int[] getLogicalStreamsForPhysicalStream(int physicalStreamNumber) {
128 return mLogicalStreams[physicalStreamNumber];
129 }
130
131 public int getPhysicalStreamForLogicalStream(int logicalStream) {
Keun-young Park5672e852016-02-09 19:53:48 -0800132 return mPhysicalStreamForLogicalStream[logicalStream];
keunyounga74b9ca2015-10-21 13:33:58 -0700133 }
134
keunyoung5c7cb262015-10-19 10:47:45 -0700135 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}