Home | History | Annotate | Download | only in datamodel
      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;
     18 
     19 import android.content.Context;
     20 import android.database.Cursor;
     21 import android.net.Uri;
     22 import android.provider.ContactsContract;
     23 import android.provider.ContactsContract.Contacts;
     24 
     25 import com.android.messaging.util.FallbackStrategies;
     26 import com.android.messaging.util.FallbackStrategies.Strategy;
     27 import com.android.messaging.util.LogUtil;
     28 import com.android.messaging.util.OsUtil;
     29 
     30 /**
     31  * Helper for querying frequent (and/or starred) contacts.
     32  */
     33 public class FrequentContactsCursorQueryData extends CursorQueryData {
     34     private static final String TAG = LogUtil.BUGLE_TAG;
     35 
     36     private static class FrequentContactsCursorLoader extends BoundCursorLoader {
     37         private final Uri mOriginalUri;
     38 
     39         FrequentContactsCursorLoader(String bindingId, Context context, Uri uri,
     40                 String[] projection, String selection, String[] selectionArgs, String sortOrder) {
     41             super(bindingId, context, uri, projection, selection, selectionArgs, sortOrder);
     42             mOriginalUri = uri;
     43         }
     44 
     45         @Override
     46         public Cursor loadInBackground() {
     47             return FallbackStrategies
     48                     .startWith(new PrimaryStrequentContactsQueryStrategy())
     49                     .thenTry(new FrequentOnlyContactsQueryStrategy())
     50                     .thenTry(new PhoneOnlyStrequentContactsQueryStrategy())
     51                     .execute(null);
     52         }
     53 
     54         private abstract class StrequentContactsQueryStrategy implements Strategy<Void, Cursor> {
     55             @Override
     56             public Cursor execute(Void params) throws Exception {
     57                 final Uri uri = getUri();
     58                 if (uri != null) {
     59                     setUri(uri);
     60                 }
     61                 return FrequentContactsCursorLoader.super.loadInBackground();
     62             }
     63             protected abstract Uri getUri();
     64         }
     65 
     66         private class PrimaryStrequentContactsQueryStrategy extends StrequentContactsQueryStrategy {
     67             @Override
     68             protected Uri getUri() {
     69                 // Use the original URI requested.
     70                 return mOriginalUri;
     71             }
     72         }
     73 
     74         private class FrequentOnlyContactsQueryStrategy extends StrequentContactsQueryStrategy {
     75             @Override
     76             protected Uri getUri() {
     77                 // Some phones have a buggy implementation of the Contacts provider which crashes
     78                 // when we query for strequent (starred+frequent) contacts (b/17991485).
     79                 // If this happens, switch to just querying for frequent contacts.
     80                 return Contacts.CONTENT_FREQUENT_URI;
     81             }
     82         }
     83 
     84         private class PhoneOnlyStrequentContactsQueryStrategy extends
     85                 StrequentContactsQueryStrategy {
     86             @Override
     87             protected Uri getUri() {
     88                 // Some 3rd party ROMs have content provider
     89                 // implementation where invalid SQL queries are returned for regular strequent
     90                 // queries. Using strequent_phone_only query as a fallback to display only phone
     91                 // contacts. This is the last-ditch effort; if this fails, we will display an
     92                 // empty frequent list (b/18354836).
     93                 final String strequentQueryParam = OsUtil.isAtLeastL() ?
     94                         ContactsContract.STREQUENT_PHONE_ONLY : "strequent_phone_only";
     95                 // TODO: Handle enterprise contacts post M once contacts provider supports it
     96                 return Contacts.CONTENT_STREQUENT_URI.buildUpon()
     97                         .appendQueryParameter(strequentQueryParam, "true").build();
     98             }
     99         }
    100     }
    101 
    102     public FrequentContactsCursorQueryData(Context context, String[] projection,
    103             String selection, String[] selectionArgs, String sortOrder) {
    104         // TODO: Handle enterprise contacts post M once contacts provider supports it
    105         super(context, Contacts.CONTENT_STREQUENT_URI, projection, selection, selectionArgs,
    106                 sortOrder);
    107     }
    108 
    109     @Override
    110     public BoundCursorLoader createBoundCursorLoader(String bindingId) {
    111         return new FrequentContactsCursorLoader(bindingId, mContext, mUri, mProjection, mSelection,
    112                 mSelectionArgs, mSortOrder);
    113     }
    114 }
    115