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

Commit 23bc9b72 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick
Browse files

Hopefully fix frequently-reported ViewContactActivity ANR.

See background in bug 2539603.

BUG=2539603

Change-Id: I1392e8767a6174048c59a782076663772a3402d1
parent 4e9be7cc
Loading
Loading
Loading
Loading
+46 −26
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.graphics.drawable.Drawable;
import android.net.ParseException;
import android.net.Uri;
import android.net.WebAddress;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
@@ -305,7 +306,7 @@ public class ViewContactActivity extends Activity
    }

    /** {@inheritDoc} */
    public void onQueryComplete(int token, Object cookie, Cursor cursor) {
    public void onQueryComplete(int token, Object cookie, final Cursor cursor) {
        if (token == TOKEN_STATUSES) {
            try {
                // Read available social rows and consider binding
@@ -315,17 +316,52 @@ public class ViewContactActivity extends Activity
                    cursor.close();
                }
            }
        } else {
            considerBindData();
            return;
        }

        // We also have to iterate over the Cursor in the background,
        // as iterating over the Cursor can ANR on large result sets,
        // especially as our ContentProvider is cross-process.
        final ArrayList<Entity> oldEntities = mEntities;
        (new AsyncTask<Void, Void, ArrayList<Entity>>() {
            @Override
            protected ArrayList<Entity> doInBackground(Void... params) {
                ArrayList<Entity> newEntities = Lists.newArrayList();
                EntityIterator iterator = RawContacts.newEntityIterator(cursor);
                try {
                // Read incoming entities and consider binding
                readEntities(iterator);
                    while (iterator.hasNext()) {
                        Entity entity = iterator.next();
                        newEntities.add(entity);
                    }
                } catch (RemoteException e) {
                    Log.w(TAG, "Problem reading contact data: " + e.toString());
                    return null;
                } finally {
                    iterator.close();
                }
                return newEntities;
            }

            @Override
            protected void onPostExecute(ArrayList<Entity> newEntities) {
                if (newEntities == null) {
                    // There was an error loading.
                    return;
                }
                synchronized (ViewContactActivity.this) {
                    if (mEntities != oldEntities) {
                        // Multiple async tasks were in flight and we
                        // lost the race.
                        return;
                    }
                    mEntities = newEntities;
                    mHasEntities = true;
                }
                considerBindData();
            }
        }).execute();
    }

    private long getRefreshedContactId() {
        Uri freshContactUri = Contacts.lookupContact(getContentResolver(), mLookupUri);
@@ -335,22 +371,6 @@ public class ViewContactActivity extends Activity
        return -1;
    }

    /**
     * Read from the given {@link EntityIterator} to build internal set of
     * {@link #mEntities} for data display.
     */
    private synchronized void readEntities(EntityIterator iterator) {
        mEntities.clear();
        try {
            while (iterator.hasNext()) {
                mEntities.add(iterator.next());
            }
            mHasEntities = true;
        } catch (RemoteException e) {
            Log.w(TAG, "Problem reading contact data: " + e.toString());
        }
    }

    /**
     * Read from the given {@link Cursor} and build a set of {@link DataStatus}
     * objects to match any valid statuses found.