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.os.AsyncTask;
200ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengimport android.os.Looper;
210ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengimport android.provider.CallLog.Calls;
220ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
230ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng/**
2445b79134b1b857b33addc4bcd2a7fd41e4295098Yorke Lee * Class to access the call log asynchronously to avoid carrying out database operations on the
2545b79134b1b857b33addc4bcd2a7fd41e4295098Yorke Lee * UI thread, using an {@link AsyncTask}.
260ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
270ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * <pre class="prettyprint">
280ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * Typical usage:
290ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * ==============
300ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
310ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  // From an activity...
320ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  String mLastNumber = "";
330ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
340ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  CallLogAsync log = new CallLogAsync();
350ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
360ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  CallLogAsync.GetLastOutgoingCallArgs lastCallArgs = new CallLogAsync.GetLastOutgoingCallArgs(
370ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *      this, new CallLogAsync.OnLastOutgoingCallComplete() {
380ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *               public void lastOutgoingCall(String number) { mLastNumber = number; }
390ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *            });
400ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *  log.getLastOutgoingCall(lastCallArgs);
410ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng * </pre>
420ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng *
430ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng */
440ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
450ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Chengpublic class CallLogAsync {
460ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    private static final String TAG = "CallLogAsync";
470ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
480ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /**
490ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * Parameter object to hold the args to get the last outgoing call
500ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * from the call log DB.
510ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     */
520ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    public static class GetLastOutgoingCallArgs {
530ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public GetLastOutgoingCallArgs(Context context,
540ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                                       OnLastOutgoingCallComplete callback) {
550ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.context = context;
560ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            this.callback = callback;
570ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
580ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final Context context;
590ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public final OnLastOutgoingCallComplete callback;
600ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
610ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
620ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /** Interface to retrieve the last dialed number asynchronously. */
630ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    public interface OnLastOutgoingCallComplete {
640ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        /** @param number The last dialed number or an empty string if
650ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng         *                none exists yet. */
660ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        void lastOutgoingCall(String number);
670ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
680ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
690ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /**
700ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * CallLog.getLastOutgoingCall(...)
710ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     */
720ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    public AsyncTask getLastOutgoingCall(GetLastOutgoingCallArgs args) {
730ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        assertUiThread();
740ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        return new GetLastOutgoingCallTask(args.callback).execute(args);
750ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
760ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
770ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    /**
780ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     * AsyncTask to get the last outgoing call from the DB.
790ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng     */
800ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    private class GetLastOutgoingCallTask extends AsyncTask<GetLastOutgoingCallArgs, Void, String> {
810ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        private final OnLastOutgoingCallComplete mCallback;
820ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        private String mNumber;
830ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        public GetLastOutgoingCallTask(OnLastOutgoingCallComplete callback) {
840ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            mCallback = callback;
850ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
860ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
870ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // Happens on a background thread. We cannot run the callback
880ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // here because only the UI thread can modify the view
890ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // hierarchy (e.g enable/disable the dial button). The
900ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // callback is ran rom the post execute method.
910ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        @Override
920ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        protected String doInBackground(GetLastOutgoingCallArgs... list) {
930ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            int count = list.length;
940ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            String number = "";
950ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            for (GetLastOutgoingCallArgs args : list) {
960ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                // May block. Select only the last one.
970ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng                number = Calls.getLastOutgoingCall(args.context);
980ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            }
990ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            return number;  // passed to the onPostExecute method.
1000ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
1010ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
1020ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // Happens on the UI thread, it is safe to run the callback
1030ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        // that may do some work on the views.
1040ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        @Override
1050ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        protected void onPostExecute(String number) {
1060ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            assertUiThread();
1070ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            mCallback.lastOutgoingCall(number);
1080ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
1090ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
1100ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng
1110ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    private void assertUiThread() {
1120ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        if (!Looper.getMainLooper().equals(Looper.myLooper())) {
1130ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng            throw new RuntimeException("Not on the UI thread!");
1140ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng        }
1150ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng    }
1160ada29ea0983ed27e33d12dfe9b1280fc7005a7eChiao Cheng}
117