1 /* 2 * Copyright (C) 2012 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 android.telephony; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 26 import com.android.internal.telephony.uicc.IccUtils; 27 28 import java.lang.annotation.Retention; 29 import java.lang.annotation.RetentionPolicy; 30 import java.time.LocalDateTime; 31 import java.time.ZoneOffset; 32 import java.util.Arrays; 33 34 /** 35 * Contains information elements for a GSM or UMTS ETWS (Earthquake and Tsunami Warning 36 * System) warning notification. Supported values for each element are defined in 3GPP TS 23.041. 37 * 38 * {@hide} 39 */ 40 @SystemApi 41 public final class SmsCbEtwsInfo implements Parcelable { 42 43 /** ETWS warning type for earthquake. */ 44 public static final int ETWS_WARNING_TYPE_EARTHQUAKE = 0x00; 45 46 /** ETWS warning type for tsunami. */ 47 public static final int ETWS_WARNING_TYPE_TSUNAMI = 0x01; 48 49 /** ETWS warning type for earthquake and tsunami. */ 50 public static final int ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI = 0x02; 51 52 /** ETWS warning type for test messages. */ 53 public static final int ETWS_WARNING_TYPE_TEST_MESSAGE = 0x03; 54 55 /** ETWS warning type for other emergency types. */ 56 public static final int ETWS_WARNING_TYPE_OTHER_EMERGENCY = 0x04; 57 58 /** Unknown ETWS warning type. */ 59 public static final int ETWS_WARNING_TYPE_UNKNOWN = -1; 60 61 /** @hide */ 62 @Retention(RetentionPolicy.SOURCE) 63 @IntDef(prefix = {"ETWS_WARNING_TYPE_"}, 64 value = { 65 ETWS_WARNING_TYPE_EARTHQUAKE, 66 ETWS_WARNING_TYPE_TSUNAMI, 67 ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI, 68 ETWS_WARNING_TYPE_TEST_MESSAGE, 69 ETWS_WARNING_TYPE_OTHER_EMERGENCY, 70 ETWS_WARNING_TYPE_UNKNOWN, 71 }) 72 public @interface WarningType {} 73 74 /** One of the ETWS warning type constants defined in this class. */ 75 private final @WarningType int mWarningType; 76 77 /** Whether or not to activate the emergency user alert tone and vibration. */ 78 private final boolean mIsEmergencyUserAlert; 79 80 /** Whether or not to activate a popup alert. */ 81 private final boolean mIsPopupAlert; 82 83 /** Whether ETWS primary message or not/ */ 84 private final boolean mIsPrimary; 85 86 /** 87 * 50-byte security information (ETWS primary notification for GSM only). As of Release 10, 88 * 3GPP TS 23.041 states that the UE shall ignore the ETWS primary notification timestamp 89 * and digital signature if received. Therefore it is treated as a raw byte array and 90 * parceled with the broadcast intent if present, but the timestamp is only computed if an 91 * application asks for the individual components. 92 */ 93 @Nullable 94 private final byte[] mWarningSecurityInformation; 95 96 /** 97 * Create a new SmsCbEtwsInfo object with the specified values. 98 * @param warningType the type of ETWS warning 99 * @param isEmergencyUserAlert whether the warning is an emergency alert, which will activate 100 * the user alert tone and vibration 101 * @param isPopupAlert whether the warning will activate a popup alert 102 * @param isPrimary whether this is an ETWS primary message 103 * @param warningSecurityInformation 50-byte security information (for primary notifications 104 * on GSM only). 105 */ SmsCbEtwsInfo(@arningType int warningType, boolean isEmergencyUserAlert, boolean isPopupAlert, boolean isPrimary, @Nullable byte[] warningSecurityInformation)106 public SmsCbEtwsInfo(@WarningType int warningType, boolean isEmergencyUserAlert, 107 boolean isPopupAlert, 108 boolean isPrimary, @Nullable byte[] warningSecurityInformation) { 109 mWarningType = warningType; 110 mIsEmergencyUserAlert = isEmergencyUserAlert; 111 mIsPopupAlert = isPopupAlert; 112 mIsPrimary = isPrimary; 113 mWarningSecurityInformation = warningSecurityInformation; 114 } 115 116 /** Create a new SmsCbEtwsInfo object from a Parcel. */ SmsCbEtwsInfo(Parcel in)117 SmsCbEtwsInfo(Parcel in) { 118 mWarningType = in.readInt(); 119 mIsEmergencyUserAlert = (in.readInt() != 0); 120 mIsPopupAlert = (in.readInt() != 0); 121 mIsPrimary = (in.readInt() != 0); 122 mWarningSecurityInformation = in.createByteArray(); 123 } 124 125 /** 126 * Flatten this object into a Parcel. 127 * 128 * @param dest The Parcel in which the object should be written. 129 * @param flags Additional flags about how the object should be written (ignored). 130 */ 131 @Override writeToParcel(Parcel dest, int flags)132 public void writeToParcel(Parcel dest, int flags) { 133 dest.writeInt(mWarningType); 134 dest.writeInt(mIsEmergencyUserAlert ? 1 : 0); 135 dest.writeInt(mIsPopupAlert ? 1 : 0); 136 dest.writeInt(mIsPrimary ? 1 : 0); 137 dest.writeByteArray(mWarningSecurityInformation); 138 } 139 140 /** 141 * Returns the ETWS warning type. 142 * @return a warning type such as {@link #ETWS_WARNING_TYPE_EARTHQUAKE} 143 */ getWarningType()144 public @WarningType int getWarningType() { 145 return mWarningType; 146 } 147 148 /** 149 * Returns the ETWS emergency user alert flag. If the ETWS message is an emergency alert, it 150 * will activate an alert tone and vibration. 151 * @return true to notify terminal to activate emergency user alert; false otherwise 152 */ isEmergencyUserAlert()153 public boolean isEmergencyUserAlert() { 154 return mIsEmergencyUserAlert; 155 } 156 157 /** 158 * Returns the ETWS activate popup flag. 159 * @return true to notify terminal to activate display popup; false otherwise 160 */ isPopupAlert()161 public boolean isPopupAlert() { 162 return mIsPopupAlert; 163 } 164 165 /** 166 * Returns the ETWS format flag. 167 * @return true if the message is primary message, otherwise secondary message 168 */ isPrimary()169 public boolean isPrimary() { 170 return mIsPrimary; 171 } 172 173 /** 174 * Returns the Warning-Security-Information timestamp (GSM primary notifications only). 175 * As of Release 10, 3GPP TS 23.041 states that the UE shall ignore this value if received. 176 * @return a UTC timestamp in System.currentTimeMillis() format, or 0 if not present 177 */ getPrimaryNotificationTimestamp()178 public long getPrimaryNotificationTimestamp() { 179 if (mWarningSecurityInformation == null || mWarningSecurityInformation.length < 7) { 180 return 0; 181 } 182 183 int year = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[0]); 184 int month = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[1]); 185 int day = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[2]); 186 int hour = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[3]); 187 int minute = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[4]); 188 int second = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[5]); 189 190 // For the timezone, the most significant bit of the 191 // least significant nibble is the sign byte 192 // (meaning the max range of this field is 79 quarter-hours, 193 // which is more than enough) 194 195 byte tzByte = mWarningSecurityInformation[6]; 196 197 // Mask out sign bit. 198 int timezoneOffset = IccUtils.gsmBcdByteToInt((byte) (tzByte & (~0x08))); 199 200 timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset : -timezoneOffset; 201 // timezoneOffset is in quarter hours. 202 int timeZoneOffsetSeconds = timezoneOffset * 15 * 60; 203 204 LocalDateTime localDateTime = LocalDateTime.of( 205 // We only need to support years above 2000. 206 year + 2000, 207 month /* 1-12 */, 208 day, 209 hour, 210 minute, 211 second); 212 213 long epochSeconds = localDateTime.toEpochSecond(ZoneOffset.UTC) - timeZoneOffsetSeconds; 214 // Convert to milliseconds, ignore overflow. 215 return epochSeconds * 1000; 216 } 217 218 /** 219 * Returns the digital signature (GSM primary notifications only). As of Release 10, 220 * 3GPP TS 23.041 states that the UE shall ignore this value if received. 221 * @return a byte array containing a copy of the primary notification digital signature 222 */ 223 @Nullable getPrimaryNotificationSignature()224 public byte[] getPrimaryNotificationSignature() { 225 if (mWarningSecurityInformation == null || mWarningSecurityInformation.length < 50) { 226 return null; 227 } 228 return Arrays.copyOfRange(mWarningSecurityInformation, 7, 50); 229 } 230 231 @Override toString()232 public String toString() { 233 return "SmsCbEtwsInfo{warningType=" + mWarningType + ", emergencyUserAlert=" 234 + mIsEmergencyUserAlert + ", activatePopup=" + mIsPopupAlert + '}'; 235 } 236 237 /** 238 * Describe the kinds of special objects contained in the marshalled representation. 239 * @return a bitmask indicating this Parcelable contains no special objects 240 */ 241 @Override describeContents()242 public int describeContents() { 243 return 0; 244 } 245 246 /** Creator for unparcelling objects. */ 247 @NonNull 248 public static final Creator<SmsCbEtwsInfo> CREATOR = new Creator<SmsCbEtwsInfo>() { 249 @Override 250 public SmsCbEtwsInfo createFromParcel(Parcel in) { 251 return new SmsCbEtwsInfo(in); 252 } 253 254 @Override 255 public SmsCbEtwsInfo[] newArray(int size) { 256 return new SmsCbEtwsInfo[size]; 257 } 258 }; 259 } 260