Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c5523895 authored by Pengquan Meng's avatar Pengquan Meng Committed by Android (Google) Code Review
Browse files

Merge "Support maximum wait time for Cell broadcast"

parents 6f31f79a 02d6ac0f
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -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>
@@ -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
@@ -4235,7 +4254,8 @@ public final class Telephony {
                CMAS_CERTAINTY,
                RECEIVED_TIME,
                MESSAGE_BROADCASTED,
                GEOMETRIES
                GEOMETRIES,
                MAXIMUM_WAIT_TIME
        };
    }

+39 −6
Original line number Diff line number Diff line
@@ -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;
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -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))
+24 −8
Original line number Diff line number Diff line
@@ -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);
    }

    /**