Home | History | Annotate | Download | only in data
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.messaging.datamodel.data;
     18 
     19 import android.app.LoaderManager;
     20 import android.content.Context;
     21 import android.content.Loader;
     22 import android.database.Cursor;
     23 import android.os.Bundle;
     24 
     25 import com.android.messaging.datamodel.BoundCursorLoader;
     26 import com.android.messaging.datamodel.FrequentContactsCursorBuilder;
     27 import com.android.messaging.datamodel.MessagingContentProvider;
     28 import com.android.messaging.datamodel.binding.BindableData;
     29 import com.android.messaging.datamodel.binding.BindingBase;
     30 import com.android.messaging.sms.MmsConfig;
     31 import com.android.messaging.util.Assert;
     32 import com.android.messaging.util.ContactUtil;
     33 import com.android.messaging.util.LogUtil;
     34 
     35 /**
     36  * Class to access phone contacts.
     37  * The caller is responsible for ensuring that the app has READ_CONTACTS permission (see
     38  * {@link ContactUtil#hasReadContactsPermission()}) before instantiating this class.
     39  */
     40 public class ContactPickerData extends BindableData implements
     41         LoaderManager.LoaderCallbacks<Cursor> {
     42     public interface ContactPickerDataListener {
     43         void onAllContactsCursorUpdated(Cursor data);
     44         void onFrequentContactsCursorUpdated(Cursor data);
     45         void onContactCustomColorLoaded(ContactPickerData data);
     46     }
     47 
     48     private static final String BINDING_ID = "bindingId";
     49     private final Context mContext;
     50     private LoaderManager mLoaderManager;
     51     private ContactPickerDataListener mListener;
     52     private final FrequentContactsCursorBuilder mFrequentContactsCursorBuilder;
     53 
     54     public ContactPickerData(final Context context, final ContactPickerDataListener listener) {
     55         mListener = listener;
     56         mContext = context;
     57         mFrequentContactsCursorBuilder = new FrequentContactsCursorBuilder();
     58     }
     59 
     60     private static final int ALL_CONTACTS_LOADER = 1;
     61     private static final int FREQUENT_CONTACTS_LOADER = 2;
     62     private static final int PARTICIPANT_LOADER = 3;
     63 
     64     @Override
     65     public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
     66         final String bindingId = args.getString(BINDING_ID);
     67         // Check if data still bound to the requesting ui element
     68         if (isBound(bindingId)) {
     69             switch (id) {
     70                 case ALL_CONTACTS_LOADER:
     71                     return ContactUtil.getPhones(mContext)
     72                             .createBoundCursorLoader(bindingId);
     73                 case FREQUENT_CONTACTS_LOADER:
     74                     return ContactUtil.getFrequentContacts(mContext)
     75                             .createBoundCursorLoader(bindingId);
     76                 case PARTICIPANT_LOADER:
     77                     return new BoundCursorLoader(bindingId, mContext,
     78                             MessagingContentProvider.PARTICIPANTS_URI,
     79                             ParticipantData.ParticipantsQuery.PROJECTION, null, null, null);
     80                 default:
     81                     Assert.fail("Unknown loader id for contact picker!");
     82                     break;
     83             }
     84         } else {
     85             LogUtil.w(LogUtil.BUGLE_TAG, "Loader created after unbinding the contacts list");
     86         }
     87         return null;
     88     }
     89 
     90     /**
     91      * {@inheritDoc}
     92      */
     93     @Override
     94     public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
     95         final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
     96         if (isBound(cursorLoader.getBindingId())) {
     97             switch (loader.getId()) {
     98                 case ALL_CONTACTS_LOADER:
     99                     mListener.onAllContactsCursorUpdated(data);
    100                     mFrequentContactsCursorBuilder.setAllContacts(data);
    101                     break;
    102                 case FREQUENT_CONTACTS_LOADER:
    103                     mFrequentContactsCursorBuilder.setFrequents(data);
    104                     break;
    105                 case PARTICIPANT_LOADER:
    106                     mListener.onContactCustomColorLoaded(this);
    107                     break;
    108                 default:
    109                     Assert.fail("Unknown loader id for contact picker!");
    110                     break;
    111             }
    112 
    113             if (loader.getId() != PARTICIPANT_LOADER) {
    114                 // The frequent contacts cursor to be used in the UI depends on results from both
    115                 // all contacts and frequent contacts loader, and we don't know which will finish
    116                 // first. Therefore, try to build the cursor and notify the listener if it's
    117                 // successfully built.
    118                 final Cursor frequentContactsCursor = mFrequentContactsCursorBuilder.build();
    119                 if (frequentContactsCursor != null) {
    120                     mListener.onFrequentContactsCursorUpdated(frequentContactsCursor);
    121                 }
    122             }
    123         } else {
    124             LogUtil.w(LogUtil.BUGLE_TAG, "Loader finished after unbinding the contacts list");
    125         }
    126     }
    127 
    128     /**
    129      * {@inheritDoc}
    130      */
    131     @Override
    132     public void onLoaderReset(final Loader<Cursor> loader) {
    133         final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader;
    134         if (isBound(cursorLoader.getBindingId())) {
    135             switch (loader.getId()) {
    136                 case ALL_CONTACTS_LOADER:
    137                     mListener.onAllContactsCursorUpdated(null);
    138                     mFrequentContactsCursorBuilder.setAllContacts(null);
    139                     break;
    140                 case FREQUENT_CONTACTS_LOADER:
    141                     mListener.onFrequentContactsCursorUpdated(null);
    142                     mFrequentContactsCursorBuilder.setFrequents(null);
    143                     break;
    144                 case PARTICIPANT_LOADER:
    145                     mListener.onContactCustomColorLoaded(this);
    146                     break;
    147                 default:
    148                     Assert.fail("Unknown loader id for contact picker!");
    149                     break;
    150             }
    151         } else {
    152             LogUtil.w(LogUtil.BUGLE_TAG, "Loader reset after unbinding the contacts list");
    153         }
    154     }
    155 
    156     public void init(final LoaderManager loaderManager,
    157                      final BindingBase<ContactPickerData> binding) {
    158         final Bundle args = new Bundle();
    159         args.putString(BINDING_ID, binding.getBindingId());
    160         mLoaderManager = loaderManager;
    161         mLoaderManager.initLoader(ALL_CONTACTS_LOADER, args, this);
    162         mLoaderManager.initLoader(FREQUENT_CONTACTS_LOADER, args, this);
    163         mLoaderManager.initLoader(PARTICIPANT_LOADER, args, this);
    164     }
    165 
    166     @Override
    167     protected void unregisterListeners() {
    168         mListener = null;
    169 
    170 
    171         // This could be null if we bind but the caller doesn't init the BindableData
    172         if (mLoaderManager != null) {
    173             mLoaderManager.destroyLoader(ALL_CONTACTS_LOADER);
    174             mLoaderManager.destroyLoader(FREQUENT_CONTACTS_LOADER);
    175             mLoaderManager.destroyLoader(PARTICIPANT_LOADER);
    176             mLoaderManager = null;
    177         }
    178         mFrequentContactsCursorBuilder.resetBuilder();
    179     }
    180 
    181     public static boolean isTooManyParticipants(final int participantCount) {
    182         // When creating a conversation, the conversation will be created using the system's
    183         // default SIM, so use the default MmsConfig's recipient limit.
    184         return (participantCount > MmsConfig.get(ParticipantData.DEFAULT_SELF_SUB_ID)
    185                 .getRecipientLimit());
    186     }
    187 
    188     public static boolean getCanAddMoreParticipants(final int participantCount) {
    189         // When creating a conversation, the conversation will be created using the system's
    190         // default SIM, so use the default MmsConfig's recipient limit.
    191         return (participantCount < MmsConfig.get(ParticipantData.DEFAULT_SELF_SUB_ID)
    192                 .getRecipientLimit());
    193     }
    194 }
    195