10d4bcdf379842af4b6304809156971e926f374f0Jake Hamby/*
20d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Copyright (C) 2013 The Android Open Source Project
30d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
40d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Licensed under the Apache License, Version 2.0 (the "License");
50d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * you may not use this file except in compliance with the License.
60d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * You may obtain a copy of the License at
70d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
80d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *      http://www.apache.org/licenses/LICENSE-2.0
90d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Unless required by applicable law or agreed to in writing, software
110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * distributed under the License is distributed on an "AS IS" BASIS,
120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * See the License for the specific language governing permissions and
140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * limitations under the License.
150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */
160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
170d4bcdf379842af4b6304809156971e926f374f0Jake Hambypackage com.android.internal.telephony.gsm;
180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
190d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.Context;
200d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.os.AsyncResult;
210d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.os.Message;
220d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.os.SystemProperties;
230d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.CellLocation;
240d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.SmsCbLocation;
250d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.SmsCbMessage;
260d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.gsm.GsmCellLocation;
270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
280d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.CellBroadcastHandler;
290d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.PhoneBase;
300d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.TelephonyProperties;
310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
320d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.HashMap;
330d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.Iterator;
340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby/**
360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Handler for 3GPP format Cell Broadcasts. Parent class can also handle CDMA Cell Broadcasts.
370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */
380d4bcdf379842af4b6304809156971e926f374f0Jake Hambypublic class GsmCellBroadcastHandler extends CellBroadcastHandler {
390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private static final boolean VDBG = false;  // log CB PDU data
400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /** This map holds incomplete concatenated messages waiting for assembly. */
420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private final HashMap<SmsCbConcatInfo, byte[][]> mSmsCbPageMap =
430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            new HashMap<SmsCbConcatInfo, byte[][]>(4);
440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected GsmCellBroadcastHandler(Context context, PhoneBase phone) {
46d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        super("GsmCellBroadcastHandler", context, phone);
470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        phone.mCi.setOnNewGsmBroadcastSms(getHandler(), EVENT_NEW_SMS_MESSAGE, null);
480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected void onQuitting() {
520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mPhone.mCi.unSetOnNewGsmBroadcastSms(getHandler());
530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        super.onQuitting();     // release wakelock
540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Create a new CellBroadcastHandler.
580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param context the context to use for dispatching Intents
590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return the new handler
600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    public static GsmCellBroadcastHandler makeGsmCellBroadcastHandler(Context context,
620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            PhoneBase phone) {
630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        GsmCellBroadcastHandler handler = new GsmCellBroadcastHandler(context, phone);
640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        handler.start();
650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return handler;
660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Handle 3GPP-format Cell Broadcast messages sent from radio.
700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     *
710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param message the message to process
720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return true if an ordered broadcast was sent; false on failure
730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected boolean handleSmsMessage(Message message) {
760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (message.obj instanceof AsyncResult) {
770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            SmsCbMessage cbMessage = handleGsmBroadcastSms((AsyncResult) message.obj);
780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (cbMessage != null) {
790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                handleBroadcastSms(cbMessage);
800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return true;
810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return super.handleSmsMessage(message);
840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Handle 3GPP format SMS-CB message.
880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param ar the AsyncResult containing the received PDUs
890d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private SmsCbMessage handleGsmBroadcastSms(AsyncResult ar) {
910d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        try {
920d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            byte[] receivedPdu = (byte[]) ar.result;
930d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
940d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (VDBG) {
950d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                int pduLength = receivedPdu.length;
960d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                for (int i = 0; i < pduLength; i += 8) {
970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    StringBuilder sb = new StringBuilder("SMS CB pdu data: ");
980d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    for (int j = i; j < i + 8 && j < pduLength; j++) {
990d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                        int b = receivedPdu[j] & 0xff;
1000d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                        if (b < 0x10) {
1010d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                            sb.append('0');
1020d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                        }
1030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                        sb.append(Integer.toHexString(b)).append(' ');
1040d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    }
1050d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    log(sb.toString());
1060d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                }
1070d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1080d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1090d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            SmsCbHeader header = new SmsCbHeader(receivedPdu);
1100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            String plmn = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC);
1110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            int lac = -1;
1120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            int cid = -1;
1130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            CellLocation cl = mPhone.getCellLocation();
1140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // Check if cell location is GsmCellLocation.  This is required to support
1150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // dual-mode devices such as CDMA/LTE devices that require support for
1160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // both 3GPP and 3GPP2 format messages
1170d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (cl instanceof GsmCellLocation) {
1180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                GsmCellLocation cellLocation = (GsmCellLocation)cl;
1190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                lac = cellLocation.getLac();
1200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                cid = cellLocation.getCid();
1210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            SmsCbLocation location;
1240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            switch (header.getGeographicalScope()) {
1250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                case SmsCbMessage.GEOGRAPHICAL_SCOPE_LA_WIDE:
1260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    location = new SmsCbLocation(plmn, lac, -1);
1270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    break;
1280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE:
1300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                case SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE:
1310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    location = new SmsCbLocation(plmn, lac, cid);
1320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    break;
1330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                case SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE:
1350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                default:
1360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    location = new SmsCbLocation(plmn);
1370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    break;
1380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            byte[][] pdus;
1410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            int pageCount = header.getNumberOfPages();
1420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (pageCount > 1) {
1430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // Multi-page message
1440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                SmsCbConcatInfo concatInfo = new SmsCbConcatInfo(header, location);
1450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // Try to find other pages of the same message
1470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                pdus = mSmsCbPageMap.get(concatInfo);
1480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                if (pdus == null) {
1500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    // This is the first page of this message, make room for all
1510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    // pages and keep until complete
1520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    pdus = new byte[pageCount][];
1530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    mSmsCbPageMap.put(concatInfo, pdus);
1550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                }
1560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // Page parameter is one-based
1580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                pdus[header.getPageIndex() - 1] = receivedPdu;
1590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                for (byte[] pdu : pdus) {
1610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    if (pdu == null) {
1620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                        // Still missing pages, exit
1630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                        return null;
1640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    }
1650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                }
1660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // Message complete, remove and dispatch
1680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                mSmsCbPageMap.remove(concatInfo);
1690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            } else {
1700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // Single page message
1710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                pdus = new byte[1][];
1720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                pdus[0] = receivedPdu;
1730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // Remove messages that are out of scope to prevent the map from
1760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // growing indefinitely, containing incomplete messages that were
1770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // never assembled
1780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            Iterator<SmsCbConcatInfo> iter = mSmsCbPageMap.keySet().iterator();
1790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            while (iter.hasNext()) {
1810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                SmsCbConcatInfo info = iter.next();
1820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                if (!info.matchesLocation(plmn, lac, cid)) {
1840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    iter.remove();
1850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                }
1860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return GsmSmsCbMessage.createSmsCbMessage(header, location, pdus);
1890d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        } catch (RuntimeException e) {
1910d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            loge("Error in decoding SMS CB pdu", e);
1920d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return null;
1930d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1940d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
1950d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1960d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
1970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Holds all info about a message page needed to assemble a complete concatenated message.
1980d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
1990d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private static final class SmsCbConcatInfo {
2000d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2010d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        private final SmsCbHeader mHeader;
2020d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        private final SmsCbLocation mLocation;
2030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2040d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        SmsCbConcatInfo(SmsCbHeader header, SmsCbLocation location) {
2050d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            mHeader = header;
2060d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            mLocation = location;
2070d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
2080d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2090d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        @Override
2100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        public int hashCode() {
2110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return (mHeader.getSerialNumber() * 31) + mLocation.hashCode();
2120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
2130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        @Override
2150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        public boolean equals(Object obj) {
2160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (obj instanceof SmsCbConcatInfo) {
2170d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                SmsCbConcatInfo other = (SmsCbConcatInfo)obj;
2180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // Two pages match if they have the same serial number (which includes the
2200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // geographical scope and update number), and both pages belong to the same
2210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // location (PLMN, plus LAC and CID if these are part of the geographical scope).
2220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return mHeader.getSerialNumber() == other.mHeader.getSerialNumber()
2230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                        && mLocation.equals(other.mLocation);
2240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
2250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return false;
2270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
2280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
2290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        /**
2300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby         * Compare the location code for this message to the current location code. The match is
2310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby         * relative to the geographical scope of the message, which determines whether the LAC
2320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby         * and Cell ID are saved in mLocation or set to -1 to match all values.
2330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby         *
2340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby         * @param plmn the current PLMN
2350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby         * @param lac the current Location Area (GSM) or Service Area (UMTS)
2360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby         * @param cid the current Cell ID
2370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby         * @return true if this message is valid for the current location; false otherwise
2380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby         */
2390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        public boolean matchesLocation(String plmn, int lac, int cid) {
2400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return mLocation.isInLocationArea(plmn, lac, cid);
2410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
2420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
2430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby}
244