1 /*
2  * Copyright (C) 2018 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.dialer.phonelookup.cp2;
18 
19 import android.content.Context;
20 import android.database.Cursor;
21 import android.provider.ContactsContract;
22 import android.provider.ContactsContract.CommonDataKinds.Phone;
23 import android.provider.ContactsContract.Contacts;
24 import android.provider.ContactsContract.PhoneLookup;
25 import android.text.TextUtils;
26 import com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo;
27 
28 /**
29  * A class providing projection-related functionality for {@link
30  * com.android.dialer.phonelookup.PhoneLookup} implementations for ContactsProvider2 (CP2).
31  */
32 final class Cp2Projections {
33 
34   // Projection for performing lookups using the PHONE table
35   private static final String[] PHONE_PROJECTION =
36       new String[] {
37         Phone.DISPLAY_NAME_PRIMARY, // 0
38         Phone.PHOTO_THUMBNAIL_URI, // 1
39         Phone.PHOTO_URI, // 2
40         Phone.PHOTO_ID, // 3
41         Phone.TYPE, // 4
42         Phone.LABEL, // 5
43         Phone.NORMALIZED_NUMBER, // 6
44         Phone.CONTACT_ID, // 7
45         Phone.LOOKUP_KEY, // 8
46         Phone.CARRIER_PRESENCE
47       };
48 
49   // Projection for performing lookups using the PHONE_LOOKUP table
50   private static final String[] PHONE_LOOKUP_PROJECTION =
51       new String[] {
52         PhoneLookup.DISPLAY_NAME_PRIMARY, // 0
53         PhoneLookup.PHOTO_THUMBNAIL_URI, // 1
54         PhoneLookup.PHOTO_URI, // 2
55         PhoneLookup.PHOTO_ID, // 3
56         PhoneLookup.TYPE, // 4
57         PhoneLookup.LABEL, // 5
58         PhoneLookup.NORMALIZED_NUMBER, // 6
59         PhoneLookup.CONTACT_ID, // 7
60         PhoneLookup.LOOKUP_KEY // 8
61       };
62 
63   // The following indexes should match the common columns in
64   // PHONE_PROJECTION and PHONE_LOOKUP_PROJECTION above.
65   private static final int CP2_INFO_NAME_INDEX = 0;
66   private static final int CP2_INFO_PHOTO_THUMBNAIL_URI_INDEX = 1;
67   private static final int CP2_INFO_PHOTO_URI_INDEX = 2;
68   private static final int CP2_INFO_PHOTO_ID_INDEX = 3;
69   private static final int CP2_INFO_TYPE_INDEX = 4;
70   private static final int CP2_INFO_LABEL_INDEX = 5;
71   private static final int CP2_INFO_NORMALIZED_NUMBER_INDEX = 6;
72   private static final int CP2_INFO_CONTACT_ID_INDEX = 7;
73   private static final int CP2_INFO_LOOKUP_KEY_INDEX = 8;
74 
Cp2Projections()75   private Cp2Projections() {}
76 
getProjectionForPhoneTable()77   static String[] getProjectionForPhoneTable() {
78     return PHONE_PROJECTION;
79   }
80 
getProjectionForPhoneLookupTable()81   static String[] getProjectionForPhoneLookupTable() {
82     return PHONE_LOOKUP_PROJECTION;
83   }
84 
85   /**
86    * Builds a {@link Cp2ContactInfo} based on the current row of {@code cursor}, of which the
87    * projection is either {@link #PHONE_PROJECTION} or {@link #PHONE_LOOKUP_PROJECTION}.
88    */
buildCp2ContactInfoFromCursor( Context appContext, Cursor cursor, long directoryId)89   static Cp2ContactInfo buildCp2ContactInfoFromCursor(
90       Context appContext, Cursor cursor, long directoryId) {
91     String displayName = cursor.getString(CP2_INFO_NAME_INDEX);
92     String photoThumbnailUri = cursor.getString(CP2_INFO_PHOTO_THUMBNAIL_URI_INDEX);
93     String photoUri = cursor.getString(CP2_INFO_PHOTO_URI_INDEX);
94     int photoId = cursor.getInt(CP2_INFO_PHOTO_ID_INDEX);
95     int type = cursor.getInt(CP2_INFO_TYPE_INDEX);
96     String label = cursor.getString(CP2_INFO_LABEL_INDEX);
97     int contactId = cursor.getInt(CP2_INFO_CONTACT_ID_INDEX);
98     String lookupKey = cursor.getString(CP2_INFO_LOOKUP_KEY_INDEX);
99 
100     Cp2ContactInfo.Builder infoBuilder = Cp2ContactInfo.newBuilder();
101     if (!TextUtils.isEmpty(displayName)) {
102       infoBuilder.setName(displayName);
103     }
104     if (!TextUtils.isEmpty(photoThumbnailUri)) {
105       infoBuilder.setPhotoThumbnailUri(photoThumbnailUri);
106     }
107     if (!TextUtils.isEmpty(photoUri)) {
108       infoBuilder.setPhotoUri(photoUri);
109     }
110     if (photoId > 0) {
111       infoBuilder.setPhotoId(photoId);
112     }
113 
114     // Phone.getTypeLabel returns "Custom" if given (0, null) which is not of any use. Just
115     // omit setting the label if there's no information for it.
116     if (type != 0 || !TextUtils.isEmpty(label)) {
117       infoBuilder.setLabel(Phone.getTypeLabel(appContext.getResources(), type, label).toString());
118     }
119     infoBuilder.setContactId(contactId);
120     if (!TextUtils.isEmpty(lookupKey)) {
121       infoBuilder.setLookupUri(
122           Contacts.getLookupUri(contactId, lookupKey)
123               .buildUpon()
124               .appendQueryParameter(
125                   ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId))
126               .build()
127               .toString());
128     }
129 
130     // Only PHONE_PROJECTION has a column containing carrier presence info.
131     int carrierPresenceColumn = cursor.getColumnIndex(Phone.CARRIER_PRESENCE);
132     if (carrierPresenceColumn != -1) {
133       int carrierPresenceInfo = cursor.getInt(carrierPresenceColumn);
134       infoBuilder.setCanSupportCarrierVideoCall(
135           (carrierPresenceInfo & Phone.CARRIER_PRESENCE_VT_CAPABLE)
136               == Phone.CARRIER_PRESENCE_VT_CAPABLE);
137     }
138 
139     return infoBuilder.build();
140   }
141 
142   /** Returns the normalized number in the current row of {@code cursor}. */
getNormalizedNumberFromCursor(Cursor cursor)143   static String getNormalizedNumberFromCursor(Cursor cursor) {
144     return cursor.getString(CP2_INFO_NORMALIZED_NUMBER_INDEX);
145   }
146 }
147