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