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 = "CellBroadcastOtherChannelsManager";
     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 
     60         private static final String KEY_TYPE = "type";
     61         private static final String KEY_EMERGENCY = "emergency";
     62 
     63         public int mStartId;
     64         public int mEndId;
     65         public ToneType mToneType;
     66         public boolean mIsEmergency;
     67 
     68         public CellBroadcastChannelRange(String channelRange) throws Exception {
     69 
     70             mToneType = ToneType.CMAS_DEFAULT;
     71             mIsEmergency = false;
     72 
     73             int colonIndex = channelRange.indexOf(':');
     74             if (colonIndex != -1){
     75                 // Parse the tone type and emergency flag
     76                 String[] pairs = channelRange.substring(colonIndex + 1).trim().split(",");
     77                 for (String pair : pairs) {
     78                     pair = pair.trim();
     79                     String[] tokens = pair.split("=");
     80                     if (tokens.length == 2) {
     81                         String key = tokens[0].trim();
     82                         String value = tokens[1].trim();
     83                         switch (key) {
     84                             case KEY_TYPE:
     85                                 mToneType = ToneType.valueOf(value.toUpperCase());
     86                                 break;
     87                             case KEY_EMERGENCY:
     88                                 mIsEmergency = value.equalsIgnoreCase("true");
     89                                 break;
     90                         }
     91                     }
     92                 }
     93                 channelRange = channelRange.substring(0, colonIndex).trim();
     94             }
     95 
     96             // Parse the channel range
     97             int dashIndex = channelRange.indexOf('-');
     98             if (dashIndex != -1) {
     99                 // range that has start id and end id
    100                 mStartId = Integer.decode(channelRange.substring(0, dashIndex).trim());
    101                 mEndId = Integer.decode(channelRange.substring(dashIndex + 1).trim());
    102             } else {
    103                 // Not a range, only a single id
    104                 mStartId = mEndId = Integer.decode(channelRange);
    105             }
    106         }
    107     }
    108 
    109     /**
    110      * Get the instance of the cell broadcast other channel manager
    111      * @return The singleton instance
    112      */
    113     public static CellBroadcastOtherChannelsManager getInstance() {
    114         if (sInstance == null) {
    115             sInstance = new CellBroadcastOtherChannelsManager();
    116         }
    117         return sInstance;
    118     }
    119 
    120     /**
    121      * Get cell broadcast channels enabled by the carriers.
    122      * @param context Application context
    123      * @param subId Subscription id
    124      * @return The list of channel ranges enabled by the carriers.
    125      */
    126      public ArrayList<CellBroadcastChannelRange> getCellBroadcastChannelRanges(
    127             Context context, int subId) {
    128 
    129         // Check if the cache already had it.
    130         if (sChannelRanges.get(subId) == null) {
    131 
    132             if (context == null) {
    133                 loge("context is null");
    134                 return null;
    135             }
    136 
    137             ArrayList<CellBroadcastChannelRange> result = new ArrayList<>();
    138             String[] ranges;
    139             CarrierConfigManager configManager =
    140                     (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
    141 
    142             if (configManager != null) {
    143                 PersistableBundle carrierConfig = configManager.getConfigForSubId(subId);
    144 
    145                 if (carrierConfig != null) {
    146                     ranges = carrierConfig.getStringArray(
    147                             CarrierConfigManager.KEY_CARRIER_ADDITIONAL_CBS_CHANNELS_STRINGS);
    148 
    149                     if (ranges == null || ranges.length == 0) {
    150                         log("No additional channels configured. subId = " + subId);
    151 
    152                         // If there is nothing configured, store an empty list in the cache
    153                         // so we won't look up again next time.
    154                         sChannelRanges.put(subId, result);
    155                         return result;
    156                     }
    157 
    158                     for (String range : ranges) {
    159                         try {
    160                             result.add(new CellBroadcastChannelRange(range));
    161                         } catch (Exception e) {
    162                             loge("Failed to parse \"" + range + "\". e=" + e);
    163                         }
    164                     }
    165 
    166                     sChannelRanges.put(subId, result);
    167 
    168                 } else {
    169                     loge("Can't get carrier config. subId=" + subId);
    170                     return null;
    171                 }
    172             } else {
    173                 loge("Carrier config manager is not available");
    174                 return null;
    175             }
    176         }
    177 
    178         return sChannelRanges.get(subId);
    179     }
    180 
    181     private static void log(String msg) {
    182         Log.d(TAG, msg);
    183     }
    184 
    185     private static void loge(String msg) {
    186         Log.e(TAG, msg);
    187     }
    188 }
    189