1 /* 2 * Copyright (C) 2016 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 17 package com.android.cellbroadcastreceiver; 18 19 import android.content.Context; 20 import android.os.PersistableBundle; 21 import android.telephony.CarrierConfigManager; 22 import android.util.Log; 23 import android.util.SparseArray; 24 25 import com.android.cellbroadcastreceiver.CellBroadcastAlertAudio.ToneType; 26 27 import java.util.ArrayList; 28 29 /** 30 * CellBroadcastOtherChannelsManager handles the additional cell broadcast channels that 31 * carriers might enable through carrier config app. 32 * Syntax: "<channel id range>:type=<tone type>" 33 * For example, 34 * <string-array name="carrier_additional_cbs_channels_strings" num="3"> 35 * <item value="43008:type=earthquake" /> 36 * <item value="0xAFEE:type=tsunami" /> 37 * <item value="0xAC00-0xAFED:type=other" /> 38 * <item value="1234-5678" /> 39 * </string-array> 40 * If no tones are specified, the tone type will be set to CMAS_DEFAULT. 41 */ 42 public class CellBroadcastOtherChannelsManager { 43 44 private static final String TAG = "CellBroadcastChannelsManager"; 45 46 private static CellBroadcastOtherChannelsManager sInstance = null; 47 48 /** 49 * Channel range caches with sub id as the key. 50 */ 51 private static SparseArray<ArrayList<CellBroadcastChannelRange>> sChannelRanges = 52 new SparseArray<>(); 53 54 /** 55 * Cell broadcast channel range 56 * A range is consisted by starting channel id, ending channel id, and the tone type 57 */ 58 public static class CellBroadcastChannelRange { 59 public int mStartId; 60 public int mEndId; 61 public ToneType mToneType; 62 63 public CellBroadcastChannelRange(String channelRange) throws Exception { 64 65 mToneType = ToneType.CMAS_DEFAULT; 66 67 int colonIndex = channelRange.indexOf(':'); 68 if (colonIndex != -1){ 69 // Parse the tone type 70 String[] tokens = channelRange.substring(colonIndex + 1).trim().split("="); 71 if (tokens.length == 2 && tokens[0].trim().equalsIgnoreCase("type")) { 72 mToneType = ToneType.valueOf(tokens[1].trim().toUpperCase()); 73 } 74 channelRange = channelRange.substring(0, colonIndex).trim(); 75 } 76 77 // Parse the channel range 78 int dashIndex = channelRange.indexOf('-'); 79 if (dashIndex != -1) { 80 // range that has start id and end id 81 mStartId = Integer.decode(channelRange.substring(0, dashIndex).trim()); 82 mEndId = Integer.decode(channelRange.substring(dashIndex + 1).trim()); 83 } else { 84 // Not a range, only a single id 85 mStartId = mEndId = Integer.decode(channelRange); 86 } 87 } 88 } 89 90 /** 91 * Get the instance of the cell broadcast other channel manager 92 * @return The singleton instance 93 */ 94 public static CellBroadcastOtherChannelsManager getInstance() { 95 if (sInstance == null) { 96 sInstance = new CellBroadcastOtherChannelsManager(); 97 } 98 return sInstance; 99 } 100 101 /** 102 * Get cell broadcast channels enabled by the carriers. 103 * @param context Application context 104 * @param subId Subscription id 105 * @return The list of channel ranges enabled by the carriers. 106 */ 107 public ArrayList<CellBroadcastChannelRange> getCellBroadcastChannelRanges( 108 Context context, int subId) { 109 110 // Check if the cache already had it. 111 if (sChannelRanges.get(subId) == null) { 112 113 ArrayList<CellBroadcastChannelRange> result = new ArrayList<>(); 114 String[] ranges; 115 CarrierConfigManager configManager = 116 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); 117 118 if (configManager != null) { 119 PersistableBundle carrierConfig = configManager.getConfigForSubId(subId); 120 121 if (carrierConfig != null) { 122 ranges = carrierConfig.getStringArray( 123 CarrierConfigManager.KEY_CARRIER_ADDITIONAL_CBS_CHANNELS_STRINGS); 124 125 if (ranges == null || ranges.length == 0) { 126 log("No additional channels configured."); 127 128 // If there is nothing configured, store an empty list in the cache 129 // so we won't look up again next time. 130 sChannelRanges.put(subId, result); 131 return result; 132 } 133 134 for (String range : ranges) { 135 try { 136 result.add(new CellBroadcastChannelRange(range)); 137 } catch (Exception e) { 138 loge("Failed to parse \"" + range + "\". e=" + e); 139 } 140 } 141 142 sChannelRanges.put(subId, result); 143 144 } else { 145 loge("Can't get carrier config. subId=" + subId); 146 return null; 147 } 148 } else { 149 loge("Carrier config manager is not available"); 150 return null; 151 } 152 } 153 154 return sChannelRanges.get(subId); 155 } 156 157 private static void log(String msg) { 158 Log.d(TAG, msg); 159 } 160 161 private static void loge(String msg) { 162 Log.e(TAG, msg); 163 } 164 } 165