10ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng/*
20ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * Copyright (C) 2010 The Android Open Source Project
30ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
40ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * Licensed under the Apache License, Version 2.0 (the "License");
50ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * you may not use this file except in compliance with the License.
60ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * You may obtain a copy of the License at
70ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
80ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *      http://www.apache.org/licenses/LICENSE-2.0
90ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
100ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * Unless required by applicable law or agreed to in writing, software
110ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * distributed under the License is distributed on an "AS IS" BASIS,
120ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * See the License for the specific language governing permissions and
140ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * limitations under the License.
150ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng */
160ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
170ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengpackage com.android.phone.common;
180ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengimport android.content.Context;
190ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengimport android.net.Uri;
200ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengimport android.os.AsyncTask;
210ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengimport android.os.Looper;
220ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengimport android.provider.CallLog.Calls;
230ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengimport android.util.Log;
240ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengimport com.android.internal.telephony.CallerInfo;
250ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
260ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng/**
270ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * Class to access the call logs database asynchronously since
280ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * database ops can take a long time depending on the system's load.
290ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * It uses AsyncTask which has its own thread pool.
300ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
310ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * <pre class="prettyprint">
320ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * Typical usage:
330ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * ==============
340ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
350ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  // From an activity...
360ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  String mLastNumber = "";
370ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
380ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  CallLogAsync log = new CallLogAsync();
390ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
400ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  CallLogAsync.AddCallArgs addCallArgs = new CallLogAsync.AddCallArgs(
410ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *      this, ci, number, presentation, type, timestamp, duration);
420ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
430ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  log.addCall(addCallArgs);
440ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
450ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  CallLogAsync.GetLastOutgoingCallArgs lastCallArgs = new CallLogAsync.GetLastOutgoingCallArgs(
460ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *      this, new CallLogAsync.OnLastOutgoingCallComplete() {
470ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *               public void lastOutgoingCall(String number) { mLastNumber = number; }
480ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *            });
490ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  log.getLastOutgoingCall(lastCallArgs);
500ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * </pre>
510ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
520ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng */
530ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
540ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengpublic class CallLogAsync {
550ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    private static final String TAG = "CallLogAsync";
560ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
570ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /**
580ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * Parameter object to hold the args to add a call in the call log DB.
590ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     */
600ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    public static class AddCallArgs {
610ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        /**
620ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng         * @param ci               CallerInfo.
630ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng         * @param number           To be logged.
640ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng         * @param presentation     Of the number.
650ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng         * @param callType         The type of call (e.g INCOMING_TYPE). @see
660ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng         *                         android.provider.CallLog for the list of values.
670ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng         * @param timestamp        Of the call (millisecond since epoch).
680ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng         * @param durationInMillis Of the call (millisecond).
690ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng         */
700ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public AddCallArgs(Context context,
710ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                           CallerInfo ci,
720ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                           String number,
730ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                           int presentation,
740ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                           int callType,
750ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                           long timestamp,
760ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                           long durationInMillis) {
770ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // Note that the context is passed each time. We could
780ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // have stored it in a member but we've run into a bunch
790ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // of memory leaks in the past that resulted from storing
800ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // references to contexts in places that were long lived
810ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // when the contexts were expected to be short lived. For
820ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // example, if you initialize this class with an Activity
830ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // instead of an Application the Activity can't be GCed
840ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // until this class can, and Activities tend to hold
850ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // references to large amounts of RAM for things like the
860ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // bitmaps in their views.
870ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            //
880ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // Having hit more than a few of those bugs in the past
890ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // we've grown cautious of storing references to Contexts
900ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // when it's not very clear that the thing holding the
910ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // references is tightly tied to the Context, for example
920ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            // Views the Activity is displaying.
930ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
940ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.context = context;
950ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.ci = ci;
960ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.number = number;
970ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.presentation = presentation;
980ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.callType = callType;
990ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.timestamp = timestamp;
1000ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.durationInSec = (int)(durationInMillis / 1000);
1010ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
1020ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // Since the members are accessed directly, we don't use the
1030ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // mXxxx notation.
1040ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final Context context;
1050ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final CallerInfo ci;
1060ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final String number;
1070ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final int presentation;
1080ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final int callType;
1090ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final long timestamp;
1100ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final int durationInSec;
1110ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
1120ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
1130ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /**
1140ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * Parameter object to hold the args to get the last outgoing call
1150ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * from the call log DB.
1160ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     */
1170ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    public static class GetLastOutgoingCallArgs {
1180ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public GetLastOutgoingCallArgs(Context context,
1190ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                                       OnLastOutgoingCallComplete callback) {
1200ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.context = context;
1210ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.callback = callback;
1220ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
1230ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final Context context;
1240ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final OnLastOutgoingCallComplete callback;
1250ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
1260ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
1270ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /**
1280ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * Non blocking version of CallLog.addCall(...)
1290ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     */
1300ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    public AsyncTask addCall(AddCallArgs args) {
1310ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        assertUiThread();
1320ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        return new AddCallTask().execute(args);
1330ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
1340ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
1350ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /** Interface to retrieve the last dialed number asynchronously. */
1360ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    public interface OnLastOutgoingCallComplete {
1370ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        /** @param number The last dialed number or an empty string if
1380ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng         *                none exists yet. */
1390ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        void lastOutgoingCall(String number);
1400ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
1410ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
1420ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /**
1430ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * CallLog.getLastOutgoingCall(...)
1440ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     */
1450ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    public AsyncTask getLastOutgoingCall(GetLastOutgoingCallArgs args) {
1460ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        assertUiThread();
1470ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        return new GetLastOutgoingCallTask(args.callback).execute(args);
1480ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
1490ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
1500ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /**
1510ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * AsyncTask to save calls in the DB.
1520ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     */
1530ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    private class AddCallTask extends AsyncTask<AddCallArgs, Void, Uri[]> {
1540ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        @Override
1550ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        protected Uri[] doInBackground(AddCallArgs... callList) {
1560ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            int count = callList.length;
1570ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            Uri[] result = new Uri[count];
1580ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            for (int i = 0; i < count; i++) {
1590ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                AddCallArgs c = callList[i];
1600ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
1610ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                try {
1620ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    // May block.
1630ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    result[i] = Calls.addCall(
1640ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                            c.ci, c.context, c.number, c.presentation,
1650ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                            c.callType, c.timestamp, c.durationInSec);
1660ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                } catch (Exception e) {
1670ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    // This must be very rare but may happen in legitimate cases.
1680ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    // e.g. If the phone is encrypted and thus write request fails, it may
1690ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    // cause some kind of Exception (right now it is IllegalArgumentException, but
1700ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    // might change).
1710ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    //
1720ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    // We don't want to crash the whole process just because of that.
1730ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    // Let's just ignore it and leave logs instead.
1740ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    Log.e(TAG, "Exception raised during adding CallLog entry: " + e);
1750ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    result[i] = null;
1760ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                }
1770ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            }
1780ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            return result;
1790ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
1800ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
1810ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // Perform a simple sanity check to make sure the call was
1820ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // written in the database. Typically there is only one result
1830ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // per call so it is easy to identify which one failed.
1840ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        @Override
1850ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        protected void onPostExecute(Uri[] result) {
1860ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            for (Uri uri : result) {
1870ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                if (uri == null) {
1880ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                    Log.e(TAG, "Failed to write call to the log.");
1890ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                }
1900ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            }
1910ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
1920ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
1930ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
1940ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /**
1950ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * AsyncTask to get the last outgoing call from the DB.
1960ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     */
1970ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    private class GetLastOutgoingCallTask extends AsyncTask<GetLastOutgoingCallArgs, Void, String> {
1980ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        private final OnLastOutgoingCallComplete mCallback;
1990ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        private String mNumber;
2000ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public GetLastOutgoingCallTask(OnLastOutgoingCallComplete callback) {
2010ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            mCallback = callback;
2020ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
2030ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
2040ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // Happens on a background thread. We cannot run the callback
2050ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // here because only the UI thread can modify the view
2060ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // hierarchy (e.g enable/disable the dial button). The
2070ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // callback is ran rom the post execute method.
2080ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        @Override
2090ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        protected String doInBackground(GetLastOutgoingCallArgs... list) {
2100ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            int count = list.length;
2110ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            String number = "";
2120ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            for (GetLastOutgoingCallArgs args : list) {
2130ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                // May block. Select only the last one.
2140ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                number = Calls.getLastOutgoingCall(args.context);
2150ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            }
2160ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            return number;  // passed to the onPostExecute method.
2170ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
2180ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
2190ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // Happens on the UI thread, it is safe to run the callback
2200ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // that may do some work on the views.
2210ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        @Override
2220ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        protected void onPostExecute(String number) {
2230ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            assertUiThread();
2240ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            mCallback.lastOutgoingCall(number);
2250ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
2260ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
2270ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
2280ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    private void assertUiThread() {
2290ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        if (!Looper.getMainLooper().equals(Looper.myLooper())) {
2300ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            throw new RuntimeException("Not on the UI thread!");
2310ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
2320ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
2330ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng}
234