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

Commit 7f7695fd authored by Pengquan Meng's avatar Pengquan Meng
Browse files

Support maximum wait time for Cell broadcast

Geo-Fencing Maximum Wait Time a device shall allow to determines it
location 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.

Bug: 139022202
Test: manual
Change-Id: Ic93c0013cd46da1a8ebaa78011e5b99ff0eebe00
parent f72a8fd4
Loading
Loading
Loading
Loading
+28 −13
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ import android.provider.Telephony;
import android.provider.Telephony.CellBroadcasts;
import android.provider.Telephony.CellBroadcasts;
import android.telephony.SmsCbMessage;
import android.telephony.SmsCbMessage;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager;
import android.text.format.DateUtils;
import android.util.LocalLog;
import android.util.LocalLog;
import android.util.Log;
import android.util.Log;


@@ -98,7 +99,7 @@ public class CellBroadcastHandler extends WakeLockStateMachine {
     * 3GPP-format Cell Broadcast messages sent from radio are handled in the subclass.
     * 3GPP-format Cell Broadcast messages sent from radio are handled in the subclass.
     *
     *
     * @param message the message to process
     * @param message the message to process
     * @return true if an ordered broadcast was sent; false on failure
     * @return true if need to wait for geo-fencing or an ordered broadcast was sent.
     */
     */
    @Override
    @Override
    protected boolean handleSmsMessage(Message message) {
    protected boolean handleSmsMessage(Message message) {
@@ -141,7 +142,7 @@ public class CellBroadcastHandler extends WakeLockStateMachine {
                } else {
                } else {
                    performGeoFencing(message, uri, message.getGeometries(), location);
                    performGeoFencing(message, uri, message.getGeometries(), location);
                }
                }
            });
            }, message.getMaximumWaitingTime());
        } else {
        } else {
            if (DBG) {
            if (DBG) {
                log("Broadcast the message directly because no geo-fencing required, "
                log("Broadcast the message directly because no geo-fencing required, "
@@ -185,9 +186,11 @@ public class CellBroadcastHandler extends WakeLockStateMachine {
    /**
    /**
     * Request a single location update.
     * Request a single location update.
     * @param callback a callback will be called when the location is available.
     * @param callback a callback will be called when the location is available.
     * @param maximumWaitTimeSec the maximum wait time of this request. If location is not updated
     * within the maximum wait time, {@code callback#onLocationUpadte(null)} will be called.
     */
     */
    protected void requestLocationUpdate(LocationUpdateCallback callback) {
    protected void requestLocationUpdate(LocationUpdateCallback callback, int maximumWaitTimeSec) {
        mLocationRequester.requestLocationUpdate(callback);
        mLocationRequester.requestLocationUpdate(callback, maximumWaitTimeSec);
    }
    }


    /**
    /**
@@ -294,6 +297,12 @@ public class CellBroadcastHandler extends WakeLockStateMachine {
    private static final class LocationRequester {
    private static final class LocationRequester {
        private static final String TAG = LocationRequester.class.getSimpleName();
        private static final String TAG = LocationRequester.class.getSimpleName();


        /**
         * Use as the default maximum wait time if the cell broadcast doesn't specify the value.
         * Most of the location request should be responded within 20 seconds.
         */
        private static final int DEFAULT_MAXIMUM_WAIT_TIME_SEC = 20;

        /**
        /**
         * Trigger this event when the {@link LocationManager} is not responded within the given
         * Trigger this event when the {@link LocationManager} is not responded within the given
         * time.
         * time.
@@ -303,9 +312,6 @@ public class CellBroadcastHandler extends WakeLockStateMachine {
        /** Request a single location update. */
        /** Request a single location update. */
        private static final int EVENT_REQUEST_LOCATION_UPDATE = 2;
        private static final int EVENT_REQUEST_LOCATION_UPDATE = 2;


        /** Default expired time of the location request. */
        private static final int LOCATION_REQUEST_TIMEOUT_MILLIS = 30 * 1000;

        /**
        /**
         * Request location update from network or gps location provider. Network provider will be
         * Request location update from network or gps location provider. Network provider will be
         * used if available, otherwise use the gps provider.
         * used if available, otherwise use the gps provider.
@@ -330,10 +336,16 @@ public class CellBroadcastHandler extends WakeLockStateMachine {
        /**
        /**
         * Request a single location update. If the location is not available, a callback with
         * Request a single location update. If the location is not available, a callback with
         * {@code null} location will be called immediately.
         * {@code null} location will be called immediately.
         *
         * @param callback a callback to the the response when the location is available
         * @param callback a callback to the the response when the location is available
         * @param maximumWaitTimeSec the maximum wait time of this request. If location is not
         * updated within the maximum wait time, {@code callback#onLocationUpadte(null)} will be
         * called.
         */
         */
        void requestLocationUpdate(@NonNull LocationUpdateCallback callback) {
        void requestLocationUpdate(@NonNull LocationUpdateCallback callback,
            mLocationHandler.obtainMessage(EVENT_REQUEST_LOCATION_UPDATE, callback).sendToTarget();
                int maximumWaitTimeSec) {
            mLocationHandler.obtainMessage(EVENT_REQUEST_LOCATION_UPDATE, maximumWaitTimeSec,
                    0 /* arg2 */, callback).sendToTarget();
        }
        }


        private void onLocationUpdate(@Nullable LatLng location) {
        private void onLocationUpdate(@Nullable LatLng location) {
@@ -343,7 +355,8 @@ public class CellBroadcastHandler extends WakeLockStateMachine {
            mCallbacks.clear();
            mCallbacks.clear();
        }
        }


        private void requestLocationUpdateInternal(@NonNull LocationUpdateCallback callback) {
        private void requestLocationUpdateInternal(@NonNull LocationUpdateCallback callback,
                int maximumWaitTimeSec) {
            if (DBG) Log.d(TAG, "requestLocationUpdate");
            if (DBG) Log.d(TAG, "requestLocationUpdate");
            if (!isLocationServiceAvailable()) {
            if (!isLocationServiceAvailable()) {
                if (DBG) {
                if (DBG) {
@@ -353,11 +366,13 @@ public class CellBroadcastHandler extends WakeLockStateMachine {
                return;
                return;
            }
            }


            // TODO: handle the "Geo-fencing Maximum Wait" defined in ATIS-0700041 Section 5.2.3
            if (!mLocationHandler.hasMessages(EVENT_LOCATION_REQUEST_TIMEOUT)) {
            if (!mLocationHandler.hasMessages(EVENT_LOCATION_REQUEST_TIMEOUT)) {
                if (maximumWaitTimeSec == SmsCbMessage.MAXIMUM_WAIT_TIME_NOT_SET) {
                    maximumWaitTimeSec = DEFAULT_MAXIMUM_WAIT_TIME_SEC;
                }
                mLocationHandler.sendMessageDelayed(
                mLocationHandler.sendMessageDelayed(
                        mLocationHandler.obtainMessage(EVENT_LOCATION_REQUEST_TIMEOUT),
                        mLocationHandler.obtainMessage(EVENT_LOCATION_REQUEST_TIMEOUT),
                        LOCATION_REQUEST_TIMEOUT_MILLIS);
                        maximumWaitTimeSec * DateUtils.SECOND_IN_MILLIS);
            }
            }


            mCallbacks.add(callback);
            mCallbacks.add(callback);
@@ -414,7 +429,7 @@ public class CellBroadcastHandler extends WakeLockStateMachine {
                        onLocationUpdate(null);
                        onLocationUpdate(null);
                        break;
                        break;
                    case EVENT_REQUEST_LOCATION_UPDATE:
                    case EVENT_REQUEST_LOCATION_UPDATE:
                        requestLocationUpdateInternal((LocationUpdateCallback) msg.obj);
                        requestLocationUpdateInternal((LocationUpdateCallback) msg.obj, msg.arg1);
                        break;
                        break;
                    default:
                    default:
                        Log.e(TAG, "Unsupported message type " + msg.what);
                        Log.e(TAG, "Unsupported message type " + msg.what);
+25 −11
Original line number Original line Diff line number Diff line
@@ -31,6 +31,7 @@ import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
import android.telephony.SmsCbMessage;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.text.format.DateUtils;


import com.android.internal.telephony.CbGeoUtils.Geometry;
import com.android.internal.telephony.CbGeoUtils.Geometry;
import com.android.internal.telephony.CellBroadcastHandler;
import com.android.internal.telephony.CellBroadcastHandler;
@@ -86,16 +87,23 @@ public class GsmCellBroadcastHandler extends CellBroadcastHandler {
     * Find the cell broadcast messages specify by the geo-fencing trigger message and perform a
     * Find the cell broadcast messages specify by the geo-fencing trigger message and perform a
     * geo-fencing check for these messages.
     * geo-fencing check for these messages.
     * @param geoFencingTriggerMessage the trigger message
     * @param geoFencingTriggerMessage the trigger message
     *
     * @return {@code True} if geo-fencing is need for some cell broadcast message.
     */
     */
    private void handleGeoFencingTriggerMessage(GeoFencingTriggerMessage geoFencingTriggerMessage) {
    private boolean handleGeoFencingTriggerMessage(
            GeoFencingTriggerMessage geoFencingTriggerMessage) {
        final List<SmsCbMessage> cbMessages = new ArrayList<>();
        final List<SmsCbMessage> cbMessages = new ArrayList<>();
        final List<Uri> cbMessageUris = new ArrayList<>();
        final List<Uri> cbMessageUris = new ArrayList<>();


        // Only consider the cell broadcast received within 24 hours.
        long lastReceivedTime = System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS;

        // Find the cell broadcast message identify by the message identifier and serial number
        // Find the cell broadcast message identify by the message identifier and serial number
        // and is not broadcasted.
        // and is not broadcasted.
        String where = CellBroadcasts.SERVICE_CATEGORY + "=? AND "
        String where = CellBroadcasts.SERVICE_CATEGORY + "=? AND "
                + CellBroadcasts.SERIAL_NUMBER + "=? AND "
                + CellBroadcasts.SERIAL_NUMBER + "=? AND "
                + CellBroadcasts.MESSAGE_BROADCASTED + "=?";
                + CellBroadcasts.MESSAGE_BROADCASTED + "=? AND "
                + CellBroadcasts.RECEIVED_TIME + ">?";


        ContentResolver resolver = mContext.getContentResolver();
        ContentResolver resolver = mContext.getContentResolver();
        for (CellBroadcastIdentity identity : geoFencingTriggerMessage.cbIdentifiers) {
        for (CellBroadcastIdentity identity : geoFencingTriggerMessage.cbIdentifiers) {
@@ -103,7 +111,8 @@ public class GsmCellBroadcastHandler extends CellBroadcastHandler {
                    CellBroadcasts.QUERY_COLUMNS_FWK,
                    CellBroadcasts.QUERY_COLUMNS_FWK,
                    where,
                    where,
                    new String[] { Integer.toString(identity.messageIdentifier),
                    new String[] { Integer.toString(identity.messageIdentifier),
                            Integer.toString(identity.serialNumber), MESSAGE_NOT_BROADCASTED},
                            Integer.toString(identity.serialNumber), MESSAGE_NOT_BROADCASTED,
                            Long.toString(lastReceivedTime) },
                    null /* sortOrder */)) {
                    null /* sortOrder */)) {
                if (cursor != null) {
                if (cursor != null) {
                    while (cursor.moveToNext()) {
                    while (cursor.moveToNext()) {
@@ -124,6 +133,14 @@ public class GsmCellBroadcastHandler extends CellBroadcastHandler {
            }
            }
        }
        }


        // ATIS doesn't specify the geo fencing maximum wait time for the cell broadcasts specified
        // in geo fencing trigger message. We will pick the largest maximum wait time among these
        // cell broadcasts.
        int maximumWaitTimeSec = 0;
        for (SmsCbMessage msg : cbMessages) {
            maximumWaitTimeSec = Math.max(maximumWaitTimeSec, msg.getMaximumWaitingTime());
        }

        if (DBG) {
        if (DBG) {
            logd("Geo-fencing trigger message = " + geoFencingTriggerMessage);
            logd("Geo-fencing trigger message = " + geoFencingTriggerMessage);
            for (SmsCbMessage msg : cbMessages) {
            for (SmsCbMessage msg : cbMessages) {
@@ -133,10 +150,7 @@ public class GsmCellBroadcastHandler extends CellBroadcastHandler {


        if (cbMessages.isEmpty()) {
        if (cbMessages.isEmpty()) {
            if (DBG) logd("No CellBroadcast message need to be broadcasted");
            if (DBG) logd("No CellBroadcast message need to be broadcasted");

            return false;
            // Need to send this event to make the state machine back to Idle.
            if (mReceiverCount.get() == 0) sendMessage(EVENT_BROADCAST_COMPLETE);
            return;
        }
        }


        requestLocationUpdate(location -> {
        requestLocationUpdate(location -> {
@@ -155,14 +169,15 @@ public class GsmCellBroadcastHandler extends CellBroadcastHandler {
                    }
                    }
                }
                }
            }
            }
        });
        }, maximumWaitTimeSec);
        return true;
    }
    }


    /**
    /**
     * Handle 3GPP-format Cell Broadcast messages sent from radio.
     * Handle 3GPP-format Cell Broadcast messages sent from radio.
     *
     *
     * @param message the message to process
     * @param message the message to process
     * @return true if an ordered broadcast was sent; false on failure
     * @return true if need to wait for geo-fencing or an ordered broadcast was sent.
     */
     */
    @Override
    @Override
    protected boolean handleSmsMessage(Message message) {
    protected boolean handleSmsMessage(Message message) {
@@ -176,8 +191,7 @@ public class GsmCellBroadcastHandler extends CellBroadcastHandler {
                GeoFencingTriggerMessage triggerMessage =
                GeoFencingTriggerMessage triggerMessage =
                        GsmSmsCbMessage.createGeoFencingTriggerMessage(pdu);
                        GsmSmsCbMessage.createGeoFencingTriggerMessage(pdu);
                if (triggerMessage != null) {
                if (triggerMessage != null) {
                    handleGeoFencingTriggerMessage(triggerMessage);
                    return handleGeoFencingTriggerMessage(triggerMessage);
                    return true;
                }
                }
            } else {
            } else {
                SmsCbMessage cbMessage = handleGsmBroadcastSms(header, ar);
                SmsCbMessage cbMessage = handleGsmBroadcastSms(header, ar);