1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package com.android.cellbroadcastreceiver;
18
19import android.content.Context;
20import android.graphics.Typeface;
21import android.telephony.CellBroadcastMessage;
22import android.telephony.SmsCbCmasInfo;
23import android.telephony.SmsCbEtwsInfo;
24import android.text.Spannable;
25import android.text.SpannableStringBuilder;
26import android.text.style.StyleSpan;
27
28import com.android.cellbroadcastreceiver.CellBroadcastChannelManager.CellBroadcastChannelRange;
29
30import java.util.ArrayList;
31
32/**
33 * Returns the string resource ID's for CMAS and ETWS emergency alerts.
34 */
35public class CellBroadcastResources {
36
37    private CellBroadcastResources() {
38    }
39
40    /**
41     * Returns a styled CharSequence containing the message date/time and alert details.
42     * @param context a Context for resource string access
43     * @return a CharSequence for display in the broadcast alert dialog
44     */
45    public static CharSequence getMessageDetails(Context context, CellBroadcastMessage cbm) {
46        SpannableStringBuilder buf = new SpannableStringBuilder();
47
48        // Alert date/time
49        int start = buf.length();
50        buf.append(context.getString(R.string.delivery_time_heading));
51        int end = buf.length();
52        buf.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
53        buf.append(" ");
54        buf.append(cbm.getDateString(context));
55
56        if (cbm.isCmasMessage()) {
57            // CMAS category, response type, severity, urgency, certainty
58            appendCmasAlertDetails(context, buf, cbm.getCmasWarningInfo());
59        }
60
61        return buf;
62    }
63
64    private static void appendCmasAlertDetails(Context context, SpannableStringBuilder buf,
65            SmsCbCmasInfo cmasInfo) {
66        // CMAS category
67        int categoryId = getCmasCategoryResId(cmasInfo);
68        if (categoryId != 0) {
69            appendMessageDetail(context, buf, R.string.cmas_category_heading, categoryId);
70        }
71
72        // CMAS response type
73        int responseId = getCmasResponseResId(cmasInfo);
74        if (responseId != 0) {
75            appendMessageDetail(context, buf, R.string.cmas_response_heading, responseId);
76        }
77
78        // CMAS severity
79        int severityId = getCmasSeverityResId(cmasInfo);
80        if (severityId != 0) {
81            appendMessageDetail(context, buf, R.string.cmas_severity_heading, severityId);
82        }
83
84        // CMAS urgency
85        int urgencyId = getCmasUrgencyResId(cmasInfo);
86        if (urgencyId != 0) {
87            appendMessageDetail(context, buf, R.string.cmas_urgency_heading, urgencyId);
88        }
89
90        // CMAS certainty
91        int certaintyId = getCmasCertaintyResId(cmasInfo);
92        if (certaintyId != 0) {
93            appendMessageDetail(context, buf, R.string.cmas_certainty_heading, certaintyId);
94        }
95    }
96
97    private static void appendMessageDetail(Context context, SpannableStringBuilder buf,
98            int typeId, int valueId) {
99        if (buf.length() != 0) {
100            buf.append("\n");
101        }
102        int start = buf.length();
103        buf.append(context.getString(typeId));
104        int end = buf.length();
105        buf.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
106        buf.append(" ");
107        buf.append(context.getString(valueId));
108    }
109
110    /**
111     * Returns the string resource ID for the CMAS category.
112     * @return a string resource ID, or 0 if the CMAS category is unknown or not present
113     */
114    private static int getCmasCategoryResId(SmsCbCmasInfo cmasInfo) {
115        switch (cmasInfo.getCategory()) {
116            case SmsCbCmasInfo.CMAS_CATEGORY_GEO:
117                return R.string.cmas_category_geo;
118
119            case SmsCbCmasInfo.CMAS_CATEGORY_MET:
120                return R.string.cmas_category_met;
121
122            case SmsCbCmasInfo.CMAS_CATEGORY_SAFETY:
123                return R.string.cmas_category_safety;
124
125            case SmsCbCmasInfo.CMAS_CATEGORY_SECURITY:
126                return R.string.cmas_category_security;
127
128            case SmsCbCmasInfo.CMAS_CATEGORY_RESCUE:
129                return R.string.cmas_category_rescue;
130
131            case SmsCbCmasInfo.CMAS_CATEGORY_FIRE:
132                return R.string.cmas_category_fire;
133
134            case SmsCbCmasInfo.CMAS_CATEGORY_HEALTH:
135                return R.string.cmas_category_health;
136
137            case SmsCbCmasInfo.CMAS_CATEGORY_ENV:
138                return R.string.cmas_category_env;
139
140            case SmsCbCmasInfo.CMAS_CATEGORY_TRANSPORT:
141                return R.string.cmas_category_transport;
142
143            case SmsCbCmasInfo.CMAS_CATEGORY_INFRA:
144                return R.string.cmas_category_infra;
145
146            case SmsCbCmasInfo.CMAS_CATEGORY_CBRNE:
147                return R.string.cmas_category_cbrne;
148
149            case SmsCbCmasInfo.CMAS_CATEGORY_OTHER:
150                return R.string.cmas_category_other;
151
152            default:
153                return 0;
154        }
155    }
156
157    /**
158     * Returns the string resource ID for the CMAS response type.
159     * @return a string resource ID, or 0 if the CMAS response type is unknown or not present
160     */
161    private static int getCmasResponseResId(SmsCbCmasInfo cmasInfo) {
162        switch (cmasInfo.getResponseType()) {
163            case SmsCbCmasInfo.CMAS_RESPONSE_TYPE_SHELTER:
164                return R.string.cmas_response_shelter;
165
166            case SmsCbCmasInfo.CMAS_RESPONSE_TYPE_EVACUATE:
167                return R.string.cmas_response_evacuate;
168
169            case SmsCbCmasInfo.CMAS_RESPONSE_TYPE_PREPARE:
170                return R.string.cmas_response_prepare;
171
172            case SmsCbCmasInfo.CMAS_RESPONSE_TYPE_EXECUTE:
173                return R.string.cmas_response_execute;
174
175            case SmsCbCmasInfo.CMAS_RESPONSE_TYPE_MONITOR:
176                return R.string.cmas_response_monitor;
177
178            case SmsCbCmasInfo.CMAS_RESPONSE_TYPE_AVOID:
179                return R.string.cmas_response_avoid;
180
181            case SmsCbCmasInfo.CMAS_RESPONSE_TYPE_ASSESS:
182                return R.string.cmas_response_assess;
183
184            case SmsCbCmasInfo.CMAS_RESPONSE_TYPE_NONE:
185                return R.string.cmas_response_none;
186
187            default:
188                return 0;
189        }
190    }
191
192    /**
193     * Returns the string resource ID for the CMAS severity.
194     * @return a string resource ID, or 0 if the CMAS severity is unknown or not present
195     */
196    private static int getCmasSeverityResId(SmsCbCmasInfo cmasInfo) {
197        switch (cmasInfo.getSeverity()) {
198            case SmsCbCmasInfo.CMAS_SEVERITY_EXTREME:
199                return R.string.cmas_severity_extreme;
200
201            case SmsCbCmasInfo.CMAS_SEVERITY_SEVERE:
202                return R.string.cmas_severity_severe;
203
204            default:
205                return 0;
206        }
207    }
208
209    /**
210     * Returns the string resource ID for the CMAS urgency.
211     * @return a string resource ID, or 0 if the CMAS urgency is unknown or not present
212     */
213    private static int getCmasUrgencyResId(SmsCbCmasInfo cmasInfo) {
214        switch (cmasInfo.getUrgency()) {
215            case SmsCbCmasInfo.CMAS_URGENCY_IMMEDIATE:
216                return R.string.cmas_urgency_immediate;
217
218            case SmsCbCmasInfo.CMAS_URGENCY_EXPECTED:
219                return R.string.cmas_urgency_expected;
220
221            default:
222                return 0;
223        }
224    }
225
226    /**
227     * Returns the string resource ID for the CMAS certainty.
228     * @return a string resource ID, or 0 if the CMAS certainty is unknown or not present
229     */
230    private static int getCmasCertaintyResId(SmsCbCmasInfo cmasInfo) {
231        switch (cmasInfo.getCertainty()) {
232            case SmsCbCmasInfo.CMAS_CERTAINTY_OBSERVED:
233                return R.string.cmas_certainty_observed;
234
235            case SmsCbCmasInfo.CMAS_CERTAINTY_LIKELY:
236                return R.string.cmas_certainty_likely;
237
238            default:
239                return 0;
240        }
241    }
242
243    public static int getDialogTitleResource(Context context, CellBroadcastMessage cbm) {
244        // ETWS warning types
245        SmsCbEtwsInfo etwsInfo = cbm.getEtwsWarningInfo();
246        if (etwsInfo != null) {
247            switch (etwsInfo.getWarningType()) {
248                case SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE:
249                    return R.string.etws_earthquake_warning;
250
251                case SmsCbEtwsInfo.ETWS_WARNING_TYPE_TSUNAMI:
252                    return R.string.etws_tsunami_warning;
253
254                case SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI:
255                    return R.string.etws_earthquake_and_tsunami_warning;
256
257                case SmsCbEtwsInfo.ETWS_WARNING_TYPE_TEST_MESSAGE:
258                    return R.string.etws_test_message;
259
260                case SmsCbEtwsInfo.ETWS_WARNING_TYPE_OTHER_EMERGENCY:
261                default:
262                    return R.string.etws_other_emergency_type;
263            }
264        }
265
266        // CMAS warning types
267        SmsCbCmasInfo cmasInfo = cbm.getCmasWarningInfo();
268        if (cmasInfo != null) {
269            switch (cmasInfo.getMessageClass()) {
270                case SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT:
271                    return R.string.cmas_presidential_level_alert;
272
273                case SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT:
274                    return R.string.cmas_extreme_alert;
275
276                case SmsCbCmasInfo.CMAS_CLASS_SEVERE_THREAT:
277                    return R.string.cmas_severe_alert;
278
279                case SmsCbCmasInfo.CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY:
280                    return R.string.cmas_amber_alert;
281
282                case SmsCbCmasInfo.CMAS_CLASS_REQUIRED_MONTHLY_TEST:
283                    return R.string.cmas_required_monthly_test;
284
285                case SmsCbCmasInfo.CMAS_CLASS_CMAS_EXERCISE:
286                    return R.string.cmas_exercise_alert;
287
288                case SmsCbCmasInfo.CMAS_CLASS_OPERATOR_DEFINED_USE:
289                    return R.string.cmas_operator_defined_alert;
290
291                default:
292                    return R.string.pws_other_message_identifiers;
293            }
294        }
295
296        if (CellBroadcastAlertService.isEmergencyMessage(context, cbm)) {
297            ArrayList<CellBroadcastChannelRange> ranges = CellBroadcastChannelManager
298                    .getInstance().getCellBroadcastChannelRanges(context);
299            if (ranges != null) {
300                for (CellBroadcastChannelRange range : ranges) {
301                    if (cbm.getServiceCategory() >= range.mStartId &&
302                            cbm.getServiceCategory() <= range.mEndId) {
303                        // Apply the closest title to the specified tones.
304                        switch (range.mAlertType) {
305                            case CMAS_DEFAULT:
306                                return R.string.pws_other_message_identifiers;
307                            case ETWS_EARTHQUAKE:
308                                return R.string.etws_earthquake_warning;
309                            case ETWS_TSUNAMI:
310                                return R.string.etws_tsunami_warning;
311                            case ETWS_TEST:
312                                return R.string.etws_test_message;
313                            case ETWS_DEFAULT:
314                            case OTHER:
315                                return R.string.etws_other_emergency_type;
316                        }
317                    }
318                }
319
320            }
321            return R.string.pws_other_message_identifiers;
322        } else {
323            return R.string.cb_other_message_identifiers;
324        }
325    }
326}
327