10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/* 20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2008 The Android Open Source Project 30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License. 60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at 70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software 110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and 140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License. 150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony; 180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 19032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_DELIVERY_IND; 20032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND; 21032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_READ_ORIG_IND; 220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.Activity; 237fce994eb223105829becb6c26e3af7a9739752cDianne Hackbornimport android.app.AppOpsManager; 24932f590aadc3cfac86cc3972db5eb7013f94780dDianne Hackbornimport android.app.BroadcastOptions; 250d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.BroadcastReceiver; 260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.ComponentName; 27b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.content.ContentValues; 280d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.Context; 290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent; 309e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajanimport android.content.IntentFilter; 310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.ServiceConnection; 32b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.database.Cursor; 33b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.database.DatabaseUtils; 34b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.database.sqlite.SQLiteException; 35b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.database.sqlite.SqliteWrapper; 36b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.net.Uri; 37038b5c11030741f103c15741db74068ce099cb53Shri Bordeimport android.os.Bundle; 380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.IBinder; 39932f590aadc3cfac86cc3972db5eb7013f94780dDianne Hackbornimport android.os.IDeviceIdleController; 400825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.RemoteException; 41932f590aadc3cfac86cc3972db5eb7013f94780dDianne Hackbornimport android.os.ServiceManager; 42a2ce002a0327f0deb079cc6acad1c493e6ded442Amith Yamasaniimport android.os.UserHandle; 439e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajanimport android.os.UserManager; 44b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.provider.Telephony; 450d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.provider.Telephony.Sms.Intents; 46032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport android.telephony.Rlog; 47f1aeeb51f2c62420012122e0ccc75b3940c570e4Ye Wenimport android.telephony.SmsManager; 48a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.SubscriptionManager; 49b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wenimport android.util.Log; 500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 51d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils; 5272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang 5372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yangimport java.util.HashMap; 5472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang 55032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport com.google.android.mms.MmsException; 56032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport com.google.android.mms.pdu.DeliveryInd; 57032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport com.google.android.mms.pdu.GenericPdu; 58032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport com.google.android.mms.pdu.NotificationInd; 59032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport com.google.android.mms.pdu.PduHeaders; 60032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport com.google.android.mms.pdu.PduParser; 61032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport com.google.android.mms.pdu.PduPersister; 62032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport com.google.android.mms.pdu.ReadOrigInd; 63d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka 640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/** 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WAP push handler class. 660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * @hide 680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 690d4bcdf379842af4b6304809156971e926f374f0Jake Hambypublic class WapPushOverSms implements ServiceConnection { 700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private static final String TAG = "WAP PUSH"; 71932f590aadc3cfac86cc3972db5eb7013f94780dDianne Hackborn private static final boolean DBG = false; 720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final Context mContext; 7460a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan private IDeviceIdleController mDeviceIdleController; 75932f590aadc3cfac86cc3972db5eb7013f94780dDianne Hackborn 76932f590aadc3cfac86cc3972db5eb7013f94780dDianne Hackborn private String mWapPushManagerPackage; 770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** Assigned from ServiceConnection callback on main threaad. */ 790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private volatile IWapPushManager mWapPushManager; 800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 819e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan /** Broadcast receiver that binds to WapPushManager when the user unlocks the phone for the 829e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan * first time after reboot and the credential-encrypted storage is available. 839e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan */ 849e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 859e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan @Override 869e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan public void onReceive(final Context context, Intent intent) { 879e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan Rlog.d(TAG, "Received broadcast " + intent.getAction()); 889e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) { 899e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan new BindServiceThread(mContext).start(); 909e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan } 919e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan } 929e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan }; 939e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan 949e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan private class BindServiceThread extends Thread { 959e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan private final Context context; 969e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan 979e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan private BindServiceThread(Context context) { 989e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan this.context = context; 999e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan } 1009e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan 1019e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan @Override 1029e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan public void run() { 1039e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan bindWapPushManagerService(context); 1049e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan } 1059e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan } 1069e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan 1079e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan private void bindWapPushManagerService(Context context) { 1089e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan Intent intent = new Intent(IWapPushManager.class.getName()); 1099e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0); 1109e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan intent.setComponent(comp); 1119e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan if (comp == null || !context.bindService(intent, this, Context.BIND_AUTO_CREATE)) { 1129e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan Rlog.e(TAG, "bindService() for wappush manager failed"); 1139e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan } else { 1149e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan synchronized (this) { 1159e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan mWapPushManagerPackage = comp.getPackageName(); 1169e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan } 1179e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan if (DBG) Rlog.v(TAG, "bindService() for wappush manager succeeded"); 1189e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan } 1199e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan } 1209e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan 1210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby @Override 1220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby public void onServiceConnected(ComponentName name, IBinder service) { 1230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mWapPushManager = IWapPushManager.Stub.asInterface(service); 1240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (DBG) Rlog.v(TAG, "wappush manager connected to " + hashCode()); 1250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby @Override 1280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby public void onServiceDisconnected(ComponentName name) { 1290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mWapPushManager = null; 1300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (DBG) Rlog.v(TAG, "wappush manager disconnected."); 1310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby public WapPushOverSms(Context context) { 1340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mContext = context; 13560a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan mDeviceIdleController = TelephonyComponentFactory.getInstance().getIDeviceIdleController(); 1369e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan 1379e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1389e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan 1399e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan if (userManager.isUserUnlocked()) { 1409e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan bindWapPushManagerService(mContext); 14116d259bfedada60d6b772ee0c640df58830527dfWink Saville } else { 1429e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan IntentFilter userFilter = new IntentFilter(); 1439e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan userFilter.addAction(Intent.ACTION_USER_UNLOCKED); 1449e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan context.registerReceiver(mBroadcastReceiver, userFilter); 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 14860a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan public void dispose() { 14916d259bfedada60d6b772ee0c640df58830527dfWink Saville if (mWapPushManager != null) { 15016d259bfedada60d6b772ee0c640df58830527dfWink Saville if (DBG) Rlog.v(TAG, "dispose: unbind wappush manager"); 15116d259bfedada60d6b772ee0c640df58830527dfWink Saville mContext.unbindService(this); 15216d259bfedada60d6b772ee0c640df58830527dfWink Saville } else { 15316d259bfedada60d6b772ee0c640df58830527dfWink Saville Rlog.e(TAG, "dispose: not bound to a wappush manager"); 15416d259bfedada60d6b772ee0c640df58830527dfWink Saville } 1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 15872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * Decodes the wap push pdu. The decoded result is wrapped inside the {@link DecodedResult} 15972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * object. The caller of this method should check {@link DecodedResult#statusCode} for the 16072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * decoding status. It can have the following values. 1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 16272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * Activity.RESULT_OK - the wap push pdu is successfully decoded and should be further processed 16372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * Intents.RESULT_SMS_HANDLED - the wap push pdu should be ignored. 16472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * Intents.RESULT_SMS_GENERIC_ERROR - the pdu is invalid. 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 16672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang private DecodedResult decodeWapPdu(byte[] pdu, InboundSmsHandler handler) { 16772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang DecodedResult result = new DecodedResult(); 1680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (DBG) Rlog.d(TAG, "Rx: " + IccUtils.bytesToHexString(pdu)); 1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 170023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby try { 171023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby int index = 0; 172023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby int transactionId = pdu[index++] & 0xFF; 173023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby int pduType = pdu[index++] & 0xFF; 174023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby 175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // Should we "abort" if no subId for now just no supplying extra param below 176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville int phoneId = handler.getPhone().getPhoneId(); 177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 178023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) && 179023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) { 180023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby index = mContext.getResources().getInteger( 181023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby com.android.internal.R.integer.config_valid_wappush_index); 182023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (index != -1) { 183023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby transactionId = pdu[index++] & 0xff; 184023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby pduType = pdu[index++] & 0xff; 185023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (DBG) 186023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby Rlog.d(TAG, "index = " + index + " PDU Type = " + pduType + 187023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby " transactionID = " + transactionId); 188023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby 189023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby // recheck wap push pduType 190023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) 191023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby && (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) { 192023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (DBG) Rlog.w(TAG, "Received non-PUSH WAP PDU. Type = " + pduType); 19372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.statusCode = Intents.RESULT_SMS_HANDLED; 19472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang return result; 195023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby } 196023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby } else { 19713fa971b6c6eab1578f4732c8de6fa2ba3b57ce6Sungmin Choi if (DBG) Rlog.w(TAG, "Received non-PUSH WAP PDU. Type = " + pduType); 19872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.statusCode = Intents.RESULT_SMS_HANDLED; 19972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang return result; 20013fa971b6c6eab1578f4732c8de6fa2ba3b57ce6Sungmin Choi } 20113fa971b6c6eab1578f4732c8de6fa2ba3b57ce6Sungmin Choi } 2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 20360a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan WspTypeDecoder pduDecoder = 20460a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan TelephonyComponentFactory.getInstance().makeWspTypeDecoder(pdu); 205023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby 206023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby /** 207023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * Parse HeaderLen(unsigned integer). 208023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * From wap-230-wsp-20010705-a section 8.1.2 209023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * The maximum size of a uintvar is 32 bits. 210023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * So it will be encoded in no more than 5 octets. 211023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby */ 212023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (pduDecoder.decodeUintvarInteger(index) == false) { 213023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (DBG) Rlog.w(TAG, "Received PDU. Header Length error."); 21472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.statusCode = Intents.RESULT_SMS_GENERIC_ERROR; 21572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang return result; 216023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby } 217023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby int headerLength = (int) pduDecoder.getValue32(); 218023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby index += pduDecoder.getDecodedDataLength(); 219023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby 220023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby int headerStartIndex = index; 221023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby 222023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby /** 223023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * Parse Content-Type. 224023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * From wap-230-wsp-20010705-a section 8.4.2.24 225023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * 226023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * Content-type-value = Constrained-media | Content-general-form 227023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * Content-general-form = Value-length Media-type 228023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * Media-type = (Well-known-media | Extension-Media) *(Parameter) 229023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * Value-length = Short-length | (Length-quote Length) 230023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * Short-length = <Any octet 0-30> (octet <= WAP_PDU_SHORT_LENGTH_MAX) 231023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * Length-quote = <Octet 31> (WAP_PDU_LENGTH_QUOTE) 232023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * Length = Uintvar-integer 233023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby */ 234023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (pduDecoder.decodeContentType(index) == false) { 235023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (DBG) Rlog.w(TAG, "Received PDU. Header Content-Type error."); 23672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.statusCode = Intents.RESULT_SMS_GENERIC_ERROR; 23772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang return result; 238023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby } 2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 240023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby String mimeType = pduDecoder.getValueString(); 241023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby long binaryContentType = pduDecoder.getValue32(); 242023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby index += pduDecoder.getDecodedDataLength(); 2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 244023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby byte[] header = new byte[headerLength]; 245023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby System.arraycopy(pdu, headerStartIndex, header, 0, header.length); 2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 247023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby byte[] intentData; 2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 249023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) { 250023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby intentData = pdu; 251023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby } else { 252023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby int dataIndex = headerStartIndex + headerLength; 253023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby intentData = new byte[pdu.length - dataIndex]; 254023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby System.arraycopy(pdu, dataIndex, intentData, 0, intentData.length); 2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 257ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry int[] subIds = SubscriptionManager.getSubId(phoneId); 258ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry int subId = (subIds != null) && (subIds.length > 0) ? subIds[0] 259ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry : SmsManager.getDefaultSmsSubscriptionId(); 260ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry 261722b1b5403842bf0595ba8c11e7f01fdb9844518Abhijith Shastry // Continue if PDU parsing fails: the default messaging app may successfully parse the 262722b1b5403842bf0595ba8c11e7f01fdb9844518Abhijith Shastry // same PDU. 263722b1b5403842bf0595ba8c11e7f01fdb9844518Abhijith Shastry GenericPdu parsedPdu = null; 264722b1b5403842bf0595ba8c11e7f01fdb9844518Abhijith Shastry try { 265722b1b5403842bf0595ba8c11e7f01fdb9844518Abhijith Shastry parsedPdu = new PduParser(intentData, shouldParseContentDisposition(subId)).parse(); 266722b1b5403842bf0595ba8c11e7f01fdb9844518Abhijith Shastry } catch (Exception e) { 267722b1b5403842bf0595ba8c11e7f01fdb9844518Abhijith Shastry Rlog.e(TAG, "Unable to parse PDU: " + e.toString()); 268722b1b5403842bf0595ba8c11e7f01fdb9844518Abhijith Shastry } 269722b1b5403842bf0595ba8c11e7f01fdb9844518Abhijith Shastry 270ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry if (parsedPdu != null && parsedPdu.getMessageType() == MESSAGE_TYPE_NOTIFICATION_IND) { 271ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry final NotificationInd nInd = (NotificationInd) parsedPdu; 272ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry if (nInd.getFrom() != null 273ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry && BlockChecker.isBlocked(mContext, nInd.getFrom().getString())) { 27472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.statusCode = Intents.RESULT_SMS_HANDLED; 27572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang return result; 276ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry } 277ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry } 278ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry 279023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby /** 280023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * Seek for application ID field in WSP header. 281023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * If application ID is found, WapPushManager substitute the message 282023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * processing. Since WapPushManager is optional module, if WapPushManager 283023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby * is not found, legacy message processing will be continued. 284023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby */ 285023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (pduDecoder.seekXWapApplicationId(index, index + headerLength - 1)) { 286023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby index = (int) pduDecoder.getValue32(); 287023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby pduDecoder.decodeXWapApplicationId(index); 288023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby String wapAppId = pduDecoder.getValueString(); 289023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (wapAppId == null) { 290023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby wapAppId = Integer.toString((int) pduDecoder.getValue32()); 291023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby } 29272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.wapAppId = wapAppId; 293023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby String contentType = ((mimeType == null) ? 294023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby Long.toString(binaryContentType) : mimeType); 29572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.contentType = contentType; 296023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby if (DBG) Rlog.v(TAG, "appid found: " + wapAppId + ":" + contentType); 29772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 298023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby 29972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.subId = subId; 30072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.phoneId = phoneId; 30172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.parsedPdu = parsedPdu; 30272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.mimeType = mimeType; 30372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.transactionId = transactionId; 30472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.pduType = pduType; 30572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.header = header; 30672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.intentData = intentData; 30772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.contentTypeParameters = pduDecoder.getContentParameters(); 30872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.statusCode = Activity.RESULT_OK; 30972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } catch (ArrayIndexOutOfBoundsException aie) { 31072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang // 0-byte WAP PDU or other unexpected WAP PDU contents can easily throw this; 31172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang // log exception string without stack trace and return false. 31272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang Rlog.e(TAG, "ignoring dispatchWapPdu() array index exception: " + aie); 31372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.statusCode = Intents.RESULT_SMS_GENERIC_ERROR; 31472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 31572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang return result; 31672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 317023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby 31872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang /** 31972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * Dispatches inbound messages that are in the WAP PDU format. See 32072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * wap-230-wsp-20010705-a section 8 for details on the WAP PDU format. 32172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * 32272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * @param pdu The WAP PDU, made up of one or more SMS PDUs 32372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * @return a result code from {@link android.provider.Telephony.Sms.Intents}, or 32472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * {@link Activity#RESULT_OK} if the message has been broadcast 32572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * to applications 32672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang */ 32772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang public int dispatchWapPdu(byte[] pdu, BroadcastReceiver receiver, InboundSmsHandler handler) { 32872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang DecodedResult result = decodeWapPdu(pdu, handler); 32972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (result.statusCode != Activity.RESULT_OK) { 33072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang return result.statusCode; 33172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 33372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (SmsManager.getDefault().getAutoPersisting()) { 33472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang // Store the wap push data in telephony 33572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang writeInboxMessage(result.subId, result.parsedPdu); 33672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 33872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang /** 33972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * If the pdu has application ID, WapPushManager substitute the message 34072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * processing. Since WapPushManager is optional module, if WapPushManager 34172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * is not found, legacy message processing will be continued. 34272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang */ 34372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (result.wapAppId != null) { 34472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang try { 34572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang boolean processFurther = true; 34672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang IWapPushManager wapPushMan = mWapPushManager; 34772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang 34872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (wapPushMan == null) { 34972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (DBG) Rlog.w(TAG, "wap push manager not found!"); 35072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } else { 3519e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan synchronized (this) { 3529e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan mDeviceIdleController.addPowerSaveTempWhitelistAppForMms( 3539e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan mWapPushManagerPackage, 0, "mms-mgr"); 3549e271688595d0281fe73acb16eb70925be9cf9b5Amit Mahajan } 35572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang 35672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang Intent intent = new Intent(); 35772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.putExtra("transactionId", result.transactionId); 35872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.putExtra("pduType", result.pduType); 35972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.putExtra("header", result.header); 36072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.putExtra("data", result.intentData); 36172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.putExtra("contentTypeParameters", result.contentTypeParameters); 36272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang SubscriptionManager.putPhoneIdAndSubIdExtra(intent, result.phoneId); 36372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang 36472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang int procRet = wapPushMan.processMessage( 36572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang result.wapAppId, result.contentType, intent); 36672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (DBG) Rlog.v(TAG, "procRet:" + procRet); 36772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if ((procRet & WapPushManagerParams.MESSAGE_HANDLED) > 0 36872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang && (procRet & WapPushManagerParams.FURTHER_PROCESSING) == 0) { 36972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang processFurther = false; 37072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 371932f590aadc3cfac86cc3972db5eb7013f94780dDianne Hackborn } 37272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (!processFurther) { 37372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang return Intents.RESULT_SMS_HANDLED; 37472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 37572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } catch (RemoteException e) { 37672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (DBG) Rlog.w(TAG, "remote func failed..."); 377023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby } 37872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 37972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (DBG) Rlog.v(TAG, "fall back to existing handler"); 3805c3b6658d82f3af57161d5a34385dd95ea0f1abbDavid Braun 38172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (result.mimeType == null) { 38272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (DBG) Rlog.w(TAG, "Header Content-Type error."); 383023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby return Intents.RESULT_SMS_GENERIC_ERROR; 384023346cf9050c146a36eedd14886d0e9a679dc49Jake Hamby } 38572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang 38672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang Intent intent = new Intent(Intents.WAP_PUSH_DELIVER_ACTION); 38772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.setType(result.mimeType); 38872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.putExtra("transactionId", result.transactionId); 38972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.putExtra("pduType", result.pduType); 39072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.putExtra("header", result.header); 39172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.putExtra("data", result.intentData); 39272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.putExtra("contentTypeParameters", result.contentTypeParameters); 39372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang SubscriptionManager.putPhoneIdAndSubIdExtra(intent, result.phoneId); 39472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang 39572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang // Direct the intent to only the default MMS app. If we can't find a default MMS app 39672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang // then sent it to all broadcast receivers. 39772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang ComponentName componentName = SmsApplication.getDefaultMmsApplication(mContext, true); 39872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang Bundle options = null; 39972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (componentName != null) { 40072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang // Deliver MMS message only to this receiver 40172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang intent.setComponent(componentName); 40272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang if (DBG) Rlog.v(TAG, "Delivering MMS to: " + componentName.getPackageName() + 40372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang " " + componentName.getClassName()); 40472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang try { 40572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang long duration = mDeviceIdleController.addPowerSaveTempWhitelistAppForMms( 40672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang componentName.getPackageName(), 0, "mms-app"); 40772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang BroadcastOptions bopts = BroadcastOptions.makeBasic(); 40872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang bopts.setTemporaryAppWhitelistDuration(duration); 40972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang options = bopts.toBundle(); 41072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } catch (RemoteException e) { 41172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 41272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 41372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang 41472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang handler.dispatchIntent(intent, getPermissionForType(result.mimeType), 41572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang getAppOpsPermissionForIntent(result.mimeType), options, receiver, 41672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang UserHandle.SYSTEM); 41772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang return Activity.RESULT_OK; 41872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 41972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang 42072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang /** 42172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * Check whether the pdu is a MMS WAP push pdu that should be dispatched to the SMS app. 42272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang */ 42372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang public boolean isWapPushForMms(byte[] pdu, InboundSmsHandler handler) { 42472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang DecodedResult result = decodeWapPdu(pdu, handler); 42572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang return result.statusCode == Activity.RESULT_OK 42672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang && WspTypeDecoder.CONTENT_TYPE_B_MMS.equals(result.mimeType); 4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 428b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 429032e0398ba2770edd52c543482afbae6f92ff29bYe Wen private static boolean shouldParseContentDisposition(int subId) { 430032e0398ba2770edd52c543482afbae6f92ff29bYe Wen return SmsManager 431032e0398ba2770edd52c543482afbae6f92ff29bYe Wen .getSmsManagerForSubscriptionId(subId) 432032e0398ba2770edd52c543482afbae6f92ff29bYe Wen .getCarrierConfigValues() 433032e0398ba2770edd52c543482afbae6f92ff29bYe Wen .getBoolean(SmsManager.MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION, true); 434032e0398ba2770edd52c543482afbae6f92ff29bYe Wen } 435032e0398ba2770edd52c543482afbae6f92ff29bYe Wen 436ba51280f53e677ac527b11bd9a5dfa819740f70aAbhijith Shastry private void writeInboxMessage(int subId, GenericPdu pdu) { 437b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (pdu == null) { 438b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "Invalid PUSH PDU"); 439b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 440b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final PduPersister persister = PduPersister.getPduPersister(mContext); 441b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final int type = pdu.getMessageType(); 442b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen try { 443b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen switch (type) { 444b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen case MESSAGE_TYPE_DELIVERY_IND: 445b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen case MESSAGE_TYPE_READ_ORIG_IND: { 446b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final long threadId = getDeliveryOrReadReportThreadId(mContext, pdu); 447b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (threadId == -1) { 448b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen // The associated SendReq isn't found, therefore skip 449b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen // processing this PDU. 450b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "Failed to find delivery or read report's thread id"); 451b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen break; 452b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 453b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final Uri uri = persister.persist( 454b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen pdu, 455b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Telephony.Mms.Inbox.CONTENT_URI, 456b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen true/*createThreadId*/, 457b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen true/*groupMmsEnabled*/, 458b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen null/*preOpenedFiles*/); 459b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (uri == null) { 460b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "Failed to persist delivery or read report"); 461b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen break; 462b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 463b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen // Update thread ID for ReadOrigInd & DeliveryInd. 464b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final ContentValues values = new ContentValues(1); 465b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen values.put(Telephony.Mms.THREAD_ID, threadId); 466b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (SqliteWrapper.update( 467b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen mContext, 468b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen mContext.getContentResolver(), 469b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen uri, 470b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen values, 471b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen null/*where*/, 472b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen null/*selectionArgs*/) != 1) { 473b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "Failed to update delivery or read report thread id"); 474b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 475b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen break; 476b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 477b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen case MESSAGE_TYPE_NOTIFICATION_IND: { 478b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final NotificationInd nInd = (NotificationInd) pdu; 479b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 4809dbb6ad72f064bde732111fe40ded4543b34295eYe Wen Bundle configs = SmsManager.getSmsManagerForSubscriptionId(subId) 481917cd56bf468b599ae1aca56773d18ee4a5d4df8Tom Taylor .getCarrierConfigValues(); 482038b5c11030741f103c15741db74068ce099cb53Shri Borde if (configs != null && configs.getBoolean( 483038b5c11030741f103c15741db74068ce099cb53Shri Borde SmsManager.MMS_CONFIG_APPEND_TRANSACTION_ID, false)) { 484b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final byte [] contentLocation = nInd.getContentLocation(); 485b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if ('=' == contentLocation[contentLocation.length - 1]) { 486b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen byte [] transactionId = nInd.getTransactionId(); 487b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen byte [] contentLocationWithId = new byte [contentLocation.length 488b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen + transactionId.length]; 489b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen System.arraycopy(contentLocation, 0, contentLocationWithId, 490b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 0, contentLocation.length); 491b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen System.arraycopy(transactionId, 0, contentLocationWithId, 492b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen contentLocation.length, transactionId.length); 493b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen nInd.setContentLocation(contentLocationWithId); 494b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 495b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 496b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (!isDuplicateNotification(mContext, nInd)) { 497b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final Uri uri = persister.persist( 498b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen pdu, 499b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Telephony.Mms.Inbox.CONTENT_URI, 500b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen true/*createThreadId*/, 501b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen true/*groupMmsEnabled*/, 502b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen null/*preOpenedFiles*/); 503b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (uri == null) { 504b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "Failed to save MMS WAP push notification ind"); 505b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 506b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } else { 507b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.d(TAG, "Skip storing duplicate MMS WAP push notification ind: " 508b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen + new String(nInd.getContentLocation())); 509b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 510b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen break; 511b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 512b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen default: 513b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Log.e(TAG, "Received unrecognized WAP Push PDU."); 514b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 515b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } catch (MmsException e) { 516b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Log.e(TAG, "Failed to save MMS WAP push data: type=" + type, e); 517b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } catch (RuntimeException e) { 518b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Log.e(TAG, "Unexpected RuntimeException in persisting MMS WAP push data", e); 519b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 520b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 521b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 522b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 523b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen private static final String THREAD_ID_SELECTION = 524b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Telephony.Mms.MESSAGE_ID + "=? AND " + Telephony.Mms.MESSAGE_TYPE + "=?"; 525b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 526b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen private static long getDeliveryOrReadReportThreadId(Context context, GenericPdu pdu) { 527b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen String messageId; 528b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (pdu instanceof DeliveryInd) { 529b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen messageId = new String(((DeliveryInd) pdu).getMessageId()); 530b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } else if (pdu instanceof ReadOrigInd) { 531b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen messageId = new String(((ReadOrigInd) pdu).getMessageId()); 532b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } else { 533b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "WAP Push data is neither delivery or read report type: " 534b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen + pdu.getClass().getCanonicalName()); 535b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen return -1L; 536b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 537b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Cursor cursor = null; 538b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen try { 539b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen cursor = SqliteWrapper.query( 540b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen context, 541b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen context.getContentResolver(), 542b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Telephony.Mms.CONTENT_URI, 543b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen new String[]{ Telephony.Mms.THREAD_ID }, 544b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen THREAD_ID_SELECTION, 545b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen new String[]{ 546b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen DatabaseUtils.sqlEscapeString(messageId), 547b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Integer.toString(PduHeaders.MESSAGE_TYPE_SEND_REQ) 548b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen }, 549b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen null/*sortOrder*/); 550b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (cursor != null && cursor.moveToFirst()) { 551b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen return cursor.getLong(0); 552b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 553b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } catch (SQLiteException e) { 554b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "Failed to query delivery or read report thread id", e); 555b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } finally { 556b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (cursor != null) { 557b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen cursor.close(); 558b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 559b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 560b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen return -1L; 561b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 562b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 563b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen private static final String LOCATION_SELECTION = 564b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Telephony.Mms.MESSAGE_TYPE + "=? AND " + Telephony.Mms.CONTENT_LOCATION + " =?"; 565b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen 566b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen private static boolean isDuplicateNotification(Context context, NotificationInd nInd) { 567b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen final byte[] rawLocation = nInd.getContentLocation(); 568b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (rawLocation != null) { 569b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen String location = new String(rawLocation); 570b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen String[] selectionArgs = new String[] { location }; 571b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Cursor cursor = null; 572b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen try { 573b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen cursor = SqliteWrapper.query( 574b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen context, 575b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen context.getContentResolver(), 576b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Telephony.Mms.CONTENT_URI, 577b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen new String[]{Telephony.Mms._ID}, 578b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen LOCATION_SELECTION, 579b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen new String[]{ 580b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND), 581b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen new String(rawLocation) 582b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen }, 583b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen null/*sortOrder*/); 584b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (cursor != null && cursor.getCount() > 0) { 585b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen // We already received the same notification before. 586b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen return true; 587b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 588b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } catch (SQLiteException e) { 589b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen Rlog.e(TAG, "failed to query existing notification ind", e); 590b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } finally { 591b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen if (cursor != null) { 592b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen cursor.close(); 593b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 594b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 595b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 596b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen return false; 597b29851580bba4a13ddbf7a534d8b09295eb2c60fYe Wen } 598ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan 59960a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan public static String getPermissionForType(String mimeType) { 600ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan String permission; 601ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan if (WspTypeDecoder.CONTENT_TYPE_B_MMS.equals(mimeType)) { 602ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan permission = android.Manifest.permission.RECEIVE_MMS; 603ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan } else { 604ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan permission = android.Manifest.permission.RECEIVE_WAP_PUSH; 605ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan } 606ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan return permission; 607ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan } 608ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan 60960a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan public static int getAppOpsPermissionForIntent(String mimeType) { 610ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan int appOp; 611ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan if (WspTypeDecoder.CONTENT_TYPE_B_MMS.equals(mimeType)) { 612ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan appOp = AppOpsManager.OP_RECEIVE_MMS; 613ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan } else { 614ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan appOp = AppOpsManager.OP_RECEIVE_WAP_PUSH; 615ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan } 616ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan return appOp; 617ba798021d26fc3690a16a2c9b4f41f44a1122b49Amit Mahajan } 61872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang 61972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang /** 62072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang * Place holder for decoded Wap pdu data. 62172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang */ 62272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang private final class DecodedResult { 62372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang String mimeType; 62472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang String contentType; 62572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang int transactionId; 62672f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang int pduType; 62772f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang int phoneId; 62872f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang int subId; 62972f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang byte[] header; 63072f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang String wapAppId; 63172f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang byte[] intentData; 63272f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang HashMap<String, String> contentTypeParameters; 63372f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang GenericPdu parsedPdu; 63472f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang int statusCode; 63572f7fc997b09204bf01ccaac34ac4b9bd91d954bJi Yang } 6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 637