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

Commit d31b9344 authored by Katherine Kuan's avatar Katherine Kuan Committed by Android (Google) Code Review
Browse files

Merge "Fix viewing legacy and raw contact URI on tablet"

parents d25f3189 6cd5b0ab
Loading
Loading
Loading
Loading
+3 −42
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.contacts;
import com.android.contacts.model.AccountType;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.model.AccountTypeWithDataSet;
import com.android.contacts.util.ContactLoaderUtils;
import com.android.contacts.util.DataStatus;
import com.android.contacts.util.StreamItemEntry;
import com.android.contacts.util.StreamItemPhotoEntry;
@@ -681,7 +682,8 @@ public class ContactLoader extends Loader<ContactLoader.Result> {
        protected Result doInBackground(Void... args) {
            try {
                final ContentResolver resolver = getContext().getContentResolver();
                final Uri uriCurrentFormat = ensureIsContactUri(resolver, mLookupUri);
                final Uri uriCurrentFormat = ContactLoaderUtils.ensureIsContactUri(
                        resolver, mLookupUri);
                Result result = loadContactEntity(resolver, uriCurrentFormat);
                if (!result.isNotFound()) {
                    if (result.isDirectoryEntry()) {
@@ -706,47 +708,6 @@ public class ContactLoader extends Loader<ContactLoader.Result> {
            }
        }

        /**
         * Transforms the given Uri and returns a Lookup-Uri that represents the contact.
         * For legacy contacts, a raw-contact lookup is performed.
         * @param resolver
         */
        private Uri ensureIsContactUri(final ContentResolver resolver, final Uri uri) {
            if (uri == null) throw new IllegalArgumentException("uri must not be null");

            final String authority = uri.getAuthority();

            // Current Style Uri?
            if (ContactsContract.AUTHORITY.equals(authority)) {
                final String type = resolver.getType(uri);
                // Contact-Uri? Good, return it
                if (Contacts.CONTENT_ITEM_TYPE.equals(type)) {
                    return uri;
                }

                // RawContact-Uri? Transform it to ContactUri
                if (RawContacts.CONTENT_ITEM_TYPE.equals(type)) {
                    final long rawContactId = ContentUris.parseId(uri);
                    return RawContacts.getContactLookupUri(getContext().getContentResolver(),
                            ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
                }

                // Anything else? We don't know what this is
                throw new IllegalArgumentException("uri format is unknown");
            }

            // Legacy Style? Convert to RawContact
            final String OBSOLETE_AUTHORITY = "contacts";
            if (OBSOLETE_AUTHORITY.equals(authority)) {
                // Legacy Format. Convert to RawContact-Uri and then lookup the contact
                final long rawContactId = ContentUris.parseId(uri);
                return RawContacts.getContactLookupUri(resolver,
                        ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
            }

            throw new IllegalArgumentException("uri authority is unknown");
        }

        private Result loadContactEntity(ContentResolver resolver, Uri contactUri) {
            Uri entityUri = Uri.withAppendedPath(contactUri, Contacts.Entity.CONTENT_DIRECTORY);
            Cursor cursor = resolver.query(entityUri, ContactQuery.COLUMNS, null, null,
+50 −38
Original line number Diff line number Diff line
@@ -17,10 +17,10 @@ package com.android.contacts.list;

import com.android.common.widget.CompositeCursorAdapter.Partition;
import com.android.contacts.R;
import com.android.contacts.util.ContactLoaderUtils;
import com.android.contacts.widget.AutoScrollListView;

import android.app.Activity;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Loader;
@@ -28,6 +28,7 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -92,50 +93,63 @@ public abstract class ContactBrowseListFragment extends
    private String mPersistentSelectionPrefix = PERSISTENT_SELECTION_PREFIX;

    protected OnContactBrowserActionListener mListener;
    private ContactLookupTask mContactLookupTask;

    /**
     * Refreshes a contact URI: it may have changed as a result of aggregation
     * activity.
     */
    private class ContactUriQueryHandler extends AsyncQueryHandler {
    private final class ContactLookupTask extends AsyncTask<Void, Void, Uri> {

        public ContactUriQueryHandler(ContentResolver cr) {
            super(cr);
        }
        private final Uri mUri;
        private boolean mIsCancelled;

        public void runQuery() {
            startQuery(0, mSelectedContactUri, mSelectedContactUri,
                    new String[] { Contacts._ID, Contacts.LOOKUP_KEY }, null, null, null);
        public ContactLookupTask(Uri uri) {
            mUri = uri;
        }

        @Override
        protected void onQueryComplete(int token, Object cookie, Cursor data) {
            long contactId = 0;
            String lookupKey = null;
            if (data != null) {
                if (data.moveToFirst()) {
                    contactId = data.getLong(0);
                    lookupKey = data.getString(1);
        protected Uri doInBackground(Void... args) {
            Cursor cursor = null;
            try {
                final ContentResolver resolver = getContext().getContentResolver();
                final Uri uriCurrentFormat = ContactLoaderUtils.ensureIsContactUri(resolver, mUri);
                cursor = resolver.query(uriCurrentFormat,
                        new String[] { Contacts._ID, Contacts.LOOKUP_KEY }, null, null, null);

                if (cursor != null && cursor.moveToFirst()) {
                    final long contactId = cursor.getLong(0);
                    final String lookupKey = cursor.getString(1);
                    if (contactId != 0 && !TextUtils.isEmpty(lookupKey)) {
                        return Contacts.getLookupUri(contactId, lookupKey);
                    }
                data.close();
                }

            if (!cookie.equals(mSelectedContactUri)) {
                return;
                Log.e(TAG, "Error: No contact ID or lookup key for contact " + mUri);
                return null;
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }

            Uri uri;
            if (contactId != 0 && lookupKey != null) {
                uri = Contacts.getLookupUri(contactId, lookupKey);
            } else {
                uri = null;
        public void cancel() {
            super.cancel(true);
            // Use a flag to keep track of whether the {@link AsyncTask} was cancelled or not in
            // order to ensure onPostExecute() is not executed after the cancel request. The flag is
            // necessary because {@link AsyncTask} still calls onPostExecute() if the cancel request
            // came after the worker thread was finished.
            mIsCancelled = true;
        }

            onContactUriQueryFinished(uri);
        @Override
        protected void onPostExecute(Uri uri) {
            // Make sure the {@link Fragment} is at least still attached to the {@link Activity}
            // before continuing.
            if (mIsCancelled || !isAdded() || uri == null) {
                return;
            }
            mSelectedContactUri = uri;
            onContactUriQueryFinished(mSelectedContactUri);
        }
    }

    private ContactUriQueryHandler mQueryHandler;

    private boolean mDelaySelection;

@@ -158,7 +172,6 @@ public abstract class ContactBrowseListFragment extends
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mQueryHandler = new ContactUriQueryHandler(activity.getContentResolver());
        mPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
        restoreFilter();
        restoreSelectedUri(false);
@@ -228,12 +241,10 @@ public abstract class ContactBrowseListFragment extends
    }

    protected void refreshSelectedContactUri() {
        if (mQueryHandler == null) {
            return;
        if (mContactLookupTask != null) {
            mContactLookupTask.cancel();
        }

        mQueryHandler.cancelOperation(0);

        if (!isSelectionVisible()) {
            return;
        }
@@ -249,7 +260,8 @@ public abstract class ContactBrowseListFragment extends
                && mSelectedContactDirectoryId != Directory.LOCAL_INVISIBLE) {
            onContactUriQueryFinished(mSelectedContactUri);
        } else {
            mQueryHandler.runQuery();
            mContactLookupTask = new ContactLookupTask(mSelectedContactUri);
            mContactLookupTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
        }
    }

+78 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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.contacts.util;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.net.Uri;
import android.provider.Contacts;
import android.provider.ContactsContract;
import android.provider.ContactsContract.RawContacts;

/**
 * Utility methods for the {@link ContactLoader}.
 */
public final class ContactLoaderUtils {

    /** Static helper, not instantiable. */
    private ContactLoaderUtils() {}

    /**
     * Transforms the given Uri and returns a Lookup-Uri that represents the contact.
     * For legacy contacts, a raw-contact lookup is performed. An {@link IllegalArgumentException}
     * can be thrown if the URI is null or the authority is not recognized.
     *
     * Do not call from the UI thread.
     */
    @SuppressWarnings("deprecation")
    public static Uri ensureIsContactUri(final ContentResolver resolver, final Uri uri)
            throws IllegalArgumentException {
        if (uri == null) throw new IllegalArgumentException("uri must not be null");

        final String authority = uri.getAuthority();

        // Current Style Uri?
        if (ContactsContract.AUTHORITY.equals(authority)) {
            final String type = resolver.getType(uri);
            // Contact-Uri? Good, return it
            if (ContactsContract.Contacts.CONTENT_ITEM_TYPE.equals(type)) {
                return uri;
            }

            // RawContact-Uri? Transform it to ContactUri
            if (RawContacts.CONTENT_ITEM_TYPE.equals(type)) {
                final long rawContactId = ContentUris.parseId(uri);
                return RawContacts.getContactLookupUri(resolver,
                        ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
            }

            // Anything else? We don't know what this is
            throw new IllegalArgumentException("uri format is unknown");
        }

        // Legacy Style? Convert to RawContact
        final String OBSOLETE_AUTHORITY = Contacts.AUTHORITY;
        if (OBSOLETE_AUTHORITY.equals(authority)) {
            // Legacy Format. Convert to RawContact-Uri and then lookup the contact
            final long rawContactId = ContentUris.parseId(uri);
            return RawContacts.getContactLookupUri(resolver,
                    ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
        }

        throw new IllegalArgumentException("uri authority is unknown");
    }
}