Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb7c287c authored by Hall Liu's avatar Hall Liu Committed by Gerrit Code Review
Browse files

Merge "Query geo description in worker thread to prevent ANR"

parents f6f3c16d 3b90d48e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -576,7 +576,7 @@ public class CallerInfo {
     * @return a geographical description string for the specified number.
     * @see com.android.i18n.phonenumbers.PhoneNumberOfflineGeocoder
     */
    private static String getGeoDescription(Context context, String number) {
    public static String getGeoDescription(Context context, String number) {
        if (VDBG) Rlog.v(TAG, "getGeoDescription('" + number + "')...");

        if (TextUtils.isEmpty(number)) {
+66 −25
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.ContactsContract.PhoneLookup;
@@ -35,6 +36,9 @@ import android.text.TextUtils;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;

import java.util.ArrayList;
import java.util.List;

/**
 * Helper class to make it easier to run asynchronous caller-id lookup queries.
 * @see CallerInfo
@@ -50,6 +54,7 @@ public class CallerInfoAsyncQuery {
    private static final int EVENT_END_OF_QUEUE = 3;
    private static final int EVENT_EMERGENCY_NUMBER = 4;
    private static final int EVENT_VOICEMAIL_NUMBER = 5;
    private static final int EVENT_GET_GEO_DESCRIPTION = 6;

    private CallerInfoAsyncQueryHandler mHandler;

@@ -79,6 +84,7 @@ public class CallerInfoAsyncQuery {
        public Object cookie;
        public int event;
        public String number;
        public String geoDescription;

        public int subId;
    }
@@ -142,6 +148,7 @@ public class CallerInfoAsyncQuery {
        private Context mContext;
        private Uri mQueryUri;
        private CallerInfo mCallerInfo;
        private List<Runnable> mPendingListenerCallbacks = new ArrayList<>();

        /**
         * Our own query worker thread.
@@ -206,11 +213,32 @@ public class CallerInfoAsyncQuery {

                            reply.sendToTarget();

                            break;
                        case EVENT_GET_GEO_DESCRIPTION:
                            handleGeoDescription(msg);
                            break;
                        default:
                    }
                }
            }

            private void handleGeoDescription(Message msg) {
                WorkerArgs args = (WorkerArgs) msg.obj;
                CookieWrapper cw = (CookieWrapper) args.cookie;
                if (!TextUtils.isEmpty(cw.number) && cw.cookie != null && mContext != null) {
                    final long startTimeMillis = SystemClock.elapsedRealtime();
                    cw.geoDescription = CallerInfo.getGeoDescription(mContext, cw.number);
                    final long duration = SystemClock.elapsedRealtime() - startTimeMillis;
                    if (duration > 500) {
                        if (DBG) Rlog.d(LOG_TAG, "[handleGeoDescription]" +
                                "Spends long time to retrieve Geo description: " + duration);
                    }
                }
                Message reply = args.handler.obtainMessage(msg.what);
                reply.obj = args;
                reply.arg1 = msg.arg1;
                reply.sendToTarget();
            }
        }


@@ -256,6 +284,11 @@ public class CallerInfoAsyncQuery {
            }

            if (cw.event == EVENT_END_OF_QUEUE) {
                for (Runnable r : mPendingListenerCallbacks) {
                    r.run();
                }
                mPendingListenerCallbacks.clear();

                release();
                if (cursor != null) {
                    cursor.close();
@@ -263,6 +296,18 @@ public class CallerInfoAsyncQuery {
                return;
            }

            // If the cw.event == EVENT_GET_GEO_DESCRIPTION, means it would not be the 1st
            // time entering the onQueryComplete(), mCallerInfo should not be null.
            if (cw.event == EVENT_GET_GEO_DESCRIPTION) {
                if (mCallerInfo != null) {
                    mCallerInfo.geoDescription = cw.geoDescription;
                }
                // notify that we can clean up the queue after this.
                CookieWrapper endMarker = new CookieWrapper();
                endMarker.event = EVENT_END_OF_QUEUE;
                startQuery(token, endMarker, null, null, null, null, null);
            }

            // check the token and if needed, create the callerinfo object.
            if (mCallerInfo == null) {
                if ((mContext == null) || (mQueryUri == null)) {
@@ -293,34 +338,24 @@ public class CallerInfoAsyncQuery {
                                + mCallerInfo);
                    }

                    // Final step: look up the geocoded description.
                    if (ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION) {
                        // Note we do this only if we *don't* have a valid name (i.e. if
                        // no contacts matched the phone number of the incoming call),
                        // since that's the only case where the incoming-call UI cares
                        // about this field.
                        //
                        // (TODO: But if we ever want the UI to show the geoDescription
                        // even when we *do* match a contact, we'll need to either call
                        // updateGeoDescription() unconditionally here, or possibly add a
                        // new parameter to CallerInfoAsyncQuery.startQuery() to force
                        // the geoDescription field to be populated.)

                        if (TextUtils.isEmpty(mCallerInfo.name)) {
                            // Actually when no contacts match the incoming phone number,
                            // the CallerInfo object is totally blank here (i.e. no name
                            // *or* phoneNumber).  So we need to pass in cw.number as
                            // a fallback number.
                            mCallerInfo.updateGeoDescription(mContext, cw.number);
                        }
                    }

                    // Use the number entered by the user for display.
                    if (!TextUtils.isEmpty(cw.number)) {
                        mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number,
                                mCallerInfo.normalizedNumber,
                                CallerInfo.getCurrentCountryIso(mContext));
                    }

                    // This condition refer to the google default code for geo.
                    // If the number exists in Contacts, the CallCard would never show
                    // the geo description, so it would be unnecessary to query it.
                    if (ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION) {
                        if (TextUtils.isEmpty(mCallerInfo.name)) {
                            if (DBG) Rlog.d(LOG_TAG, "start querying geo description");
                            cw.event = EVENT_GET_GEO_DESCRIPTION;
                            startQuery(token, cw, null, null, null, null, null);
                            return;
                        }
                    }
                }

                if (DBG) Rlog.d(LOG_TAG, "constructing CallerInfo object for token: " + token);
@@ -333,9 +368,15 @@ public class CallerInfoAsyncQuery {

            //notify the listener that the query is complete.
            if (cw.listener != null) {
                Rlog.d(LOG_TAG, "notifying listener: " + cw.listener.getClass().toString() +
                             " for token: " + token + mCallerInfo);
                mPendingListenerCallbacks.add(new Runnable() {
                    @Override
                    public void run() {
                        if (DBG) Rlog.d(LOG_TAG, "notifying listener: "
                                + cw.listener.getClass().toString() + " for token: " + token
                                + mCallerInfo);
                        cw.listener.onQueryComplete(token, cw.cookie, mCallerInfo);
                    }
                });
            } else {
                Rlog.w(LOG_TAG, "There is no listener to notify for this query.");
            }