Merge "Support maximum wait time for Cell broadcast"
This commit is contained in:
@@ -3962,6 +3962,13 @@ public final class Telephony {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts");
|
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:
|
* Message geographical scope. Valid values are:
|
||||||
* <ul>
|
* <ul>
|
||||||
@@ -4183,6 +4190,18 @@ public final class Telephony {
|
|||||||
*/
|
*/
|
||||||
public static final String GEOMETRIES = "geometries";
|
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.
|
* Query columns for instantiating {@link android.telephony.CellBroadcastMessage} objects.
|
||||||
* @hide
|
* @hide
|
||||||
@@ -4236,7 +4255,8 @@ public final class Telephony {
|
|||||||
CMAS_CERTAINTY,
|
CMAS_CERTAINTY,
|
||||||
RECEIVED_TIME,
|
RECEIVED_TIME,
|
||||||
MESSAGE_BROADCASTED,
|
MESSAGE_BROADCASTED,
|
||||||
GEOMETRIES
|
GEOMETRIES,
|
||||||
|
MAXIMUM_WAIT_TIME
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,12 @@ public final class SmsCbMessage implements Parcelable {
|
|||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface MessagePriority {}
|
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). */
|
/** Format of this message (for interpretation of service category values). */
|
||||||
private final int mMessageFormat;
|
private final int mMessageFormat;
|
||||||
|
|
||||||
@@ -187,6 +193,14 @@ public final class SmsCbMessage implements Parcelable {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final SmsCbCmasInfo mCmasWarningInfo;
|
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. */
|
/** UNIX timestamp of when the message was received. */
|
||||||
private final long mReceivedTimeMillis;
|
private final long mReceivedTimeMillis;
|
||||||
|
|
||||||
@@ -202,8 +216,8 @@ public final class SmsCbMessage implements Parcelable {
|
|||||||
@Nullable SmsCbCmasInfo cmasWarningInfo) {
|
@Nullable SmsCbCmasInfo cmasWarningInfo) {
|
||||||
|
|
||||||
this(messageFormat, geographicalScope, serialNumber, location, serviceCategory, language,
|
this(messageFormat, geographicalScope, serialNumber, location, serviceCategory, language,
|
||||||
body, priority, etwsWarningInfo, cmasWarningInfo, null /* geometries */,
|
body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */,
|
||||||
System.currentTimeMillis());
|
null /* geometries */, System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -213,7 +227,7 @@ public final class SmsCbMessage implements Parcelable {
|
|||||||
public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
|
public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
|
||||||
SmsCbLocation location, int serviceCategory, String language, String body,
|
SmsCbLocation location, int serviceCategory, String language, String body,
|
||||||
int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo,
|
int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo,
|
||||||
List<Geometry> geometries, long receivedTimeMillis) {
|
int maximumWaitTimeSec, List<Geometry> geometries, long receivedTimeMillis) {
|
||||||
mMessageFormat = messageFormat;
|
mMessageFormat = messageFormat;
|
||||||
mGeographicalScope = geographicalScope;
|
mGeographicalScope = geographicalScope;
|
||||||
mSerialNumber = serialNumber;
|
mSerialNumber = serialNumber;
|
||||||
@@ -226,6 +240,7 @@ public final class SmsCbMessage implements Parcelable {
|
|||||||
mCmasWarningInfo = cmasWarningInfo;
|
mCmasWarningInfo = cmasWarningInfo;
|
||||||
mReceivedTimeMillis = receivedTimeMillis;
|
mReceivedTimeMillis = receivedTimeMillis;
|
||||||
mGeometries = geometries;
|
mGeometries = geometries;
|
||||||
|
mMaximumWaitTimeSec = maximumWaitTimeSec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -262,6 +277,7 @@ public final class SmsCbMessage implements Parcelable {
|
|||||||
mReceivedTimeMillis = in.readLong();
|
mReceivedTimeMillis = in.readLong();
|
||||||
String geoStr = in.readString();
|
String geoStr = in.readString();
|
||||||
mGeometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null;
|
mGeometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null;
|
||||||
|
mMaximumWaitTimeSec = in.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -295,6 +311,7 @@ public final class SmsCbMessage implements Parcelable {
|
|||||||
dest.writeLong(mReceivedTimeMillis);
|
dest.writeLong(mReceivedTimeMillis);
|
||||||
dest.writeString(
|
dest.writeString(
|
||||||
mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : null);
|
mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : null);
|
||||||
|
dest.writeInt(mMaximumWaitTimeSec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -388,6 +405,15 @@ public final class SmsCbMessage implements Parcelable {
|
|||||||
return mGeometries;
|
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.
|
* Get the time when this message was received.
|
||||||
* @return the time in millisecond
|
* @return the time in millisecond
|
||||||
@@ -475,6 +501,7 @@ public final class SmsCbMessage implements Parcelable {
|
|||||||
+ ", priority=" + mPriority
|
+ ", priority=" + mPriority
|
||||||
+ (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "")
|
+ (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "")
|
||||||
+ (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "")
|
+ (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "")
|
||||||
|
+ ", maximumWaitingTime = " + mMaximumWaitTimeSec
|
||||||
+ ", geo=" + (mGeometries != null
|
+ ", geo=" + (mGeometries != null
|
||||||
? CbGeoUtils.encodeGeometriesToString(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.GEOMETRIES, (String) null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cv.put(CellBroadcasts.MAXIMUM_WAIT_TIME, mMaximumWaitTimeSec);
|
||||||
|
|
||||||
return cv;
|
return cv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,17 +673,21 @@ public final class SmsCbMessage implements Parcelable {
|
|||||||
List<Geometry> geometries =
|
List<Geometry> geometries =
|
||||||
geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null;
|
geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null;
|
||||||
|
|
||||||
long receivedTimeSec = cursor.getLong(
|
long receivedTimeMillis = cursor.getLong(
|
||||||
cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME));
|
cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME));
|
||||||
|
|
||||||
|
int maximumWaitTimeSec = cursor.getInt(
|
||||||
|
cursor.getColumnIndexOrThrow(CellBroadcasts.MAXIMUM_WAIT_TIME));
|
||||||
|
|
||||||
return new SmsCbMessage(format, geoScope, serialNum, location, category,
|
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.
|
* @return {@code True} if this message needs geo-fencing check.
|
||||||
*/
|
*/
|
||||||
public boolean needGeoFencingCheck() {
|
public boolean needGeoFencingCheck() {
|
||||||
return mGeometries != null;
|
return mMaximumWaitTimeSec > 0 && mGeometries != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,7 +299,8 @@ public class CbGeoUtils {
|
|||||||
* @return the encoded string.
|
* @return the encoded string.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@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()
|
return geometries.stream()
|
||||||
.map(geometry -> encodeGeometryToString(geometry))
|
.map(geometry -> encodeGeometryToString(geometry))
|
||||||
.filter(encodedStr -> !TextUtils.isEmpty(encodedStr))
|
.filter(encodedStr -> !TextUtils.isEmpty(encodedStr))
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class GsmSmsCbMessage {
|
|||||||
header.getSerialNumber(), location, header.getServiceCategory(), null,
|
header.getSerialNumber(), location, header.getServiceCategory(), null,
|
||||||
getEtwsPrimaryMessage(context, header.getEtwsInfo().getWarningType()),
|
getEtwsPrimaryMessage(context, header.getEtwsInfo().getWarningType()),
|
||||||
SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, header.getEtwsInfo(),
|
SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, header.getEtwsInfo(),
|
||||||
header.getCmasInfo(), null /* geometries */, receivedTimeMillis);
|
header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis);
|
||||||
} else if (header.isUmtsFormat()) {
|
} else if (header.isUmtsFormat()) {
|
||||||
// UMTS format has only 1 PDU
|
// UMTS format has only 1 PDU
|
||||||
byte[] pdu = pdus[0];
|
byte[] pdu = pdus[0];
|
||||||
@@ -120,9 +120,13 @@ public class GsmSmsCbMessage {
|
|||||||
|
|
||||||
// Has Warning Area Coordinates information
|
// Has Warning Area Coordinates information
|
||||||
List<Geometry> geometries = null;
|
List<Geometry> geometries = null;
|
||||||
|
int maximumWaitingTimeSec = 255;
|
||||||
if (pdu.length > wacDataOffset) {
|
if (pdu.length > wacDataOffset) {
|
||||||
try {
|
try {
|
||||||
geometries = parseWarningAreaCoordinates(pdu, wacDataOffset);
|
Pair<Integer, List<Geometry>> wac = parseWarningAreaCoordinates(pdu,
|
||||||
|
wacDataOffset);
|
||||||
|
maximumWaitingTimeSec = wac.first;
|
||||||
|
geometries = wac.second;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// Catch the exception here, the message will be considered as having no WAC
|
// Catch the exception here, the message will be considered as having no WAC
|
||||||
// information which means the message will be broadcasted directly.
|
// information which means the message will be broadcasted directly.
|
||||||
@@ -133,7 +137,8 @@ public class GsmSmsCbMessage {
|
|||||||
return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP,
|
return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP,
|
||||||
header.getGeographicalScope(), header.getSerialNumber(), location,
|
header.getGeographicalScope(), header.getSerialNumber(), location,
|
||||||
header.getServiceCategory(), language, body, priority,
|
header.getServiceCategory(), language, body, priority,
|
||||||
header.getEtwsInfo(), header.getCmasInfo(), geometries, receivedTimeMillis);
|
header.getEtwsInfo(), header.getCmasInfo(), maximumWaitingTimeSec, geometries,
|
||||||
|
receivedTimeMillis);
|
||||||
} else {
|
} else {
|
||||||
String language = null;
|
String language = null;
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@@ -148,7 +153,7 @@ public class GsmSmsCbMessage {
|
|||||||
return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP,
|
return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP,
|
||||||
header.getGeographicalScope(), header.getSerialNumber(), location,
|
header.getGeographicalScope(), header.getSerialNumber(), location,
|
||||||
header.getServiceCategory(), language, sb.toString(), priority,
|
header.getServiceCategory(), language, sb.toString(), priority,
|
||||||
header.getEtwsInfo(), header.getCmasInfo(), null /* geometries */,
|
header.getEtwsInfo(), header.getCmasInfo(), 0, null /* geometries */,
|
||||||
receivedTimeMillis);
|
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
|
// little-endian
|
||||||
int wacDataLength = (pdu[wacOffset + 1] << 8) | pdu[wacOffset];
|
int wacDataLength = (pdu[wacOffset + 1] << 8) | pdu[wacOffset];
|
||||||
int offset = wacOffset + 2;
|
int offset = wacOffset + 2;
|
||||||
@@ -209,6 +224,8 @@ public class GsmSmsCbMessage {
|
|||||||
|
|
||||||
BitStreamReader bitReader = new BitStreamReader(pdu, offset);
|
BitStreamReader bitReader = new BitStreamReader(pdu, offset);
|
||||||
|
|
||||||
|
int maximumWaitTimeSec = SmsCbMessage.MAXIMUM_WAIT_TIME_NOT_SET;
|
||||||
|
|
||||||
List<Geometry> geo = new ArrayList<>();
|
List<Geometry> geo = new ArrayList<>();
|
||||||
int remainedBytes = wacDataLength;
|
int remainedBytes = wacDataLength;
|
||||||
while (remainedBytes > 0) {
|
while (remainedBytes > 0) {
|
||||||
@@ -220,8 +237,7 @@ public class GsmSmsCbMessage {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CbGeoUtils.GEO_FENCING_MAXIMUM_WAIT_TIME:
|
case CbGeoUtils.GEO_FENCING_MAXIMUM_WAIT_TIME:
|
||||||
// TODO: handle the maximum wait time in cell broadcast provider.
|
maximumWaitTimeSec = bitReader.read(8);
|
||||||
int maximumWaitTimeSec = bitReader.read(8);
|
|
||||||
break;
|
break;
|
||||||
case CbGeoUtils.GEOMETRY_TYPE_POLYGON:
|
case CbGeoUtils.GEOMETRY_TYPE_POLYGON:
|
||||||
List<LatLng> latLngs = new ArrayList<>();
|
List<LatLng> latLngs = new ArrayList<>();
|
||||||
@@ -247,7 +263,7 @@ public class GsmSmsCbMessage {
|
|||||||
throw new IllegalArgumentException("Unsupported geoType = " + type);
|
throw new IllegalArgumentException("Unsupported geoType = " + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return geo;
|
return new Pair(maximumWaitTimeSec, geo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user