summaryrefslogtreecommitdiffstats
path: root/src/com/android/cellbroadcastreceiver/CellBroadcastOtherChannelsManager.java
blob: 9eae9aa360a9498a37eed9db75de2f806dee9463 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.cellbroadcastreceiver;

import android.content.Context;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.util.Log;
import android.util.SparseArray;

import com.android.cellbroadcastreceiver.CellBroadcastAlertAudio.ToneType;

import java.util.ArrayList;

/**
 * CellBroadcastOtherChannelsManager handles the additional cell broadcast channels that
 * carriers might enable through carrier config app.
 * Syntax: "<channel id range>:type=<tone type>"
 * For example,
 * <string-array name="carrier_additional_cbs_channels_strings" num="3">
 *     <item value="43008:type=earthquake" />
 *     <item value="0xAFEE:type=tsunami" />
 *     <item value="0xAC00-0xAFED:type=other" />
 *     <item value="1234-5678" />
 * </string-array>
 * If no tones are specified, the tone type will be set to CMAS_DEFAULT.
 */
public class CellBroadcastOtherChannelsManager {

    private static final String TAG = "CellBroadcastChannelsManager";

    private static CellBroadcastOtherChannelsManager sInstance = null;

    /**
     * Channel range caches with sub id as the key.
     */
    private static SparseArray<ArrayList<CellBroadcastChannelRange>> sChannelRanges =
            new SparseArray<>();

    /**
     * Cell broadcast channel range
     * A range is consisted by starting channel id, ending channel id, and the tone type
     */
    public static class CellBroadcastChannelRange {
        public int mStartId;
        public int mEndId;
        public ToneType mToneType;

        public CellBroadcastChannelRange(String channelRange) throws Exception {

            mToneType = ToneType.CMAS_DEFAULT;

            int colonIndex = channelRange.indexOf(':');
            if (colonIndex != -1){
                // Parse the tone type
                String[] tokens = channelRange.substring(colonIndex + 1).trim().split("=");
                if (tokens.length == 2 && tokens[0].trim().equalsIgnoreCase("type")) {
                    mToneType = ToneType.valueOf(tokens[1].trim().toUpperCase());
                }
                channelRange = channelRange.substring(0, colonIndex).trim();
            }

            // Parse the channel range
            int dashIndex = channelRange.indexOf('-');
            if (dashIndex != -1) {
                // range that has start id and end id
                mStartId = Integer.decode(channelRange.substring(0, dashIndex).trim());
                mEndId = Integer.decode(channelRange.substring(dashIndex + 1).trim());
            } else {
                // Not a range, only a single id
                mStartId = mEndId = Integer.decode(channelRange);
            }
        }
    }

    /**
     * Get the instance of the cell broadcast other channel manager
     * @return The singleton instance
     */
    public static CellBroadcastOtherChannelsManager getInstance() {
        if (sInstance == null) {
            sInstance = new CellBroadcastOtherChannelsManager();
        }
        return sInstance;
    }

    /**
     * Get cell broadcast channels enabled by the carriers.
     * @param context Application context
     * @param subId Subscription id
     * @return The list of channel ranges enabled by the carriers.
     */
     public ArrayList<CellBroadcastChannelRange> getCellBroadcastChannelRanges(
            Context context, int subId) {

        // Check if the cache already had it.
        if (sChannelRanges.get(subId) == null) {

            ArrayList<CellBroadcastChannelRange> result = new ArrayList<>();
            String[] ranges;
            CarrierConfigManager configManager =
                    (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);

            if (configManager != null) {
                PersistableBundle carrierConfig = configManager.getConfig(subId);

                if (carrierConfig != null) {
                    ranges = carrierConfig.getStringArray(
                            CarrierConfigManager.KEY_CARRIER_ADDITIONAL_CBS_CHANNELS_STRINGS);

                    if (ranges == null || ranges.length == 0) {
                        log("No additional channels configured.");

                        // If there is nothing configured, store an empty list in the cache
                        // so we won't look up again next time.
                        sChannelRanges.put(subId, result);
                        return result;
                    }

                    for (String range : ranges) {
                        try {
                            result.add(new CellBroadcastChannelRange(range));
                        } catch (Exception e) {
                            loge("Failed to parse \"" + range + "\". e=" + e);
                        }
                    }

                    sChannelRanges.put(subId, result);

                } else {
                    loge("Can't get carrier config. subId=" + subId);
                    return null;
                }
            } else {
                loge("Carrier config manager is not available");
                return null;
            }
        }

        return sChannelRanges.get(subId);
    }

    private static void log(String msg) {
        Log.d(TAG, msg);
    }

    private static void loge(String msg) {
        Log.e(TAG, msg);
    }
}