Merge "Support maximum wait time for Cell broadcast"
This commit is contained in:
@@ -3962,6 +3962,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>
|
||||
@@ -4183,6 +4190,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
|
||||
@@ -4236,7 +4255,8 @@ public final class Telephony {
|
||||
CMAS_CERTAINTY,
|
||||
RECEIVED_TIME,
|
||||
MESSAGE_BROADCASTED,
|
||||
GEOMETRIES
|
||||
GEOMETRIES,
|
||||
MAXIMUM_WAIT_TIME
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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;
|
||||
@@ -226,6 +240,7 @@ public final class SmsCbMessage implements Parcelable {
|
||||
mCmasWarningInfo = cmasWarningInfo;
|
||||
mReceivedTimeMillis = receivedTimeMillis;
|
||||
mGeometries = geometries;
|
||||
mMaximumWaitTimeSec = maximumWaitTimeSec;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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")
|
||||
+ '}';
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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];
|
||||
@@ -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.
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
@@ -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<>();
|
||||
@@ -247,7 +263,7 @@ public class GsmSmsCbMessage {
|
||||
throw new IllegalArgumentException("Unsupported geoType = " + type);
|
||||
}
|
||||
}
|
||||
return geo;
|
||||
return new Pair(maximumWaitTimeSec, geo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user