TransactionService.java revision 72735c62aba8fd2a9420a0f9f83d22543e3c164f
172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/*
272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2007-2008 Esmertec AG.
372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2007-2008 The Android Open Source Project
472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * you may not use this file except in compliance with the License.
772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * You may obtain a copy of the License at
872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
1072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
1172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * See the License for the specific language governing permissions and
1572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * limitations under the License.
1672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
1772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpackage com.android.mms.transaction;
1972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.internal.telephony.Phone;
2172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.R;
2272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.util.RateController;
2372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.google.android.mms.pdu.GenericPdu;
2472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.google.android.mms.pdu.NotificationInd;
2572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.google.android.mms.pdu.PduHeaders;
2672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.google.android.mms.pdu.PduParser;
2772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.google.android.mms.pdu.PduPersister;
2872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.Service;
3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentUris;
3172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context;
3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Intent;
3372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor;
3472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.ConnectivityManager;
3572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.NetworkConnectivityListener;
3672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.NetworkInfo;
3772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri;
3872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Handler;
3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.HandlerThread;
4072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.IBinder;
4172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Looper;
4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Message;
4372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.PowerManager;
4472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.provider.Telephony.Mms;
4572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.provider.Telephony.MmsSms;
4672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.provider.Telephony.MmsSms.PendingMessages;
4772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.TextUtils;
4872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Config;
4972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log;
5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.widget.Toast;
5172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.io.IOException;
5372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.ArrayList;
5472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
5572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/**
5672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * The TransactionService of the MMS Client is responsible for handling requests
5772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * to initiate client-transactions sent from:
5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <ul>
5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <li>The Proxy-Relay (Through Push messages)</li>
6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <li>The composer/viewer activities of the MMS Client (Through intents)</li>
6172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * </ul>
6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * The TransactionService runs locally in the same process as the application.
6372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * It contains a HandlerThread to which messages are posted from the
6472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * intent-receivers of this application.
6572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <p/>
6672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <b>IMPORTANT</b>: This is currently the only instance in the system in
6772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * which simultaneous connectivity to both the mobile data network and
6872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * a Wi-Fi network is allowed. This makes the code for handling network
6972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * connectivity somewhat different than it is in other applications. In
7072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * particular, we want to be able to send or receive MMS messages when
7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * a Wi-Fi connection is active (which implies that there is no connection
7272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * to the mobile data network). This has two main consequences:
7372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <ul>
7472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <li>Testing for current network connectivity ({@link android.net.NetworkInfo#isConnected()} is
7572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * not sufficient. Instead, the correct test is for network availability
7672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * ({@link android.net.NetworkInfo#isAvailable()}).</li>
7772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * <li>If the mobile data network is not in the connected state, but it is available,
7872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * we must initiate setup of the mobile data connection, and defer handling
7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * the MMS transaction until the connection is established.</li>
8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * </ul>
8172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
8272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class TransactionService extends Service implements Observer {
8372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String TAG = "TransactionService";
8472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final boolean DEBUG = false;
8572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
8672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
8872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Used to identify notification intents broadcasted by the
8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * TransactionService when a Transaction is completed.
9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final String TRANSACTION_COMPLETED_ACTION =
9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            "android.intent.action.TRANSACTION_COMPLETED_ACTION";
9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Action for the Intent which is sent by Alarm service to launch
9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * TransactionService.
9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final String ACTION_ONALARM = "android.intent.action.ACTION_ONALARM";
9972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
10072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
10172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Used as extra key in notification intents broadcasted by the TransactionService
10272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * when a Transaction is completed (TRANSACTION_COMPLETED_ACTION intents).
10372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Allowed values for this key are: TransactionState.INITIALIZED,
10472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * TransactionState.SUCCESS, TransactionState.FAILED.
10572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
10672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final String STATE = "state";
10772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
10872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
10972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Used as extra key in notification intents broadcasted by the TransactionService
11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * when a Transaction is completed (TRANSACTION_COMPLETED_ACTION intents).
11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Allowed values for this key are any valid content uri.
11272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
11372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final String STATE_URI = "uri";
11472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
11572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
11672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Used as extra key in notification intents broadcasted by the TransactionService
11772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * when a Transaction is completed (TRANSACTION_COMPLETED_ACTION intents).
11872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Allowed values for this key  are the Uri's of stored messages relevant
11972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * for the completed  Transaction,
12072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * i.e.: Uri of DeliveryInd for DeliveryTransaction,
12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * NotificationInd for NotificationTransaction,
12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * ReadOrigInd for  ReadOrigTransaction,
12372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * null for ReadRecTransaction,
12472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * RetrieveConf for  RetrieveTransaction,
12572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * SendReq for SendTransaction.
12672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
12772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final String CONTENT_URI = "content_uri";
12872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int EVENT_TRANSACTION_REQUEST = 1;
13072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int EVENT_DATA_STATE_CHANGED = 2;
13172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int EVENT_CONTINUE_MMS_CONNECTIVITY = 3;
13272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int EVENT_HANDLE_NEXT_PENDING_TRANSACTION = 4;
13372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int EVENT_QUIT = 100;
13472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
13572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int TOAST_MSG_QUEUED = 1;
13672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int TOAST_DOWNLOAD_LATER = 2;
13772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int TOAST_NONE = -1;
13872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
13972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // How often to extend the use of the MMS APN while a transaction
14072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // is still being processed.
14172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int APN_EXTENSION_WAIT = 30 * 1000;
14272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
14372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private ServiceHandler mServiceHandler;
14472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private Looper mServiceLooper;
14572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final ArrayList<Transaction> mProcessing  = new ArrayList<Transaction>();
14672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final ArrayList<Transaction> mPending  = new ArrayList<Transaction>();
14772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private ConnectivityManager mConnMgr;
14872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private NetworkConnectivityListener mConnectivityListener;
14972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private PowerManager.WakeLock mWakeLock;
15072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public Handler mToastHandler = new Handler() {
15272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        @Override
15372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public void handleMessage(Message msg) {
15472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String str = null;
15572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (msg.what == TOAST_MSG_QUEUED) {
15772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                str = getString(R.string.message_queued);
15872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } else if (msg.what == TOAST_DOWNLOAD_LATER) {
15972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                str = getString(R.string.download_later);
16072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
16172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
16272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (str != null) {
16372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Toast.makeText(TransactionService.this, str,
16472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Toast.LENGTH_LONG).show();
16572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
16672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
16772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    };
16872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
16972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
17072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void onCreate() {
17172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (LOCAL_LOGV) {
17272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "Creating TransactionService");
17372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
17472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
17572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Start up the thread running the service.  Note that we create a
17672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // separate thread because the service normally runs in the process's
17772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // main thread, which we don't want to block.
17872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        HandlerThread thread = new HandlerThread("TransactionService");
17972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        thread.start();
18072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mServiceLooper = thread.getLooper();
18272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mServiceHandler = new ServiceHandler(mServiceLooper);
18372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mConnectivityListener = new NetworkConnectivityListener();
18572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mConnectivityListener.registerHandler(mServiceHandler, EVENT_DATA_STATE_CHANGED);
18672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mConnectivityListener.startListening(this);
18772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
18872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
19072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void onStart(Intent intent, int startId) {
19172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (LOCAL_LOGV) {
19272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "Starting #" + startId + ": " + intent.getExtras());
19372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
19472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
19572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mConnMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
19672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        boolean noNetwork = !isNetworkAvailable();
19772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
19872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (ACTION_ONALARM.equals(intent.getAction()) || (intent.getExtras() == null)) {
19972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Scan database to find all pending operations.
20072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Cursor cursor = PduPersister.getPduPersister(this).getPendingMessages(
20172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    System.currentTimeMillis());
20272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (cursor != null) {
20372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                try {
20472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (cursor.getCount() == 0) {
20572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (LOCAL_LOGV) {
20672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            Log.v(TAG, "No pending messages. Stopping service.");
20772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
20872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        RetryScheduler.setRetryAlarm(this);
20972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        stopSelfIfIdle(startId);
21072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return;
21172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
21272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
21372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    int columnIndexOfMsgId = cursor.getColumnIndexOrThrow(
21472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            PendingMessages.MSG_ID);
21572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    int columnIndexOfMsgType = cursor.getColumnIndexOrThrow(
21672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            PendingMessages.MSG_TYPE);
21772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
21872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    while (cursor.moveToNext()) {
21972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        int msgType = cursor.getInt(columnIndexOfMsgType);
22072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        int transactionType = getTransactionType(msgType);
22172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (noNetwork) {
22272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            onNetworkUnavailable(startId, transactionType);
22372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            return;
22472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
22572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        switch (transactionType) {
22672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            case -1:
22772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                break;
22872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            case Transaction.RETRIEVE_TRANSACTION:
22972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                // If it's a transiently failed transaction,
23072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                // we should retry it in spite of current
23172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                // downloading mode.
23272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                int failureType = cursor.getInt(
23372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        cursor.getColumnIndexOrThrow(
23472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                                PendingMessages.ERROR_TYPE));
23572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                if (!isTransientFailure(failureType)) {
23672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    break;
23772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                }
23872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                // fall-through
23972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            default:
24072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                Uri uri = ContentUris.withAppendedId(
24172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        Mms.CONTENT_URI,
24272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        cursor.getLong(columnIndexOfMsgId));
24372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                TransactionBundle args = new TransactionBundle(
24472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        transactionType, uri.toString());
24572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                // FIXME: We use the same startId for all MMs.
24672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                launchTransaction(startId, args, false);
24772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                break;
24872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
24972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
25072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                } finally {
25172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    cursor.close();
25272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
25372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } else {
25472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (LOCAL_LOGV) {
25572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Log.v(TAG, "No pending messages. Stopping service.");
25672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
25772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                RetryScheduler.setRetryAlarm(this);
25872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                stopSelfIfIdle(startId);
25972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
26072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
26172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // For launching NotificationTransaction and test purpose.
26272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            TransactionBundle args = new TransactionBundle(intent.getExtras());
26372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            launchTransaction(startId, args, noNetwork);
26472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
26572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
26672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
26772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void stopSelfIfIdle(int startId) {
26872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        synchronized (mProcessing) {
26972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (mProcessing.isEmpty() && mPending.isEmpty()) {
27072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                stopSelf(startId);
27172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
27272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
27372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
27472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
27572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static boolean isTransientFailure(int type) {
27672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return (type < MmsSms.ERR_TYPE_GENERIC_PERMANENT) && (type > MmsSms.NO_ERROR);
27772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
27872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
27972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private boolean isNetworkAvailable() {
28072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        NetworkInfo networkInfo = mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
28172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return networkInfo.isAvailable();
28272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
28372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
28472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private int getTransactionType(int msgType) {
28572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        switch (msgType) {
28672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
28772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return Transaction.RETRIEVE_TRANSACTION;
28872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
28972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return Transaction.READREC_TRANSACTION;
29072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
29172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return Transaction.SEND_TRANSACTION;
29272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            default:
29372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Log.w(TAG, "Unrecognized MESSAGE_TYPE: " + msgType);
29472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return -1;
29572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
29672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
29772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
29872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void launchTransaction(int serviceId, TransactionBundle txnBundle, boolean noNetwork) {
29972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (noNetwork) {
30072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            onNetworkUnavailable(serviceId, txnBundle.getTransactionType());
30172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return;
30272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
30372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Message msg = mServiceHandler.obtainMessage(EVENT_TRANSACTION_REQUEST);
30472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        msg.arg1 = serviceId;
30572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        msg.obj = txnBundle;
30672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
30772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (LOCAL_LOGV) {
30872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "Sending: " + msg);
30972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
31072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mServiceHandler.sendMessage(msg);
31172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
31272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
31372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void onNetworkUnavailable(int serviceId, int transactionType) {
31472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int toastType = TOAST_NONE;
31572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (transactionType == Transaction.RETRIEVE_TRANSACTION) {
31672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            toastType = TOAST_DOWNLOAD_LATER;
31772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (transactionType == Transaction.SEND_TRANSACTION) {
31872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            toastType = TOAST_MSG_QUEUED;
31972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
32072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (toastType != TOAST_NONE) {
32172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mToastHandler.sendEmptyMessage(toastType);
32272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
32372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        stopSelf(serviceId);
32472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
32572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
32672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
32772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void onDestroy() {
32872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (LOCAL_LOGV) {
32972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "Destroying TransactionService");
33072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
33172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (!mPending.isEmpty()) {
33272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.i(TAG, "TransactionService exiting with transaction still pending");
33372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
33472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
33572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        releaseWakeLock();
33672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
33772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mConnectivityListener.unregisterHandler(mServiceHandler);
33872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mConnectivityListener.stopListening();
33972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mConnectivityListener = null;
34072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
34172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mServiceHandler.sendEmptyMessage(EVENT_QUIT);
34272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
34372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
34472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
34572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public IBinder onBind(Intent intent) {
34672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return null;
34772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
34872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
34972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
35072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Handle status change of Transaction (The Observable).
35172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
35272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void update(Observable observable) {
35372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Transaction transaction = (Transaction) observable;
35472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int serviceId = transaction.getServiceId();
35572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
35672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            synchronized (mProcessing) {
35772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mProcessing.remove(transaction);
35872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (mPending.size() > 0) {
35972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Message msg = mServiceHandler.obtainMessage(
36072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            EVENT_HANDLE_NEXT_PENDING_TRANSACTION,
36172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            transaction.getConnectionSettings());
36272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    mServiceHandler.sendMessage(msg);
36372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
36472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                else {
36572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    endMmsConnectivity();
36672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
36772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
36872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
36972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Intent intent = new Intent(TRANSACTION_COMPLETED_ACTION);
37072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            TransactionState state = transaction.getState();
37172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            int result = state.getState();
37272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            intent.putExtra(STATE, result);
37372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
37472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            switch (result) {
37572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case TransactionState.SUCCESS:
37672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (LOCAL_LOGV) {
37772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.v(TAG, "Transaction complete: " + serviceId);
37872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
37972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
38072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    intent.putExtra(STATE_URI, state.getContentUri());
38172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
38272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    // Notify user in the system-wide notification area.
38372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    switch (transaction.getType()) {
38472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        case Transaction.NOTIFICATION_TRANSACTION:
38572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        case Transaction.RETRIEVE_TRANSACTION:
38672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            MessagingNotification.updateNewMessageIndicator(this, true);
38772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            MessagingNotification.updateDownloadFailedNotification(this);
38872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            break;
38972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        case Transaction.SEND_TRANSACTION:
39072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            RateController.getInstance().update();
39172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            break;
39272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
39372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    break;
39472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case TransactionState.FAILED:
39572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (LOCAL_LOGV) {
39672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.v(TAG, "Transaction failed: " + serviceId);
39772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
39872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    break;
39972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                default:
40072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (LOCAL_LOGV) {
40172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.v(TAG, "Transaction state unknown: " +
40272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                serviceId + " " + result);
40372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
40472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    break;
40572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
40672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
40772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Broadcast the result of the transaction.
40872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            sendBroadcast(intent);
40972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } finally {
41072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            transaction.detach(this);
41172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            stopSelf(serviceId);
41272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
41372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
41472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
41572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private synchronized void createWakeLock() {
41672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Create a new wake lock if we haven't made one yet.
41772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mWakeLock == null) {
41872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
41972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MMS Connectivity");
42072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mWakeLock.setReferenceCounted(false);
42172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
42272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
42372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
42472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
42572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void acquireWakeLock() {
42672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // It's okay to double-acquire this because we are not using it
42772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // in reference-counted mode.
42872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mWakeLock.acquire();
42972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
43072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
43172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void releaseWakeLock() {
43272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Don't release the wake lock if it hasn't been created and acquired.
43372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mWakeLock != null && mWakeLock.isHeld()) {
43472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mWakeLock.release();
43572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
43672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
43772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
43872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected int beginMmsConnectivity() throws IOException {
43972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Take a wake lock so we don't fall asleep before the message is downloaded.
44072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        createWakeLock();
44172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
44272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        int result = mConnMgr.startUsingNetworkFeature(
44372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_MMS);
44472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
44572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        switch (result) {
44672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        case Phone.APN_ALREADY_ACTIVE:
44772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        case Phone.APN_REQUEST_STARTED:
44872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            acquireWakeLock();
44972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return result;
45072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
45172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
45272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        throw new IOException("Cannot establish MMS connectivity");
45372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
45472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
45572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void endMmsConnectivity() {
45672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
45772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // cancel timer for renewal of lease
45872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mServiceHandler.removeMessages(EVENT_CONTINUE_MMS_CONNECTIVITY);
45972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (mConnMgr != null) {
46072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mConnMgr.stopUsingNetworkFeature(
46172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_MMS);
46272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
46372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } finally {
46472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            releaseWakeLock();
46572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
46672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
46772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
46872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final class ServiceHandler extends Handler {
46972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public ServiceHandler(Looper looper) {
47072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            super(looper);
47172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
47272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
47372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        /**
47472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         * Handle incoming transaction requests.
47572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         * The incoming requests are initiated by the MMSC Server or by the
47672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         * MMS Client itself.
47772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         */
47872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        @Override
47972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public void handleMessage(Message msg) {
48072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (LOCAL_LOGV) {
48172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Log.v(TAG, "Handling incoming message: " + msg);
48272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
48372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
48472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Transaction transaction = null;
48572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            switch (msg.what) {
48672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case EVENT_QUIT:
48772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    getLooper().quit();
48872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return;
48972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
49072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case EVENT_CONTINUE_MMS_CONNECTIVITY:
49172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    synchronized (mProcessing) {
49272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (mProcessing.isEmpty()) {
49372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            return;
49472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
49572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
49672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
49772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (LOCAL_LOGV) {
49872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.v(TAG, "Extending MMS connectivity - still processing txn");
49972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
50072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
50172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    try {
50272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        int result = beginMmsConnectivity();
50372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (result != Phone.APN_ALREADY_ACTIVE) {
50472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            Log.i(TAG, "Extending MMS connectivity returned " + result +
50572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    " instead of APN_ALREADY_ACTIVE");
50672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            // Just wait for connectivity startup without
50772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            // any new request of APN switch.
50872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            return;
50972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
51072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    } catch (IOException e) {
51172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.w(TAG, "Attempt to extend use of MMS connectivity failed");
51272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return;
51372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
51472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
51572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    // Restart timer
51672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    sendMessageDelayed(obtainMessage(EVENT_CONTINUE_MMS_CONNECTIVITY),
51772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                       APN_EXTENSION_WAIT);
51872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return;
51972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
52072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case EVENT_DATA_STATE_CHANGED:
52172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    /*
52272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                     * If we are being informed that connectivity has been established
52372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                     * to allow MMS traffic, then proceed with processing the pending
52472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                     * transaction, if any.
52572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                     */
52672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (mConnectivityListener == null) {
52772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return;
52872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
52972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
53072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    NetworkInfo info = mConnectivityListener.getNetworkInfo();
53172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (LOCAL_LOGV) {
53272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.v(TAG, "Got DATA_STATE_CHANGED event: " + info);
53372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
53472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
53572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    // Check availability of the mobile network.
53672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if ((info == null) || (info.getType() != ConnectivityManager.TYPE_MOBILE)) {
53772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return;
53872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
53972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
54072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (!info.isConnected()) {
54172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return;
54272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
54372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
54472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    TransactionSettings settings = new TransactionSettings(
54572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            TransactionService.this, info.getExtraInfo());
54672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
54772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (TextUtils.isEmpty(settings.getMmscUrl())) {
54872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.e(TAG, "Invalid APN setting: MMSC URL is empty");
54972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return;
55072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
55172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
55272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    // Set a timer to keep renewing our "lease" on the MMS connection
55372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    sendMessageDelayed(obtainMessage(EVENT_CONTINUE_MMS_CONNECTIVITY),
55472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                       APN_EXTENSION_WAIT);
55572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
55672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    processPendingTransaction(transaction, settings);
55772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return;
55872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
55972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case EVENT_TRANSACTION_REQUEST:
56072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    int serviceId = msg.arg1;
56172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    try {
56272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        TransactionBundle args = (TransactionBundle) msg.obj;
56372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        TransactionSettings transactionSettings;
56472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
56572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        // Set the connection settings for this transaction.
56672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        // If these have not been set in args, load the default settings.
56772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        String mmsc = args.getMmscUrl();
56872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (mmsc != null) {
56972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            transactionSettings = new TransactionSettings(
57072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    mmsc, args.getProxyAddress(), args.getProxyPort());
57172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        } else {
57272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            transactionSettings = new TransactionSettings(
57372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                                    TransactionService.this, null);
57472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
57572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
57672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        // Create appropriate transaction
57772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        switch (args.getTransactionType()) {
57872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            case Transaction.NOTIFICATION_TRANSACTION:
57972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                String uri = args.getUri();
58072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                if (uri != null) {
58172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    transaction = new NotificationTransaction(
58272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                            TransactionService.this, serviceId,
58372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                            transactionSettings, uri);
58472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                } else {
58572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    // Now it's only used for test purpose.
58672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    byte[] pushData = args.getPushData();
58772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    PduParser parser = new PduParser(pushData);
58872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    GenericPdu ind = parser.parse();
58972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
59072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    int type = PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND;
59172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    if ((ind != null) && (ind.getMessageType() == type)) {
59272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        transaction = new NotificationTransaction(
59372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                                TransactionService.this, serviceId,
59472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                                transactionSettings, (NotificationInd) ind);
59572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    } else {
59672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        Log.e(TAG, "Invalid PUSH data.");
59772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        transaction = null;
59872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        return;
59972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    }
60072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                }
60172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                break;
60272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            case Transaction.RETRIEVE_TRANSACTION:
60372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                transaction = new RetrieveTransaction(
60472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        TransactionService.this, serviceId,
60572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        transactionSettings, args.getUri());
60672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                break;
60772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            case Transaction.SEND_TRANSACTION:
60872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                transaction = new SendTransaction(
60972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        TransactionService.this, serviceId,
61072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        transactionSettings, args.getUri());
61172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                break;
61272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            case Transaction.READREC_TRANSACTION:
61372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                transaction = new ReadRecTransaction(
61472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        TransactionService.this, serviceId,
61572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        transactionSettings, args.getUri());
61672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                break;
61772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            default:
61872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                Log.w(TAG, "Invalid transaction type: " + serviceId);
61972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                transaction = null;
62072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                return;
62172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
62272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
62372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (!processTransaction(transaction)) {
62472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            transaction = null;
62572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            return;
62672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
62772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
62872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (LOCAL_LOGV) {
62972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            Log.v(TAG, "Started processing of incoming message: " + msg);
63072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
63172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    } catch (Exception ex) {
63272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (LOCAL_LOGV) {
63372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            Log.v(TAG, "Exception occurred while handling message: " + msg, ex);
63472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
63572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
63672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (transaction != null) {
63772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            try {
63872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                transaction.detach(TransactionService.this);
63972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                if (mProcessing.contains(transaction)) {
64072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    synchronized (mProcessing) {
64172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                        mProcessing.remove(transaction);
64272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    }
64372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                }
64472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            } catch (Throwable t) {
64572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                Log.e(TAG, "Unexpected Throwable.", t);
64672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            } finally {
64772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                // Set transaction to null to allow stopping the
64872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                // transaction service.
64972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                transaction = null;
65072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            }
65172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
65272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    } finally {
65372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (transaction == null) {
65472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            if (LOCAL_LOGV) {
65572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                Log.v(TAG, "Transaction was null. Stopping self: " + serviceId);
65672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            }
65772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            endMmsConnectivity();
65872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            stopSelf(serviceId);
65972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
66072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
66172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return;
66272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case EVENT_HANDLE_NEXT_PENDING_TRANSACTION:
66372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    processPendingTransaction(transaction, (TransactionSettings) msg.obj);
66472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return;
66572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                default:
66672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Log.w(TAG, "what=" + msg.what);
66772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return;
66872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
66972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
67072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
67172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        private void processPendingTransaction(Transaction transaction, TransactionSettings settings) {
67272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            int numProcessTransaction = 0;
67372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            synchronized (mProcessing) {
67472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (mPending.size() != 0) {
67572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    transaction = mPending.remove(0);
67672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
67772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                numProcessTransaction = mProcessing.size();
67872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
67972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
68072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (transaction != null) {
68172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (settings != null) {
68272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    transaction.setConnectionSettings(settings);
68372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
68472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
68572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                /*
68672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                 * Process deferred transaction
68772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                 */
68872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                try {
68972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    int serviceId = transaction.getServiceId();
69072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (processTransaction(transaction)) {
69172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (LOCAL_LOGV) {
69272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            Log.v(TAG, "Started deferred processing of transaction: "
69372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    + transaction);
69472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
69572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    } else {
69672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        transaction = null;
69772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        stopSelf(serviceId);
69872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
69972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                } catch (IOException e) {
70072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (LOCAL_LOGV) {
70172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.v(TAG, e.getMessage(), e);
70272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
70372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
70472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
70572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            else {
70672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (numProcessTransaction == 0) {
70772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    endMmsConnectivity();
70872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
70972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
71072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
71172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
71272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        /**
71372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         * Internal method to begin processing a transaction.
71472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         * @param transaction the transaction. Must not be {@code null}.
71572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         * @return {@code true} if process has begun or will begin. {@code false}
71672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         * if the transaction should be discarded.
71772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         * @throws IOException if connectivity for MMS traffic could not be
71872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         * established.
71972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project         */
72072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        private boolean processTransaction(Transaction transaction) throws IOException {
72172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Check if transaction already processing
72272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            synchronized (mProcessing) {
72372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                for (Transaction t : mPending) {
72472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (t.isEquivalent(transaction)) {
72572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (LOCAL_LOGV) {
72672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            Log.v(TAG, "Transaction already pending: " +
72772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    transaction.getServiceId());
72872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
72972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return true;
73072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
73172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
73272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                for (Transaction t : mProcessing) {
73372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (t.isEquivalent(transaction)) {
73472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (LOCAL_LOGV) {
73572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            Log.v(TAG, "Duplicated transaction: " + transaction.getServiceId());
73672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
73772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return true;
73872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
73972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
74072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
74172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                /*
74272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                * Make sure that the network connectivity necessary
74372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                * for MMS traffic is enabled. If it is not, we need
74472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                * to defer processing the transaction until
74572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                * connectivity is established.
74672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                */
74772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                int connectivityResult = beginMmsConnectivity();
74872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (connectivityResult == Phone.APN_REQUEST_STARTED) {
74972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    mPending.add(transaction);
75072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (LOCAL_LOGV) {
75172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.v(TAG, "Defer txn processing pending MMS connectivity");
75272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
75372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return true;
75472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
75572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
75672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (LOCAL_LOGV) {
75772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Log.v(TAG, "Adding transaction to list: " + transaction);
75872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
75972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mProcessing.add(transaction);
76072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
76172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
76272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (LOCAL_LOGV) {
76372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Log.v(TAG, "Starting transaction: " + transaction);
76472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
76572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
76672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Set a timer to keep renewing our "lease" on the MMS connection
76772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            sendMessageDelayed(obtainMessage(EVENT_CONTINUE_MMS_CONNECTIVITY),
76872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                               APN_EXTENSION_WAIT);
76972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
77072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Attach to transaction and process it
77172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            transaction.attach(TransactionService.this);
77272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            transaction.process();
77372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return true;
77472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
77572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
77672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
777