SmsBroadcastUndelivered.java revision a83613955a113b805729cd415aca50707529208a
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; 180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 198f21e0c6528f015924d153350dd2a717d3b51f66Ji Yangimport android.content.BroadcastReceiver; 200d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.ContentResolver; 210d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.Context; 228f21e0c6528f015924d153350dd2a717d3b51f66Ji Yangimport android.content.Intent; 238f21e0c6528f015924d153350dd2a717d3b51f66Ji Yangimport android.content.IntentFilter; 240d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.database.Cursor; 250d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.database.SQLException; 260d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.net.Uri; 278f21e0c6528f015924d153350dd2a717d3b51f66Ji Yangimport android.os.UserHandle; 28a83613955a113b805729cd415aca50707529208aAmit Mahajanimport android.os.UserManager; 290d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.provider.Telephony; 300d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.Rlog; 310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 320d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.cdma.CdmaInboundSmsHandler; 330d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.gsm.GsmInboundSmsHandler; 340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 350d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.HashMap; 360d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.HashSet; 370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby/** 398f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang * Called when the credential-encrypted storage is unlocked, collecting all acknowledged messages 408f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang * and deleting any partial message segments older than 30 days. Called from a worker thread to 418f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang * avoid delaying phone app startup. The last step is to broadcast the first pending message from 428f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang * the main thread, then the remaining pending messages will be broadcast after the previous 438f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang * ordered broadcast completes. 440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 458f21e0c6528f015924d153350dd2a717d3b51f66Ji Yangpublic class SmsBroadcastUndelivered { 460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private static final String TAG = "SmsBroadcastUndelivered"; 470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private static final boolean DBG = InboundSmsHandler.DBG; 480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** Delete any partial message segments older than 30 days. */ 500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby static final long PARTIAL_SEGMENT_EXPIRE_AGE = (long) (60 * 60 * 1000) * 24 * 30; 510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Query projection for dispatching pending messages at boot time. 540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Column order must match the {@code *_COLUMN} constants in {@link InboundSmsHandler}. 550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private static final String[] PDU_PENDING_MESSAGE_PROJECTION = { 570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby "pdu", 580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby "sequence", 590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby "destination_port", 600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby "date", 610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby "reference_number", 620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby "count", 630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby "address", 646e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan "_id", 656e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan "message_body" 660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby }; 670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 688f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang private static SmsBroadcastUndelivered instance; 690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** Content resolver to use to access raw table from SmsProvider. */ 710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private final ContentResolver mResolver; 720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** Handler for 3GPP-format messages (may be null). */ 740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private final GsmInboundSmsHandler mGsmInboundSmsHandler; 750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** Handler for 3GPP2-format messages (may be null). */ 770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private final CdmaInboundSmsHandler mCdmaInboundSmsHandler; 780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 798f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang /** Broadcast receiver that processes the raw table when the user unlocks the phone for the 808f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang * first time after reboot and the credential-encrypted storage is available. 818f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang */ 828f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 838f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang @Override 848f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang public void onReceive(Context context, Intent intent) { 858f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang Rlog.d(TAG, "Received broadcast " + intent.getAction()); 868f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) { 87a83613955a113b805729cd415aca50707529208aAmit Mahajan new ScanRawTableThread().start(); 888f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang } 898f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang } 908f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang }; 918f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang 92a83613955a113b805729cd415aca50707529208aAmit Mahajan private class ScanRawTableThread extends Thread { 93a83613955a113b805729cd415aca50707529208aAmit Mahajan @Override 94a83613955a113b805729cd415aca50707529208aAmit Mahajan public void run() { 95a83613955a113b805729cd415aca50707529208aAmit Mahajan scanRawTable(); 96a83613955a113b805729cd415aca50707529208aAmit Mahajan } 97a83613955a113b805729cd415aca50707529208aAmit Mahajan } 98a83613955a113b805729cd415aca50707529208aAmit Mahajan 998f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang public static void initialize(Context context, GsmInboundSmsHandler gsmInboundSmsHandler, 1008f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang CdmaInboundSmsHandler cdmaInboundSmsHandler) { 1018f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang if (instance == null) { 1028f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang instance = new SmsBroadcastUndelivered( 1038f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang context, gsmInboundSmsHandler, cdmaInboundSmsHandler); 1048f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang } 105dc7411e9fc8ac029a7bad8b85b0f24642a1774b6Ji Yang 106dc7411e9fc8ac029a7bad8b85b0f24642a1774b6Ji Yang // Tell handlers to start processing new messages and transit from the startup state to the 107dc7411e9fc8ac029a7bad8b85b0f24642a1774b6Ji Yang // idle state. This method may be called multiple times for multi-sim devices. We must make 108dc7411e9fc8ac029a7bad8b85b0f24642a1774b6Ji Yang // sure the state transition happen to all inbound sms handlers. 109dc7411e9fc8ac029a7bad8b85b0f24642a1774b6Ji Yang if (gsmInboundSmsHandler != null) { 110dc7411e9fc8ac029a7bad8b85b0f24642a1774b6Ji Yang gsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_START_ACCEPTING_SMS); 111dc7411e9fc8ac029a7bad8b85b0f24642a1774b6Ji Yang } 112dc7411e9fc8ac029a7bad8b85b0f24642a1774b6Ji Yang if (cdmaInboundSmsHandler != null) { 113dc7411e9fc8ac029a7bad8b85b0f24642a1774b6Ji Yang cdmaInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_START_ACCEPTING_SMS); 114dc7411e9fc8ac029a7bad8b85b0f24642a1774b6Ji Yang } 1158f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang } 1168f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang 1178f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang private SmsBroadcastUndelivered(Context context, GsmInboundSmsHandler gsmInboundSmsHandler, 1180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby CdmaInboundSmsHandler cdmaInboundSmsHandler) { 1190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mResolver = context.getContentResolver(); 1200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mGsmInboundSmsHandler = gsmInboundSmsHandler; 1210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mCdmaInboundSmsHandler = cdmaInboundSmsHandler; 1220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 123a83613955a113b805729cd415aca50707529208aAmit Mahajan UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 124a83613955a113b805729cd415aca50707529208aAmit Mahajan 125a83613955a113b805729cd415aca50707529208aAmit Mahajan if (userManager.isUserUnlocked()) { 126a83613955a113b805729cd415aca50707529208aAmit Mahajan new ScanRawTableThread().start(); 127a83613955a113b805729cd415aca50707529208aAmit Mahajan } else { 128a83613955a113b805729cd415aca50707529208aAmit Mahajan IntentFilter userFilter = new IntentFilter(); 129a83613955a113b805729cd415aca50707529208aAmit Mahajan userFilter.addAction(Intent.ACTION_USER_UNLOCKED); 130a83613955a113b805729cd415aca50707529208aAmit Mahajan context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, userFilter, null, 131a83613955a113b805729cd415aca50707529208aAmit Mahajan null); 132a83613955a113b805729cd415aca50707529208aAmit Mahajan } 1330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 1360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Scan the raw table for complete SMS messages to broadcast, and old PDUs to delete. 1370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 1380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private void scanRawTable() { 1398f21e0c6528f015924d153350dd2a717d3b51f66Ji Yang if (DBG) Rlog.d(TAG, "scanning raw table for undelivered messages"); 1400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby long startTime = System.nanoTime(); 1410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby HashMap<SmsReferenceKey, Integer> multiPartReceivedCount = 1420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby new HashMap<SmsReferenceKey, Integer>(4); 1430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby HashSet<SmsReferenceKey> oldMultiPartMessages = new HashSet<SmsReferenceKey>(4); 1440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Cursor cursor = null; 1450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby try { 1466e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan // query only non-deleted ones 1476e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan cursor = mResolver.query(InboundSmsHandler.sRawUri, PDU_PENDING_MESSAGE_PROJECTION, 1486e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan "deleted = 0", null, 1496e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan null); 1500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (cursor == null) { 1510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.e(TAG, "error getting pending message cursor"); 1520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return; 1530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby boolean isCurrentFormat3gpp2 = InboundSmsHandler.isCurrentFormat3gpp2(); 1560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby while (cursor.moveToNext()) { 1570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby InboundSmsTracker tracker; 1580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby try { 159871a2ec0bc8e8198aeb1913e7bf6cb22a7ff3604Amit Mahajan tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(cursor, 160871a2ec0bc8e8198aeb1913e7bf6cb22a7ff3604Amit Mahajan isCurrentFormat3gpp2); 1610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } catch (IllegalArgumentException e) { 1620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.e(TAG, "error loading SmsTracker: " + e); 1630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby continue; 1640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (tracker.getMessageCount() == 1) { 1670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // deliver single-part message 1680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby broadcastSms(tracker); 1690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } else { 1700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby SmsReferenceKey reference = new SmsReferenceKey(tracker); 1710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Integer receivedCount = multiPartReceivedCount.get(reference); 1720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (receivedCount == null) { 1730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby multiPartReceivedCount.put(reference, 1); // first segment seen 1740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (tracker.getTimestamp() < 1750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby (System.currentTimeMillis() - PARTIAL_SEGMENT_EXPIRE_AGE)) { 1760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // older than 30 days; delete if we don't find all the segments 1770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby oldMultiPartMessages.add(reference); 1780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } else { 1800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby int newCount = receivedCount + 1; 1810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (newCount == tracker.getMessageCount()) { 1820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // looks like we've got all the pieces; send a single tracker 1830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // to state machine which will find the other pieces to broadcast 1840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (DBG) Rlog.d(TAG, "found complete multi-part message"); 1850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby broadcastSms(tracker); 1860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // don't delete this old message until after we broadcast it 1870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby oldMultiPartMessages.remove(reference); 1880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } else { 1890d4bcdf379842af4b6304809156971e926f374f0Jake Hamby multiPartReceivedCount.put(reference, newCount); 1900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1910d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1920d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1930d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1940d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // Delete old incomplete message segments 1950d4bcdf379842af4b6304809156971e926f374f0Jake Hamby for (SmsReferenceKey message : oldMultiPartMessages) { 1966e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan // delete permanently 1976e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan int rows = mResolver.delete(InboundSmsHandler.sRawUriPermanentDelete, 1986e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan InboundSmsHandler.SELECT_BY_REFERENCE, message.getDeleteWhereArgs()); 1990d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (rows == 0) { 2000d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.e(TAG, "No rows were deleted from raw table!"); 2010d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } else if (DBG) { 2020d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.d(TAG, "Deleted " + rows + " rows from raw table for incomplete " 2030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby + message.mMessageCount + " part message"); 2040d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2050d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2060d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } catch (SQLException e) { 2070d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.e(TAG, "error reading pending SMS messages", e); 2080d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } finally { 2090d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (cursor != null) { 2100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby cursor.close(); 2110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (DBG) Rlog.d(TAG, "finished scanning raw table in " 2130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby + ((System.nanoTime() - startTime) / 1000000) + " ms"); 2140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 2170d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 2180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Send tracker to appropriate (3GPP or 3GPP2) inbound SMS handler for broadcast. 2190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 2200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private void broadcastSms(InboundSmsTracker tracker) { 2210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby InboundSmsHandler handler; 2220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (tracker.is3gpp2()) { 2230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby handler = mCdmaInboundSmsHandler; 2240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } else { 2250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby handler = mGsmInboundSmsHandler; 2260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (handler != null) { 2280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby handler.sendMessage(InboundSmsHandler.EVENT_BROADCAST_SMS, tracker); 2290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } else { 2300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Rlog.e(TAG, "null handler for " + tracker.getFormat() + " format, can't deliver."); 2310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 2340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 2350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Used as the HashMap key for matching concatenated message segments. 2360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 2370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private static class SmsReferenceKey { 2380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby final String mAddress; 2390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby final int mReferenceNumber; 2400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby final int mMessageCount; 2410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 2420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby SmsReferenceKey(InboundSmsTracker tracker) { 2430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mAddress = tracker.getAddress(); 2440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mReferenceNumber = tracker.getReferenceNumber(); 2450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mMessageCount = tracker.getMessageCount(); 2460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 2480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby String[] getDeleteWhereArgs() { 2490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return new String[]{mAddress, Integer.toString(mReferenceNumber), 2500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Integer.toString(mMessageCount)}; 2510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 2530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby @Override 2540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby public int hashCode() { 2550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return ((mReferenceNumber * 31) + mMessageCount) * 31 + mAddress.hashCode(); 2560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 2580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby @Override 2590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby public boolean equals(Object o) { 2600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (o instanceof SmsReferenceKey) { 2610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby SmsReferenceKey other = (SmsReferenceKey) o; 2620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return other.mAddress.equals(mAddress) 2630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby && (other.mReferenceNumber == mReferenceNumber) 2640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby && (other.mMessageCount == mMessageCount); 2650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return false; 2670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 2690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby} 270