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