Home | History | Annotate | Download | only in cellbroadcastreceiver
      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 
     17 package com.android.cellbroadcastreceiver;
     18 
     19 import android.content.ContentValues;
     20 import android.content.Context;
     21 import android.database.Cursor;
     22 import android.os.Parcel;
     23 import android.os.Parcelable;
     24 import android.telephony.SmsCbConstants;
     25 import android.telephony.SmsCbMessage;
     26 import android.text.format.DateUtils;
     27 
     28 import com.android.internal.telephony.gsm.SmsCbHeader;
     29 
     30 /**
     31  * Application wrapper for {@link SmsCbMessage}. This is Parcelable so that
     32  * decoded broadcast message objects can be passed between running Services.
     33  * New broadcasts are received by {@link CellBroadcastReceiver},
     34  * displayed by {@link CellBroadcastAlertService}, and saved to SQLite by
     35  * {@link CellBroadcastDatabaseService}.
     36  */
     37 public class CellBroadcastMessage implements Parcelable {
     38 
     39     /** Identifier for getExtra() when adding this object to an Intent. */
     40     public static final String SMS_CB_MESSAGE_EXTRA =
     41             "com.android.cellbroadcastreceiver.SMS_CB_MESSAGE";
     42 
     43     private final int mGeographicalScope;
     44     private final int mSerialNumber;
     45     private final int mMessageCode;
     46     private final int mMessageIdentifier;
     47     private final String mLanguageCode;
     48     private final String mMessageBody;
     49     private final long mDeliveryTime;
     50     private boolean mIsRead;
     51 
     52     public CellBroadcastMessage(SmsCbMessage message) {
     53         mGeographicalScope = message.getGeographicalScope();
     54         mSerialNumber = message.getUpdateNumber();
     55         mMessageCode = message.getMessageCode();
     56         mMessageIdentifier = message.getMessageIdentifier();
     57         mLanguageCode = message.getLanguageCode();
     58         mMessageBody = message.getMessageBody();
     59         mDeliveryTime = System.currentTimeMillis();
     60         mIsRead = false;
     61     }
     62 
     63     private CellBroadcastMessage(int geoScope, int serialNumber,
     64             int messageCode, int messageId, String languageCode,
     65             String messageBody, long deliveryTime, boolean isRead) {
     66         mGeographicalScope = geoScope;
     67         mSerialNumber = serialNumber;
     68         mMessageCode = messageCode;
     69         mMessageIdentifier = messageId;
     70         mLanguageCode = languageCode;
     71         mMessageBody = messageBody;
     72         mDeliveryTime = deliveryTime;
     73         mIsRead = isRead;
     74     }
     75 
     76     /** Parcelable: no special flags. */
     77     public int describeContents() {
     78         return 0;
     79     }
     80 
     81     public void writeToParcel(Parcel out, int flags) {
     82         out.writeInt(mGeographicalScope);
     83         out.writeInt(mSerialNumber);
     84         out.writeInt(mMessageCode);
     85         out.writeInt(mMessageIdentifier);
     86         out.writeString(mLanguageCode);
     87         out.writeString(mMessageBody);
     88         out.writeLong(mDeliveryTime);
     89         out.writeInt(mIsRead ? 1 : 0);
     90     }
     91 
     92     public static final Parcelable.Creator<CellBroadcastMessage> CREATOR
     93             = new Parcelable.Creator<CellBroadcastMessage>() {
     94         public CellBroadcastMessage createFromParcel(Parcel in) {
     95             return new CellBroadcastMessage(
     96                     in.readInt(), in.readInt(),
     97                     in.readInt(), in.readInt(), in.readString(),
     98                     in.readString(), in.readLong(), (in.readInt() != 0));
     99         }
    100 
    101         public CellBroadcastMessage[] newArray(int size) {
    102             return new CellBroadcastMessage[size];
    103         }
    104     };
    105 
    106     /**
    107      * Create a CellBroadcastMessage from a row in the database.
    108      * @param cursor an open SQLite cursor pointing to the row to read
    109      * @return the new CellBroadcastMessage
    110      */
    111     public static CellBroadcastMessage createFromCursor(Cursor cursor) {
    112         int geoScope = cursor.getInt(CellBroadcastDatabase.COLUMN_GEOGRAPHICAL_SCOPE);
    113         int serialNum = cursor.getInt(CellBroadcastDatabase.COLUMN_SERIAL_NUMBER);
    114         int messageCode = cursor.getInt(CellBroadcastDatabase.COLUMN_MESSAGE_CODE);
    115         int messageId = cursor.getInt(CellBroadcastDatabase.COLUMN_MESSAGE_IDENTIFIER);
    116         String language = cursor.getString(CellBroadcastDatabase.COLUMN_LANGUAGE_CODE);
    117         String body = cursor.getString(CellBroadcastDatabase.COLUMN_MESSAGE_BODY);
    118         long deliveryTime = cursor.getLong(CellBroadcastDatabase.COLUMN_DELIVERY_TIME);
    119         boolean isRead = (cursor.getInt(CellBroadcastDatabase.COLUMN_MESSAGE_READ) != 0);
    120         return new CellBroadcastMessage(geoScope, serialNum, messageCode, messageId,
    121                 language, body, deliveryTime, isRead);
    122     }
    123 
    124     /**
    125      * Return a ContentValues object for insertion into the database.
    126      * @return a new ContentValues object containing this object's data
    127      */
    128     public ContentValues getContentValues() {
    129         ContentValues cv = new ContentValues(8);
    130         cv.put(CellBroadcastDatabase.Columns.GEOGRAPHICAL_SCOPE, mGeographicalScope);
    131         cv.put(CellBroadcastDatabase.Columns.SERIAL_NUMBER, mSerialNumber);
    132         cv.put(CellBroadcastDatabase.Columns.MESSAGE_CODE, mMessageCode);
    133         cv.put(CellBroadcastDatabase.Columns.MESSAGE_IDENTIFIER, mMessageIdentifier);
    134         cv.put(CellBroadcastDatabase.Columns.LANGUAGE_CODE, mLanguageCode);
    135         cv.put(CellBroadcastDatabase.Columns.MESSAGE_BODY, mMessageBody);
    136         cv.put(CellBroadcastDatabase.Columns.DELIVERY_TIME, mDeliveryTime);
    137         cv.put(CellBroadcastDatabase.Columns.MESSAGE_READ, mIsRead);
    138         return cv;
    139     }
    140 
    141     /**
    142      * Set or clear the "read message" flag.
    143      * @param isRead true if the message has been read; false if not
    144      */
    145     public void setIsRead(boolean isRead) {
    146         mIsRead = isRead;
    147     }
    148 
    149     public int getGeographicalScope() {
    150         return mGeographicalScope;
    151     }
    152 
    153     public int getSerialNumber() {
    154         return mSerialNumber;
    155     }
    156 
    157     public int getMessageCode() {
    158         return mMessageCode;
    159     }
    160 
    161     public int getMessageIdentifier() {
    162         return mMessageIdentifier;
    163     }
    164 
    165     public String getLanguageCode() {
    166         return mLanguageCode;
    167     }
    168 
    169     public long getDeliveryTime() {
    170         return mDeliveryTime;
    171     }
    172 
    173     public String getMessageBody() {
    174         return mMessageBody;
    175     }
    176 
    177     public boolean isRead() {
    178         return mIsRead;
    179     }
    180 
    181     /**
    182      * Return whether the broadcast is an emergency (PWS) message type.
    183      * This includes lower priority test messages and Amber alerts.
    184      *
    185      * All public alerts show the flashing warning icon in the dialog,
    186      * but only emergency alerts play the alert sound and speak the message.
    187      *
    188      * @return true if the message is PWS type; false otherwise
    189      */
    190     public boolean isPublicAlertMessage() {
    191         return SmsCbHeader.isEmergencyMessage(mMessageIdentifier);
    192     }
    193 
    194     /**
    195      * Returns whether the broadcast is an emergency (PWS) message type,
    196      * including test messages, but excluding lower priority Amber alert broadcasts.
    197      *
    198      * @return true if the message is PWS type, excluding Amber alerts
    199      */
    200     public boolean isEmergencyAlertMessage() {
    201         int id = mMessageIdentifier;
    202         return SmsCbHeader.isEmergencyMessage(id) &&
    203                 id != SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY;
    204     }
    205 
    206     /**
    207      * Return whether the broadcast is an ETWS emergency message type.
    208      * @return true if the message is ETWS emergency type; false otherwise
    209      */
    210     public boolean isEtwsMessage() {
    211         return SmsCbHeader.isEtwsMessage(mMessageIdentifier);
    212     }
    213 
    214     /**
    215      * Return whether the broadcast is a CMAS emergency message type.
    216      * @return true if the message is CMAS emergency type; false otherwise
    217      */
    218     public boolean isCmasMessage() {
    219         return SmsCbHeader.isCmasMessage(mMessageIdentifier);
    220     }
    221 
    222     /**
    223      * Return whether the broadcast is an ETWS popup alert.
    224      * This method checks the message ID and the message code.
    225      * @return true if the message indicates an ETWS popup alert
    226      */
    227     public boolean isEtwsPopupAlert() {
    228         return SmsCbHeader.isEtwsMessage(mMessageIdentifier) &&
    229                 SmsCbHeader.isEtwsPopupAlert(mMessageCode);
    230     }
    231 
    232     /**
    233      * Return whether the broadcast is an ETWS emergency user alert.
    234      * This method checks the message ID and the message code.
    235      * @return true if the message indicates an ETWS emergency user alert
    236      */
    237     public boolean isEtwsEmergencyUserAlert() {
    238         return SmsCbHeader.isEtwsMessage(mMessageIdentifier) &&
    239                 SmsCbHeader.isEtwsEmergencyUserAlert(mMessageCode);
    240     }
    241 
    242     public int getDialogTitleResource() {
    243         switch (mMessageIdentifier) {
    244             case SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_WARNING:
    245                 return R.string.etws_earthquake_warning;
    246 
    247             case SmsCbConstants.MESSAGE_ID_ETWS_TSUNAMI_WARNING:
    248                 return R.string.etws_tsunami_warning;
    249 
    250             case SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_AND_TSUNAMI_WARNING:
    251                 return R.string.etws_earthquake_and_tsunami_warning;
    252 
    253             case SmsCbConstants.MESSAGE_ID_ETWS_TEST_MESSAGE:
    254                 return R.string.etws_test_message;
    255 
    256             case SmsCbConstants.MESSAGE_ID_ETWS_OTHER_EMERGENCY_TYPE:
    257                 return R.string.etws_other_emergency_type;
    258 
    259             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL:
    260                 return R.string.cmas_presidential_level_alert;
    261 
    262             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED:
    263             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY:
    264             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED:
    265             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY:
    266                 return R.string.cmas_extreme_alert;
    267 
    268             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED:
    269             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY:
    270             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED:
    271             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY:
    272                 return R.string.cmas_severe_alert;
    273 
    274             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY:
    275                 return R.string.cmas_amber_alert;
    276 
    277             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST:
    278                 return R.string.cmas_required_monthly_test;
    279 
    280             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXERCISE:
    281                 return R.string.cmas_exercise_alert;
    282 
    283             case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE:
    284                 return R.string.cmas_operator_defined_alert;
    285 
    286             default:
    287                 if (SmsCbHeader.isEmergencyMessage(mMessageIdentifier) ||
    288                         CellBroadcastConfigService.isOperatorDefinedEmergencyId(
    289                                 mMessageIdentifier)) {
    290                     return R.string.pws_other_message_identifiers;
    291                 } else {
    292                     return R.string.cb_other_message_identifiers;
    293                 }
    294         }
    295     }
    296 
    297     /**
    298      * Return the abbreviated date string for the message delivery time.
    299      * @param context the context object
    300      * @return a String to use in the broadcast list UI
    301      */
    302     String getDateString(Context context) {
    303         int flags = DateUtils.FORMAT_NO_NOON_MIDNIGHT | DateUtils.FORMAT_SHOW_TIME |
    304                 DateUtils.FORMAT_ABBREV_ALL | DateUtils.FORMAT_SHOW_DATE |
    305                 DateUtils.FORMAT_CAP_AMPM;
    306         return DateUtils.formatDateTime(context, mDeliveryTime, flags);
    307     }
    308 
    309     /**
    310      * Return the date string for the message delivery time, suitable for text-to-speech.
    311      * @param context the context object
    312      * @return a String for populating the list item AccessibilityEvent for TTS
    313      */
    314     String getSpokenDateString(Context context) {
    315         int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE;
    316         return DateUtils.formatDateTime(context, mDeliveryTime, flags);
    317     }
    318 }
    319