Loading telephony/java/android/provider/Telephony.java +21 −1 Original line number Diff line number Diff line Loading @@ -3961,6 +3961,13 @@ public final class Telephony { @NonNull public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts"); /** * The id of the subscription which received this cell broadcast message. * <P>Type: INTEGER</P> * @hide */ public static final String SUB_ID = "sub_id"; /** * Message geographical scope. Valid values are: * <ul> Loading Loading @@ -4182,6 +4189,18 @@ public final class Telephony { */ public static final String GEOMETRIES = "geometries"; /** * Geo-Fencing Maximum Wait Time in second. The range of the time is [0, 255]. A device * shall allow to determine its position meeting operator policy. If the device is unable to * determine its position meeting operator policy within the GeoFencing Maximum Wait Time, * it shall present the alert to the user and discontinue further positioning determination * for the alert. * * <P>Type: INTEGER</P> * @hide */ public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time"; /** * Query columns for instantiating {@link android.telephony.CellBroadcastMessage} objects. * @hide Loading Loading @@ -4235,7 +4254,8 @@ public final class Telephony { CMAS_CERTAINTY, RECEIVED_TIME, MESSAGE_BROADCASTED, GEOMETRIES GEOMETRIES, MAXIMUM_WAIT_TIME }; } Loading telephony/java/android/telephony/SmsCbMessage.java +39 −6 Original line number Diff line number Diff line Loading @@ -139,6 +139,12 @@ public final class SmsCbMessage implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface MessagePriority {} /** * ATIS-0700041 Section 5.2.8 WAC Geo-Fencing Maximum Wait Time Table 12. * @hide */ public static final int MAXIMUM_WAIT_TIME_NOT_SET = 255; /** Format of this message (for interpretation of service category values). */ private final int mMessageFormat; Loading Loading @@ -187,6 +193,14 @@ public final class SmsCbMessage implements Parcelable { @Nullable private final SmsCbCmasInfo mCmasWarningInfo; /** * Geo-Fencing Maximum Wait Time in second, a device shall allow to determine its position * meeting operator policy. If the device is unable to determine its position meeting operator * policy within the GeoFencing Maximum Wait Time, it shall present the alert to the user and * discontinue further positioning determination for the alert. */ private final int mMaximumWaitTimeSec; /** UNIX timestamp of when the message was received. */ private final long mReceivedTimeMillis; Loading @@ -202,8 +216,8 @@ public final class SmsCbMessage implements Parcelable { @Nullable SmsCbCmasInfo cmasWarningInfo) { this(messageFormat, geographicalScope, serialNumber, location, serviceCategory, language, body, priority, etwsWarningInfo, cmasWarningInfo, null /* geometries */, System.currentTimeMillis()); body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */, null /* geometries */, System.currentTimeMillis()); } /** Loading @@ -213,7 +227,7 @@ public final class SmsCbMessage implements Parcelable { public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber, SmsCbLocation location, int serviceCategory, String language, String body, int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo, List<Geometry> geometries, long receivedTimeMillis) { int maximumWaitTimeSec, List<Geometry> geometries, long receivedTimeMillis) { mMessageFormat = messageFormat; mGeographicalScope = geographicalScope; mSerialNumber = serialNumber; Loading @@ -226,6 +240,7 @@ public final class SmsCbMessage implements Parcelable { mCmasWarningInfo = cmasWarningInfo; mReceivedTimeMillis = receivedTimeMillis; mGeometries = geometries; mMaximumWaitTimeSec = maximumWaitTimeSec; } /** Loading Loading @@ -262,6 +277,7 @@ public final class SmsCbMessage implements Parcelable { mReceivedTimeMillis = in.readLong(); String geoStr = in.readString(); mGeometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null; mMaximumWaitTimeSec = in.readInt(); } /** Loading Loading @@ -295,6 +311,7 @@ public final class SmsCbMessage implements Parcelable { dest.writeLong(mReceivedTimeMillis); dest.writeString( mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : null); dest.writeInt(mMaximumWaitTimeSec); } @NonNull Loading Loading @@ -388,6 +405,15 @@ public final class SmsCbMessage implements Parcelable { return mGeometries; } /** * Get the Geo-Fencing Maximum Wait Time. * @return the time in second. * @hide */ public int getMaximumWaitingTime() { return mMaximumWaitTimeSec; } /** * Get the time when this message was received. * @return the time in millisecond Loading Loading @@ -475,6 +501,7 @@ public final class SmsCbMessage implements Parcelable { + ", priority=" + mPriority + (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "") + (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "") + ", maximumWaitingTime = " + mMaximumWaitTimeSec + ", geo=" + (mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : "null") + '}'; Loading Loading @@ -535,6 +562,8 @@ public final class SmsCbMessage implements Parcelable { cv.put(CellBroadcasts.GEOMETRIES, (String) null); } cv.put(CellBroadcasts.MAXIMUM_WAIT_TIME, mMaximumWaitTimeSec); return cv; } Loading Loading @@ -644,17 +673,21 @@ public final class SmsCbMessage implements Parcelable { List<Geometry> geometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null; long receivedTimeSec = cursor.getLong( long receivedTimeMillis = cursor.getLong( cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME)); int maximumWaitTimeSec = cursor.getInt( cursor.getColumnIndexOrThrow(CellBroadcasts.MAXIMUM_WAIT_TIME)); return new SmsCbMessage(format, geoScope, serialNum, location, category, language, body, priority, etwsInfo, cmasInfo, geometries, receivedTimeSec); language, body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, geometries, receivedTimeMillis); } /** * @return {@code True} if this message needs geo-fencing check. */ public boolean needGeoFencingCheck() { return mGeometries != null; return mMaximumWaitTimeSec > 0 && mGeometries != null; } } telephony/java/com/android/internal/telephony/CbGeoUtils.java +2 −1 Original line number Diff line number Diff line Loading @@ -299,7 +299,8 @@ public class CbGeoUtils { * @return the encoded string. */ @NonNull public static String encodeGeometriesToString(@NonNull List<Geometry> geometries) { public static String encodeGeometriesToString(List<Geometry> geometries) { if (geometries == null || geometries.isEmpty()) return ""; return geometries.stream() .map(geometry -> encodeGeometryToString(geometry)) .filter(encodedStr -> !TextUtils.isEmpty(encodedStr)) Loading telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java +24 −8 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ public class GsmSmsCbMessage { header.getSerialNumber(), location, header.getServiceCategory(), null, getEtwsPrimaryMessage(context, header.getEtwsInfo().getWarningType()), SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, header.getEtwsInfo(), header.getCmasInfo(), null /* geometries */, receivedTimeMillis); header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis); } else if (header.isUmtsFormat()) { // UMTS format has only 1 PDU byte[] pdu = pdus[0]; Loading @@ -120,9 +120,13 @@ public class GsmSmsCbMessage { // Has Warning Area Coordinates information List<Geometry> geometries = null; int maximumWaitingTimeSec = 255; if (pdu.length > wacDataOffset) { try { geometries = parseWarningAreaCoordinates(pdu, wacDataOffset); Pair<Integer, List<Geometry>> wac = parseWarningAreaCoordinates(pdu, wacDataOffset); maximumWaitingTimeSec = wac.first; geometries = wac.second; } catch (Exception ex) { // Catch the exception here, the message will be considered as having no WAC // information which means the message will be broadcasted directly. Loading @@ -133,7 +137,8 @@ public class GsmSmsCbMessage { return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP, header.getGeographicalScope(), header.getSerialNumber(), location, header.getServiceCategory(), language, body, priority, header.getEtwsInfo(), header.getCmasInfo(), geometries, receivedTimeMillis); header.getEtwsInfo(), header.getCmasInfo(), maximumWaitingTimeSec, geometries, receivedTimeMillis); } else { String language = null; StringBuilder sb = new StringBuilder(); Loading @@ -148,7 +153,7 @@ public class GsmSmsCbMessage { return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP, header.getGeographicalScope(), header.getSerialNumber(), location, header.getServiceCategory(), language, sb.toString(), priority, header.getEtwsInfo(), header.getCmasInfo(), null /* geometries */, header.getEtwsInfo(), header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis); } } Loading Loading @@ -197,7 +202,17 @@ public class GsmSmsCbMessage { } } private static List<Geometry> parseWarningAreaCoordinates(byte[] pdu, int wacOffset) { /** * Parse the broadcast area and maximum wait time from the Warning Area Coordinates TLV. * * @param pdu Warning Area Coordinates TLV. * @param wacOffset the offset of Warning Area Coordinates TLV. * @return a pair with the first element is maximum wait time and the second is the broadcast * area. The default value of the maximum wait time is 255 which means use the device default * value. */ private static Pair<Integer, List<Geometry>> parseWarningAreaCoordinates( byte[] pdu, int wacOffset) { // little-endian int wacDataLength = (pdu[wacOffset + 1] << 8) | pdu[wacOffset]; int offset = wacOffset + 2; Loading @@ -209,6 +224,8 @@ public class GsmSmsCbMessage { BitStreamReader bitReader = new BitStreamReader(pdu, offset); int maximumWaitTimeSec = SmsCbMessage.MAXIMUM_WAIT_TIME_NOT_SET; List<Geometry> geo = new ArrayList<>(); int remainedBytes = wacDataLength; while (remainedBytes > 0) { Loading @@ -220,8 +237,7 @@ public class GsmSmsCbMessage { switch (type) { case CbGeoUtils.GEO_FENCING_MAXIMUM_WAIT_TIME: // TODO: handle the maximum wait time in cell broadcast provider. int maximumWaitTimeSec = bitReader.read(8); maximumWaitTimeSec = bitReader.read(8); break; case CbGeoUtils.GEOMETRY_TYPE_POLYGON: List<LatLng> latLngs = new ArrayList<>(); Loading @@ -247,7 +263,7 @@ public class GsmSmsCbMessage { throw new IllegalArgumentException("Unsupported geoType = " + type); } } return geo; return new Pair(maximumWaitTimeSec, geo); } /** Loading Loading
telephony/java/android/provider/Telephony.java +21 −1 Original line number Diff line number Diff line Loading @@ -3961,6 +3961,13 @@ public final class Telephony { @NonNull public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts"); /** * The id of the subscription which received this cell broadcast message. * <P>Type: INTEGER</P> * @hide */ public static final String SUB_ID = "sub_id"; /** * Message geographical scope. Valid values are: * <ul> Loading Loading @@ -4182,6 +4189,18 @@ public final class Telephony { */ public static final String GEOMETRIES = "geometries"; /** * Geo-Fencing Maximum Wait Time in second. The range of the time is [0, 255]. A device * shall allow to determine its position meeting operator policy. If the device is unable to * determine its position meeting operator policy within the GeoFencing Maximum Wait Time, * it shall present the alert to the user and discontinue further positioning determination * for the alert. * * <P>Type: INTEGER</P> * @hide */ public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time"; /** * Query columns for instantiating {@link android.telephony.CellBroadcastMessage} objects. * @hide Loading Loading @@ -4235,7 +4254,8 @@ public final class Telephony { CMAS_CERTAINTY, RECEIVED_TIME, MESSAGE_BROADCASTED, GEOMETRIES GEOMETRIES, MAXIMUM_WAIT_TIME }; } Loading
telephony/java/android/telephony/SmsCbMessage.java +39 −6 Original line number Diff line number Diff line Loading @@ -139,6 +139,12 @@ public final class SmsCbMessage implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface MessagePriority {} /** * ATIS-0700041 Section 5.2.8 WAC Geo-Fencing Maximum Wait Time Table 12. * @hide */ public static final int MAXIMUM_WAIT_TIME_NOT_SET = 255; /** Format of this message (for interpretation of service category values). */ private final int mMessageFormat; Loading Loading @@ -187,6 +193,14 @@ public final class SmsCbMessage implements Parcelable { @Nullable private final SmsCbCmasInfo mCmasWarningInfo; /** * Geo-Fencing Maximum Wait Time in second, a device shall allow to determine its position * meeting operator policy. If the device is unable to determine its position meeting operator * policy within the GeoFencing Maximum Wait Time, it shall present the alert to the user and * discontinue further positioning determination for the alert. */ private final int mMaximumWaitTimeSec; /** UNIX timestamp of when the message was received. */ private final long mReceivedTimeMillis; Loading @@ -202,8 +216,8 @@ public final class SmsCbMessage implements Parcelable { @Nullable SmsCbCmasInfo cmasWarningInfo) { this(messageFormat, geographicalScope, serialNumber, location, serviceCategory, language, body, priority, etwsWarningInfo, cmasWarningInfo, null /* geometries */, System.currentTimeMillis()); body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */, null /* geometries */, System.currentTimeMillis()); } /** Loading @@ -213,7 +227,7 @@ public final class SmsCbMessage implements Parcelable { public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber, SmsCbLocation location, int serviceCategory, String language, String body, int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo, List<Geometry> geometries, long receivedTimeMillis) { int maximumWaitTimeSec, List<Geometry> geometries, long receivedTimeMillis) { mMessageFormat = messageFormat; mGeographicalScope = geographicalScope; mSerialNumber = serialNumber; Loading @@ -226,6 +240,7 @@ public final class SmsCbMessage implements Parcelable { mCmasWarningInfo = cmasWarningInfo; mReceivedTimeMillis = receivedTimeMillis; mGeometries = geometries; mMaximumWaitTimeSec = maximumWaitTimeSec; } /** Loading Loading @@ -262,6 +277,7 @@ public final class SmsCbMessage implements Parcelable { mReceivedTimeMillis = in.readLong(); String geoStr = in.readString(); mGeometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null; mMaximumWaitTimeSec = in.readInt(); } /** Loading Loading @@ -295,6 +311,7 @@ public final class SmsCbMessage implements Parcelable { dest.writeLong(mReceivedTimeMillis); dest.writeString( mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : null); dest.writeInt(mMaximumWaitTimeSec); } @NonNull Loading Loading @@ -388,6 +405,15 @@ public final class SmsCbMessage implements Parcelable { return mGeometries; } /** * Get the Geo-Fencing Maximum Wait Time. * @return the time in second. * @hide */ public int getMaximumWaitingTime() { return mMaximumWaitTimeSec; } /** * Get the time when this message was received. * @return the time in millisecond Loading Loading @@ -475,6 +501,7 @@ public final class SmsCbMessage implements Parcelable { + ", priority=" + mPriority + (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "") + (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "") + ", maximumWaitingTime = " + mMaximumWaitTimeSec + ", geo=" + (mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : "null") + '}'; Loading Loading @@ -535,6 +562,8 @@ public final class SmsCbMessage implements Parcelable { cv.put(CellBroadcasts.GEOMETRIES, (String) null); } cv.put(CellBroadcasts.MAXIMUM_WAIT_TIME, mMaximumWaitTimeSec); return cv; } Loading Loading @@ -644,17 +673,21 @@ public final class SmsCbMessage implements Parcelable { List<Geometry> geometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null; long receivedTimeSec = cursor.getLong( long receivedTimeMillis = cursor.getLong( cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME)); int maximumWaitTimeSec = cursor.getInt( cursor.getColumnIndexOrThrow(CellBroadcasts.MAXIMUM_WAIT_TIME)); return new SmsCbMessage(format, geoScope, serialNum, location, category, language, body, priority, etwsInfo, cmasInfo, geometries, receivedTimeSec); language, body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, geometries, receivedTimeMillis); } /** * @return {@code True} if this message needs geo-fencing check. */ public boolean needGeoFencingCheck() { return mGeometries != null; return mMaximumWaitTimeSec > 0 && mGeometries != null; } }
telephony/java/com/android/internal/telephony/CbGeoUtils.java +2 −1 Original line number Diff line number Diff line Loading @@ -299,7 +299,8 @@ public class CbGeoUtils { * @return the encoded string. */ @NonNull public static String encodeGeometriesToString(@NonNull List<Geometry> geometries) { public static String encodeGeometriesToString(List<Geometry> geometries) { if (geometries == null || geometries.isEmpty()) return ""; return geometries.stream() .map(geometry -> encodeGeometryToString(geometry)) .filter(encodedStr -> !TextUtils.isEmpty(encodedStr)) Loading
telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java +24 −8 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ public class GsmSmsCbMessage { header.getSerialNumber(), location, header.getServiceCategory(), null, getEtwsPrimaryMessage(context, header.getEtwsInfo().getWarningType()), SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, header.getEtwsInfo(), header.getCmasInfo(), null /* geometries */, receivedTimeMillis); header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis); } else if (header.isUmtsFormat()) { // UMTS format has only 1 PDU byte[] pdu = pdus[0]; Loading @@ -120,9 +120,13 @@ public class GsmSmsCbMessage { // Has Warning Area Coordinates information List<Geometry> geometries = null; int maximumWaitingTimeSec = 255; if (pdu.length > wacDataOffset) { try { geometries = parseWarningAreaCoordinates(pdu, wacDataOffset); Pair<Integer, List<Geometry>> wac = parseWarningAreaCoordinates(pdu, wacDataOffset); maximumWaitingTimeSec = wac.first; geometries = wac.second; } catch (Exception ex) { // Catch the exception here, the message will be considered as having no WAC // information which means the message will be broadcasted directly. Loading @@ -133,7 +137,8 @@ public class GsmSmsCbMessage { return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP, header.getGeographicalScope(), header.getSerialNumber(), location, header.getServiceCategory(), language, body, priority, header.getEtwsInfo(), header.getCmasInfo(), geometries, receivedTimeMillis); header.getEtwsInfo(), header.getCmasInfo(), maximumWaitingTimeSec, geometries, receivedTimeMillis); } else { String language = null; StringBuilder sb = new StringBuilder(); Loading @@ -148,7 +153,7 @@ public class GsmSmsCbMessage { return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP, header.getGeographicalScope(), header.getSerialNumber(), location, header.getServiceCategory(), language, sb.toString(), priority, header.getEtwsInfo(), header.getCmasInfo(), null /* geometries */, header.getEtwsInfo(), header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis); } } Loading Loading @@ -197,7 +202,17 @@ public class GsmSmsCbMessage { } } private static List<Geometry> parseWarningAreaCoordinates(byte[] pdu, int wacOffset) { /** * Parse the broadcast area and maximum wait time from the Warning Area Coordinates TLV. * * @param pdu Warning Area Coordinates TLV. * @param wacOffset the offset of Warning Area Coordinates TLV. * @return a pair with the first element is maximum wait time and the second is the broadcast * area. The default value of the maximum wait time is 255 which means use the device default * value. */ private static Pair<Integer, List<Geometry>> parseWarningAreaCoordinates( byte[] pdu, int wacOffset) { // little-endian int wacDataLength = (pdu[wacOffset + 1] << 8) | pdu[wacOffset]; int offset = wacOffset + 2; Loading @@ -209,6 +224,8 @@ public class GsmSmsCbMessage { BitStreamReader bitReader = new BitStreamReader(pdu, offset); int maximumWaitTimeSec = SmsCbMessage.MAXIMUM_WAIT_TIME_NOT_SET; List<Geometry> geo = new ArrayList<>(); int remainedBytes = wacDataLength; while (remainedBytes > 0) { Loading @@ -220,8 +237,7 @@ public class GsmSmsCbMessage { switch (type) { case CbGeoUtils.GEO_FENCING_MAXIMUM_WAIT_TIME: // TODO: handle the maximum wait time in cell broadcast provider. int maximumWaitTimeSec = bitReader.read(8); maximumWaitTimeSec = bitReader.read(8); break; case CbGeoUtils.GEOMETRY_TYPE_POLYGON: List<LatLng> latLngs = new ArrayList<>(); Loading @@ -247,7 +263,7 @@ public class GsmSmsCbMessage { throw new IllegalArgumentException("Unsupported geoType = " + type); } } return geo; return new Pair(maximumWaitTimeSec, geo); } /** Loading