gt:         if (!Looper.getMainLooper().equals(Looper.myLooper())) {
context: /*
   * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
   * Copyright (C) 2010 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.android.phone;
  import android.content.Context;
  import android.net.Uri;
  import android.os.AsyncTask;
  import android.os.Looper;
  import android.provider.CallLog.Calls;
  import android.util.Log;
  import com.android.internal.telephony.CallerInfo;
  
  /**
   * Class to access the call logs database asynchronously since
   * database ops can take a long time depending on the system's load.
   * It uses AsyncTask which has its own thread pool.
   *
   * <pre class="prettyprint">
   * Typical usage:
   * ==============
   *
   *  // From an activity...
   *  String mLastNumber = "";
   *
   *  CallLogAsync log = new CallLogAsync();
   *
   *  CallLogAsync.AddCallArgs addCallArgs = new CallLogAsync.AddCallArgs(
   *      this, ci, number, presentation, type, timestamp, duration);
   *
   *  log.addCall(addCallArgs);
   *
   *  CallLogAsync.GetLastOutgoingCallArgs lastCallArgs = new CallLogAsync.GetLastOutgoingCallArgs(
   *      this, new CallLogAsync.OnLastOutgoingCallComplete() {
   *               public void lastOutgoingCall(String number) { mLastNumber = number; }
   *            });
   *  log.getLastOutgoingCall(lastCallArgs);
   * </pre>
   *
   */
  
  public class CallLogAsync {
      private static final String TAG = "CallLogAsync";
  
      /**
       * Parameter object to hold the args to add a call in the call log DB.
       */
      public static class AddCallArgs {
          /**
           * @param ci               CallerInfo.
           * @param number           To be logged.
           * @param presentation     Of the number.
           * @param callType         The type of call (e.g INCOMING_TYPE). @see
           *                         android.provider.CallLog for the list of values.
           * @param timestamp        Of the call (millisecond since epoch).
           * @param durationInMillis Of the call (millisecond).
           */
          public AddCallArgs(Context context,
                             CallerInfo ci,
                             String number,
                             int presentation,
                             int callType,
                             long timestamp,
                             long durationInMillis,
                             int subscription) {
              // Note that the context is passed each time. We could
              // have stored it in a member but we've run into a bunch
              // of memory leaks in the past that resulted from storing
              // references to contexts in places that were long lived
              // when the contexts were expected to be short lived. For
              // example, if you initialize this class with an Activity
              // instead of an Application the Activity can't be GCed
              // until this class can, and Activities tend to hold
              // references to large amounts of RAM for things like the
              // bitmaps in their views.
              //
              // Having hit more than a few of those bugs in the past
              // we've grown cautious of storing references to Contexts
              // when it's not very clear that the thing holding the
              // references is tightly tied to the Context, for example
              // Views the Activity is displaying.
  
              this.context = context;
              this.ci = ci;
              this.number = number;
              this.presentation = presentation;
              this.callType = callType;
              this.timestamp = timestamp;
              this.durationInSec = (int)(durationInMillis / 1000);
              this.subscription = subscription;
          }
          // Since the members are accessed directly, we don't use the
          // mXxxx notation.
          public final Context context;
          public final CallerInfo ci;
          public final String number;
          public final int presentation;
          public final int callType;
          public final long timestamp;
          public final int durationInSec;
          public final int subscription;
      }
  
      /**
       * Parameter object to hold the args to get the last outgoing call
       * from the call log DB.
       */
      public static class GetLastOutgoingCallArgs {
          public GetLastOutgoingCallArgs(Context context,
                                         OnLastOutgoingCallComplete callback) {
              this.context = context;
              this.callback = callback;
          }
          public final Context context;
          public final OnLastOutgoingCallComplete callback;
      }
  
      /**
       * Non blocking version of CallLog.addCall(...)
       */
      public AsyncTask addCall(AddCallArgs args) {
          assertUiThread();
          return new AddCallTask().execute(args);
      }
  
      /** Interface to retrieve the last dialed number asynchronously. */
      public interface OnLastOutgoingCallComplete {
          /** @param number The last dialed number or an empty string if
           *                none exists yet. */
          void lastOutgoingCall(String number);
      }
  
      /**
       * CallLog.getLastOutgoingCall(...)
       */
      public AsyncTask getLastOutgoingCall(GetLastOutgoingCallArgs args) {
          assertUiThread();
          return new GetLastOutgoingCallTask(args.callback).execute(args);
      }
  
      /**
       * AsyncTask to save calls in the DB.
       */
      private class AddCallTask extends AsyncTask<AddCallArgs, Void, Uri[]> {
          @Override
          protected Uri[] doInBackground(AddCallArgs... callList) {
              int count = callList.length;
              Uri[] result = new Uri[count];
              for (int i = 0; i < count; i++) {
                  AddCallArgs c = callList[i];
  
                  // May block.
                  result[i] = Calls.addCall(
                      c.ci, c.context, c.number, c.presentation,
                      c.callType, c.timestamp, c.durationInSec, c.subscription);
              }
              return result;
          }
  
          // Perform a simple sanity check to make sure the call was
          // written in the database. Typically there is only one result
          // per call so it is easy to identify which one failed.
          @Override
          protected void onPostExecute(Uri[] result) {
              for (Uri uri : result) {
                  if (uri == null) {
                      Log.e(TAG, "Failed to write call to the log.");
                  }
              }
          }
      }
  
      /**
       * AsyncTask to get the last outgoing call from the DB.
       */
      private class GetLastOutgoingCallTask extends AsyncTask<GetLastOutgoingCallArgs, Void, String> {
          private final OnLastOutgoingCallComplete mCallback;
          private String mNumber;
          public GetLastOutgoingCallTask(OnLastOutgoingCallComplete callback) {
              mCallback = callback;
          }
  
          // Happens on a background thread. We cannot run the callback
          // here because only the UI thread can modify the view
          // hierarchy (e.g enable/disable the dial button). The
          // callback is ran rom the post execute method.
          @Override
          protected String doInBackground(GetLastOutgoingCallArgs... list) {
              int count = list.length;
              String number = "";
              for (GetLastOutgoingCallArgs args : list) {
                  // May block. Select only the last one.
                  number = Calls.getLastOutgoingCall(args.context);
              }
              return number;  // passed to the onPostExecute method.
          }
  
          // Happens on the UI thread, it is safe to run the callback
          // that may do some work on the views.
          @Override
          protected void onPostExecute(String number) {
              assertUiThread();
              mCallback.lastOutgoingCall(number);
          }
      }
  
      private void assertUiThread() {
  