Home | History | Annotate | Download | only in car
      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 
     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 
     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 
     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 
    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) {
    132         return mPhysicalStreamForLogicalStream[logicalStream];
    133     }
    134 
    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