ContactLoaderFragment.java revision 2a45e35ab3273c8901d9df3671e51614dc0250c6
12eb969cc399d87b659a45568fa951d394c216917Katherine Kuan/*
22eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * Copyright (C) 2011 The Android Open Source Project
32eb969cc399d87b659a45568fa951d394c216917Katherine Kuan *
42eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * Licensed under the Apache License, Version 2.0 (the "License");
52eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * you may not use this file except in compliance with the License.
62eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * You may obtain a copy of the License at
72eb969cc399d87b659a45568fa951d394c216917Katherine Kuan *
82eb969cc399d87b659a45568fa951d394c216917Katherine Kuan *      http://www.apache.org/licenses/LICENSE-2.0
92eb969cc399d87b659a45568fa951d394c216917Katherine Kuan *
102eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * Unless required by applicable law or agreed to in writing, software
112eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * distributed under the License is distributed on an "AS IS" BASIS,
122eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * See the License for the specific language governing permissions and
142eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * limitations under the License
152eb969cc399d87b659a45568fa951d394c216917Katherine Kuan */
162eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
172eb969cc399d87b659a45568fa951d394c216917Katherine Kuanpackage com.android.contacts.detail;
182eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
192eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport com.android.contacts.ContactLoader;
20683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelsonimport com.android.contacts.ContactSaveService;
212eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport com.android.contacts.R;
2258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
2358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport com.android.contacts.util.PhoneCapabilityTester;
242eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport com.android.internal.util.Objects;
252eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
262eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.app.Activity;
272eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.app.Fragment;
282eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.app.LoaderManager;
292eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.app.LoaderManager.LoaderCallbacks;
3058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.content.ActivityNotFoundException;
312eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.content.Context;
3258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.content.Intent;
332eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.content.Loader;
34683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelsonimport android.media.RingtoneManager;
352eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.net.Uri;
36410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoroimport android.os.AsyncTask;
372eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.os.Bundle;
38410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoroimport android.provider.ContactsContract;
3958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.provider.ContactsContract.Contacts;
402eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.util.Log;
4158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.view.KeyEvent;
422eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.view.LayoutInflater;
4358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.view.Menu;
4458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.view.MenuInflater;
4558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.view.MenuItem;
462eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.view.View;
472eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.view.ViewGroup;
4858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanimport android.widget.Toast;
492eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
502eb969cc399d87b659a45568fa951d394c216917Katherine Kuan/**
512eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * This is an invisible worker {@link Fragment} that loads the contact details for the contact card.
522eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * The data is then passed to the listener, who can then pass the data to other {@link View}s.
532eb969cc399d87b659a45568fa951d394c216917Katherine Kuan */
5458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuanpublic class ContactLoaderFragment extends Fragment implements FragmentKeyListener {
552eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
562eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private static final String TAG = ContactLoaderFragment.class.getSimpleName();
572eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
58683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    /** The launch code when picking a ringtone */
59683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    private static final int REQUEST_CODE_PICK_RINGTONE = 1;
60683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson
61683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson
6258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    private boolean mOptionsMenuOptions;
6358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    private boolean mOptionsMenuEditable;
6458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    private boolean mOptionsMenuShareable;
65683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    private boolean mSendToVoicemailState;
66683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    private String mCustomRingtone;
6758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
682eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    /**
692eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     * This is a listener to the {@link ContactLoaderFragment} and will be notified when the
7058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan     * contact details have finished loading or if the user selects any menu options.
712eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     */
722eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    public static interface ContactLoaderFragmentListener {
7358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        /**
7458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan         * Contact was not found, so somehow close this fragment. This is raised after a contact
7558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan         * is removed via Menu/Delete
7658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan         */
7758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        public void onContactNotFound();
7858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
7958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        /**
8058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan         * Contact details have finished loading.
8158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan         */
822eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        public void onDetailsLoaded(ContactLoader.Result result);
8358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
8458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        /**
8558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan         * User decided to go to Edit-Mode
8658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan         */
8758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        public void onEditRequested(Uri lookupUri);
8858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
8958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        /**
9058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan         * User decided to delete the contact
9158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan         */
9258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        public void onDeleteRequested(Uri lookupUri);
9358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
942eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
952eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
962eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private static final int LOADER_DETAILS = 1;
972eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
982eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private static final String KEY_CONTACT_URI = "contactUri";
992eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private static final String LOADER_ARG_CONTACT_URI = "contactUri";
1002eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1012eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private Context mContext;
1022eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private Uri mLookupUri;
1032eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private ContactLoaderFragmentListener mListener;
1042eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1052eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private ContactLoader.Result mContactData;
1062eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1072eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    public ContactLoaderFragment() {
1082eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
1092eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1102eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    @Override
1112eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    public void onCreate(Bundle savedInstanceState) {
1122eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        super.onCreate(savedInstanceState);
1132eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        if (savedInstanceState != null) {
1142eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            mLookupUri = savedInstanceState.getParcelable(KEY_CONTACT_URI);
1152eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
1162eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
1172eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1182eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    @Override
1192eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    public void onSaveInstanceState(Bundle outState) {
1202eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        super.onSaveInstanceState(outState);
1212eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        outState.putParcelable(KEY_CONTACT_URI, mLookupUri);
1222eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
1232eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1242eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    @Override
1252eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    public void onAttach(Activity activity) {
1262eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        super.onAttach(activity);
1272eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        mContext = activity;
1282eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
1292eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1302eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    @Override
1312eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
13258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        setHasOptionsMenu(true);
1339c0e8ac3a90e01ebca4b83f1f8ef78e9e98a9922Makoto Onuki        // This is an invisible view.  This fragment is declared in a layout, so it can't be
1349c0e8ac3a90e01ebca4b83f1f8ef78e9e98a9922Makoto Onuki        // "viewless".  (i.e. can't return null here.)
1359c0e8ac3a90e01ebca4b83f1f8ef78e9e98a9922Makoto Onuki        // See also the comment in the layout file.
1362eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        return inflater.inflate(R.layout.contact_detail_loader_fragment, container, false);
1372eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
1382eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1392eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    @Override
1402eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    public void onActivityCreated(Bundle savedInstanceState) {
1412eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        super.onActivityCreated(savedInstanceState);
1422eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1432eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        if (mLookupUri != null) {
1442eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            Bundle args = new Bundle();
1452eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            args.putParcelable(LOADER_ARG_CONTACT_URI, mLookupUri);
1462eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            getLoaderManager().initLoader(LOADER_DETAILS, args, mDetailLoaderListener);
1472eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
1482eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
1492eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1502eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    public void loadUri(Uri lookupUri) {
1512eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        if (Objects.equal(lookupUri, mLookupUri)) {
1522eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            // Same URI, no need to load the data again
1532eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            return;
1542eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
1552eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1562eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        mLookupUri = lookupUri;
1572eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        if (mLookupUri == null) {
1582eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            getLoaderManager().destroyLoader(LOADER_DETAILS);
1592eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            mContactData = null;
1602eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            if (mListener != null) {
1612eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                mListener.onDetailsLoaded(mContactData);
1622eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            }
1632eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        } else if (getActivity() != null) {
1642eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            Bundle args = new Bundle();
1652eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            args.putParcelable(LOADER_ARG_CONTACT_URI, mLookupUri);
1662eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            getLoaderManager().restartLoader(LOADER_DETAILS, args, mDetailLoaderListener);
1672eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
1682eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
1692eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1702eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    public void setListener(ContactLoaderFragmentListener value) {
1712eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        mListener = value;
1722eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
1732eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1742eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    /**
1752eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     * The listener for the detail loader
1762eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     */
1772eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private final LoaderManager.LoaderCallbacks<ContactLoader.Result> mDetailLoaderListener =
1782eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            new LoaderCallbacks<ContactLoader.Result>() {
1792eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        @Override
1802eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
1812eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            Uri lookupUri = args.getParcelable(LOADER_ARG_CONTACT_URI);
1823915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro            return new ContactLoader(mContext, lookupUri, true /* loadGroupMetaData */,
1833e6991e5ee91ea2cc82a02bd3ea4ed7e941b08afMakoto Onuki                    true /* loadStreamItems */, true /* load invitable account types */);
1842eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
1852eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1862eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        @Override
1872eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
188685157e0635ee33350d3dd1c6551e188d3df9f22Daniel Lehmann            if (!mLookupUri.equals(data.getRequestedUri())) {
1892eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                return;
1902eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            }
1912eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
1929e7b5da669fcf92a6a627fb720749e5cb627684aMakoto Onuki            if (data.isError()) {
1933acaef02bdbc612ba7573f005168cec48aa42905Katherine Kuan                // This shouldn't ever happen, so throw an exception. The {@link ContactLoader}
1943acaef02bdbc612ba7573f005168cec48aa42905Katherine Kuan                // should log the actual exception.
1959e7b5da669fcf92a6a627fb720749e5cb627684aMakoto Onuki                throw new IllegalStateException("Failed to load contact", data.getException());
1962621c5bb7049401c8bce740005fa60bf1b304b86Makoto Onuki            } else if (data.isNotFound()) {
1972eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri());
1982eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                mContactData = null;
1993acaef02bdbc612ba7573f005168cec48aa42905Katherine Kuan            } else {
2003acaef02bdbc612ba7573f005168cec48aa42905Katherine Kuan                mContactData = data;
2012eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            }
2022eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
2032eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            if (mListener != null) {
20458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                if (mContactData == null) {
20558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                    mListener.onContactNotFound();
20658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                } else {
20758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                    mListener.onDetailsLoaded(mContactData);
20858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                }
2092eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            }
210683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            // Make sure the options menu is setup correctly with the loaded data.
211683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            getActivity().invalidateOptionsMenu();
2122eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
2132eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
2144ff31284ff6bd263621771bbfa6b24e0da5af031Daniel Lehmann        @Override
215fab516143c60565b9cc0d18fbe0af33902764546Katherine Kuan        public void onLoaderReset(Loader<ContactLoader.Result> loader) {}
2162eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    };
21758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
21858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    @Override
21958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
22058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        inflater.inflate(R.menu.view_contact, menu);
22158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    }
22258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
22358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    public boolean isOptionsMenuChanged() {
22458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        return mOptionsMenuOptions != isContactOptionsChangeEnabled()
22558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                || mOptionsMenuEditable != isContactEditable()
22658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                || mOptionsMenuShareable != isContactShareable();
22758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    }
22858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
22958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    @Override
23058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    public void onPrepareOptionsMenu(Menu menu) {
23158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        mOptionsMenuOptions = isContactOptionsChangeEnabled();
23258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        mOptionsMenuEditable = isContactEditable();
23358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        mOptionsMenuShareable = isContactShareable();
234683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        if (mContactData != null) {
235683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            mSendToVoicemailState = mContactData.isSendToVoicemail();
236683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            mCustomRingtone = mContactData.getCustomRingtone();
237683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        }
23858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
239683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        // Hide telephony-related settings (ringtone, send to voicemail)
240683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        // if we don't have a telephone
241683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        final MenuItem optionsSendToVoicemail = menu.findItem(R.id.menu_send_to_voicemail);
242683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        if (optionsSendToVoicemail != null) {
243683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            optionsSendToVoicemail.setChecked(mSendToVoicemailState);
244683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            optionsSendToVoicemail.setVisible(mOptionsMenuOptions);
245683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        }
246683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        final MenuItem optionsRingtone = menu.findItem(R.id.menu_set_ringtone);
247683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        if (optionsRingtone != null) {
248683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            optionsRingtone.setVisible(mOptionsMenuOptions);
249683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        }
25058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
25158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        final MenuItem editMenu = menu.findItem(R.id.menu_edit);
25258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        editMenu.setVisible(mOptionsMenuEditable);
25358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
25458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        final MenuItem deleteMenu = menu.findItem(R.id.menu_delete);
25558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        deleteMenu.setVisible(mOptionsMenuEditable);
25658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
25758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        final MenuItem shareMenu = menu.findItem(R.id.menu_share);
25858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        shareMenu.setVisible(mOptionsMenuShareable);
25958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    }
26058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
26158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    public boolean isContactOptionsChangeEnabled() {
26258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        return mContactData != null && !mContactData.isDirectoryEntry()
26358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                && PhoneCapabilityTester.isPhone(mContext);
26458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    }
26558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
26658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    public boolean isContactEditable() {
26758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        return mContactData != null && !mContactData.isDirectoryEntry();
26858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    }
26958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
27058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    public boolean isContactShareable() {
2714ff31284ff6bd263621771bbfa6b24e0da5af031Daniel Lehmann        return mContactData != null && !mContactData.isDirectoryEntry();
27258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    }
27358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
27458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    @Override
27558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    public boolean onOptionsItemSelected(MenuItem item) {
27658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        switch (item.getItemId()) {
27758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            case R.id.menu_edit: {
27858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                if (mListener != null) mListener.onEditRequested(mLookupUri);
27958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                break;
28058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            }
28158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            case R.id.menu_delete: {
28258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                if (mListener != null) mListener.onDeleteRequested(mLookupUri);
28358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                return true;
28458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            }
285683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            case R.id.menu_set_ringtone: {
28658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                if (mContactData == null) return false;
287683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                doPickRingtone();
28858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                return true;
28958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            }
29058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            case R.id.menu_share: {
29158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                if (mContactData == null) return false;
29258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
29358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                final String lookupKey = mContactData.getLookupKey();
294410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                Uri shareUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey);
295410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                if (mContactData.isUserProfile()) {
296410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                    // User is sharing the profile.  We don't want to force the receiver to have
297410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                    // the highly-privileged READ_PROFILE permission, so we need to request a
298410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                    // pre-authorized URI from the provider.
299410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                    shareUri = getPreAuthorizedUri(shareUri);
300410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                }
30158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
30258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                final Intent intent = new Intent(Intent.ACTION_SEND);
30358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                intent.setType(Contacts.CONTENT_VCARD_TYPE);
30458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                intent.putExtra(Intent.EXTRA_STREAM, shareUri);
30558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
30658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                // Launch chooser to share contact via
30758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                final CharSequence chooseTitle = mContext.getText(R.string.share_via);
30858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                final Intent chooseIntent = Intent.createChooser(intent, chooseTitle);
30958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
31058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                try {
31158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                    mContext.startActivity(chooseIntent);
31258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                } catch (ActivityNotFoundException ex) {
31358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                    Toast.makeText(mContext, R.string.share_error, Toast.LENGTH_SHORT).show();
31458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                }
31558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                return true;
31658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            }
317683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            case R.id.menu_send_to_voicemail: {
318683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                // Update state and save
319683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                mSendToVoicemailState = !mSendToVoicemailState;
320683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                item.setChecked(mSendToVoicemailState);
321683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                Intent intent = ContactSaveService.createSetSendToVoicemail(
322683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                        mContext, mLookupUri, mSendToVoicemailState);
323683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                mContext.startService(intent);
324683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                return true;
325683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            }
32658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        }
32758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        return false;
32858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    }
32958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
330410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro    /**
331410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro     * Calls into the contacts provider to get a pre-authorized version of the given URI.
332410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro     */
333410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro    private Uri getPreAuthorizedUri(Uri uri) {
334410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro        Bundle uriBundle = new Bundle();
335410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro        uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri);
336410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro        Bundle authResponse = mContext.getContentResolver().call(
337410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                ContactsContract.AUTHORITY_URI,
338410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                ContactsContract.Authorization.AUTHORIZATION_METHOD,
339410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                null,
340410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                uriBundle);
341410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro        if (authResponse != null) {
342410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro            return (Uri) authResponse.getParcelable(
343410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro                    ContactsContract.Authorization.KEY_AUTHORIZED_URI);
344410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro        } else {
345410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro            return uri;
346410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro        }
347410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro    }
348410d0dcd2d4119cf1c627adc68bb58775dac461aDave Santoro
34958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    @Override
35058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    public boolean handleKeyDown(int keyCode) {
35158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        switch (keyCode) {
35258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            case KeyEvent.KEYCODE_DEL: {
35358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                if (mListener != null) mListener.onDeleteRequested(mLookupUri);
35458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan                return true;
35558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            }
35658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        }
35758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        return false;
35858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan    }
359683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson
360683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    private void doPickRingtone() {
361683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson
362683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
363683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        // Allow user to pick 'Default'
364683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
365683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        // Show only ringtones
366683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE);
367683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        // Don't show 'Silent'
368683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
369683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson
370683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        Uri ringtoneUri;
371683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        if (mCustomRingtone != null) {
372683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            ringtoneUri = Uri.parse(mCustomRingtone);
373683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        } else {
374683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            // Otherwise pick default ringtone Uri so that something is selected.
375683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
376683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        }
377683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson
378683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        // Put checkmark next to the current ringtone for this contact
379683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, ringtoneUri);
380683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson
381683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        // Launch!
382683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        startActivityForResult(intent, REQUEST_CODE_PICK_RINGTONE);
383683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    }
384683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson
385683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    @Override
386683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    public void onActivityResult(int requestCode, int resultCode, Intent data) {
387683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        if (resultCode != Activity.RESULT_OK) {
388683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            return;
389683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        }
390683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson
391683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        switch (requestCode) {
392683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            case REQUEST_CODE_PICK_RINGTONE: {
393683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                Uri pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
394683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                handleRingtonePicked(pickedUri);
395683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                break;
396683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            }
397683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        }
398683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    }
399683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson
400683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    private void handleRingtonePicked(Uri pickedUri) {
401683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        if (pickedUri == null || RingtoneManager.isDefault(pickedUri)) {
402683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            mCustomRingtone = null;
403683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        } else {
404683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson            mCustomRingtone = pickedUri.toString();
405683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        }
406683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        Intent intent = ContactSaveService.createSetRingtone(
407683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson                mContext, mLookupUri, mCustomRingtone);
408683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson        mContext.startService(intent);
409683b57e1fbf27c81c9973de814fc8bb1852e6df8Isaac Katzenelson    }
4102a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann
4112a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann    /** Toggles whether to load stream items. Just for debugging */
4122a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann    public void toggleLoadStreamItems() {
4132a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann        Loader<ContactLoader.Result> loaderObj = getLoaderManager().getLoader(LOADER_DETAILS);
4142a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann        ContactLoader loader = (ContactLoader) loaderObj;
4152a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann        loader.setLoadStreamItems(!loader.getLoadStreamItems());
4162a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann    }
4172a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann
4182a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann    /** Returns whether to load stream items. Just for debugging */
4192a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann    public boolean getLoadStreamItems() {
4202a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann        Loader<ContactLoader.Result> loaderObj = getLoaderManager().getLoader(LOADER_DETAILS);
4212a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann        ContactLoader loader = (ContactLoader) loaderObj;
4222a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann        return loader != null && loader.getLoadStreamItems();
4232a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann    }
4242eb969cc399d87b659a45568fa951d394c216917Katherine Kuan}
425