Home | History | Annotate | Download | only in cellbroadcastreceiver
      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