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     /** Physical stream to logical streams mapping */
     36     private final int[][] mLogicalStreams;
     37     /** Logical stream to physical stream mapping */
     38     private final int[] mPhysicalStreamForLogicalStream;
     39 
     40     public static AudioRoutingPolicy create(Context context, int policyNumber) {
     41         final Resources res = context.getResources();
     42         String[] policies = res.getStringArray(R.array.audioRoutingPolicy);
     43         return new AudioRoutingPolicy(policies[policyNumber]);
     44     }
     45 
     46     private static int getStreamType(String str) {
     47         // no radio here as radio routing is outside android (for external module) or same as music
     48         // (for android internal module)
     49         switch (str) {
     50             case "call":
     51                 return CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL;
     52             case "media":
     53                 return CarAudioManager.CAR_AUDIO_USAGE_MUSIC;
     54             case "nav_guidance":
     55                 return CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE;
     56             case "voice_command":
     57                 return CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND;
     58             case "alarm":
     59                 return CarAudioManager.CAR_AUDIO_USAGE_ALARM;
     60             case "notification":
     61                 return CarAudioManager.CAR_AUDIO_USAGE_NOTIFICATION;
     62             case "system":
     63                 return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND;
     64             case "safety":
     65                 return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT;
     66             case "unknown":
     67                 return CarAudioManager.CAR_AUDIO_USAGE_DEFAULT;
     68         }
     69         throw new IllegalArgumentException("Wrong audioRoutingPolicy config, unknown stream type:" +
     70                 str);
     71     }
     72 
     73     private AudioRoutingPolicy(String policy) {
     74         String[] streamPolicies = policy.split("#");
     75         final int nPhysicalStreams = streamPolicies.length;
     76         mLogicalStreams = new int[nPhysicalStreams][];
     77         mPhysicalStreamForLogicalStream = new int[CarAudioManager.CAR_AUDIO_USAGE_MAX + 1];
     78         for (int i = 0; i < mPhysicalStreamForLogicalStream.length; i++) {
     79             mPhysicalStreamForLogicalStream[i] = USAGE_TYPE_INVALID;
     80         }
     81         int defaultStreamType = USAGE_TYPE_INVALID;
     82         for (String streamPolicy : streamPolicies) {
     83             String[] numberVsStreams = streamPolicy.split(":");
     84             int physicalStream = Integer.parseInt(numberVsStreams[0]);
     85             String[] logicalStreams = numberVsStreams[1].split(",");
     86             int[] logicalStreamsInt = new int[logicalStreams.length];
     87             for (int i = 0; i < logicalStreams.length; i++) {
     88                 int logicalStreamNumber = getStreamType(logicalStreams[i]);
     89                 if (logicalStreamNumber == CarAudioManager.CAR_AUDIO_USAGE_DEFAULT) {
     90                     defaultStreamType = physicalStream;
     91                 }
     92                 logicalStreamsInt[i] = logicalStreamNumber;
     93                 mPhysicalStreamForLogicalStream[logicalStreamNumber] = physicalStream;
     94             }
     95             Arrays.sort(logicalStreamsInt);
     96             mLogicalStreams[physicalStream] = logicalStreamsInt;
     97         }
     98         if (defaultStreamType == USAGE_TYPE_INVALID) {
     99             Log.e(CarLog.TAG_AUDIO, "Audio routing policy did not include unknown");
    100             defaultStreamType = 0;
    101         }
    102         for (int i = 0; i < mPhysicalStreamForLogicalStream.length; i++) {
    103             if (mPhysicalStreamForLogicalStream[i] == USAGE_TYPE_INVALID) {
    104                 if (i == CarAudioManager.CAR_AUDIO_USAGE_RADIO) {
    105                     // set radio routing to be the same as music. For external radio, this does not
    106                     // matter. For internal one, it should be the same as music.
    107                     int musicPhysicalStream =
    108                             mPhysicalStreamForLogicalStream[CarAudioManager.CAR_AUDIO_USAGE_MUSIC];
    109                     if (musicPhysicalStream == USAGE_TYPE_INVALID) {
    110                         musicPhysicalStream = defaultStreamType;
    111                     }
    112                     mPhysicalStreamForLogicalStream[i] = musicPhysicalStream;
    113                 } else {
    114                     Log.w(CarLog.TAG_AUDIO, "Audio routing policy did not cover logical stream " +
    115                             i);
    116                     mPhysicalStreamForLogicalStream[i] = defaultStreamType;
    117                 }
    118             }
    119         }
    120     }
    121 
    122     public int getPhysicalStreamsCount() {
    123         return mLogicalStreams.length;
    124     }
    125 
    126     public int[] getLogicalStreamsForPhysicalStream(int physicalStreamNumber) {
    127         return mLogicalStreams[physicalStreamNumber];
    128     }
    129 
    130     public int getPhysicalStreamForLogicalStream(int logicalStream) {
    131         return mPhysicalStreamForLogicalStream[logicalStream];
    132     }
    133 
    134     public void dump(PrintWriter writer) {
    135         writer.println("*AudioRoutingPolicy*");
    136         writer.println("**Logical Streams**");
    137         for (int i = 0; i < mLogicalStreams.length; i++) {
    138             writer.print("physical stream " + i + ":");
    139             for (int logicalStream : mLogicalStreams[i]) {
    140                 writer.print(Integer.toString(logicalStream) + ",");
    141             }
    142             writer.println("");
    143         }
    144     }
    145 }
    146