summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/com/android/dialer/app/settings/DialerSettingsActivity.java18
-rw-r--r--java/com/android/dialer/assisteddialing/ConcreteCreator.java25
-rw-r--r--java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml22
-rw-r--r--java/com/android/dialer/assisteddialing/ui/AssistedDialingSettingFragment.java31
-rw-r--r--java/com/android/dialer/assisteddialing/ui/res/values/string.xml27
-rw-r--r--java/com/android/dialer/assisteddialing/ui/res/xml/assisted_dialing_setting.xml26
-rw-r--r--java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java9
-rw-r--r--java/com/android/dialer/phonenumbercache/ContactInfoHelper.java36
-rw-r--r--java/com/android/dialer/phonenumberutil/PhoneNumberHelper.java75
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java (renamed from java/com/android/dialer/voicemail/listui/NewVoicemailCallLogAdapter.java)29
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailCallLogViewHolder.java50
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java53
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java60
-rw-r--r--java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java91
-rw-r--r--java/com/android/dialer/voicemail/listui/VoicemailEntryText.java42
-rw-r--r--java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_entry.xml2
-rw-r--r--java/com/android/dialer/voicemail/listui/res/values/strings.xml20
-rw-r--r--java/com/android/dialer/voicemail/model/VoicemailEntry.java89
-rw-r--r--java/com/android/incallui/CallerInfo.java246
19 files changed, 718 insertions, 233 deletions
diff --git a/java/com/android/dialer/app/settings/DialerSettingsActivity.java b/java/com/android/dialer/app/settings/DialerSettingsActivity.java
index 10ef9ed60..706f0985a 100644
--- a/java/com/android/dialer/app/settings/DialerSettingsActivity.java
+++ b/java/com/android/dialer/app/settings/DialerSettingsActivity.java
@@ -33,9 +33,12 @@ import android.view.MenuItem;
import android.widget.Toast;
import com.android.dialer.about.AboutPhoneFragment;
import com.android.dialer.app.R;
+import com.android.dialer.assisteddialing.ConcreteCreator;
+import com.android.dialer.assisteddialing.ui.AssistedDialingSettingFragment;
import com.android.dialer.blocking.FilteredNumberCompat;
import com.android.dialer.common.LogUtil;
import com.android.dialer.compat.telephony.TelephonyManagerCompat;
+import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.proguard.UsedByReflection;
import com.android.voicemail.VoicemailClient;
import com.android.voicemail.VoicemailComponent;
@@ -135,6 +138,21 @@ public class DialerSettingsActivity extends AppCompatPreferenceActivity {
target.add(accessibilitySettingsHeader);
}
+ boolean isAssistedDialingEnabled =
+ ConcreteCreator.isAssistedDialingEnabled(
+ ConfigProviderBindings.get(getApplicationContext()));
+ LogUtil.i(
+ "DialerSettingsActivity.onBuildHeaders",
+ "showing assisted dialing header: " + isAssistedDialingEnabled);
+ if (isAssistedDialingEnabled) {
+
+ Header assistedDialingSettingsHeader = new Header();
+ assistedDialingSettingsHeader.titleRes =
+ com.android.dialer.assisteddialing.ui.R.string.assisted_dialing_setting_title;
+ assistedDialingSettingsHeader.fragment = AssistedDialingSettingFragment.class.getName();
+ target.add(assistedDialingSettingsHeader);
+ }
+
if (showAbout()) {
Header aboutPhoneHeader = new Header();
aboutPhoneHeader.titleRes = R.string.about_phone_label;
diff --git a/java/com/android/dialer/assisteddialing/ConcreteCreator.java b/java/com/android/dialer/assisteddialing/ConcreteCreator.java
index a8a9d2ab3..1790b8f3f 100644
--- a/java/com/android/dialer/assisteddialing/ConcreteCreator.java
+++ b/java/com/android/dialer/assisteddialing/ConcreteCreator.java
@@ -20,8 +20,10 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Build.VERSION_CODES;
+import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.telephony.TelephonyManager;
+import com.android.dialer.assisteddialing.ui.R;
import com.android.dialer.common.LogUtil;
import com.android.dialer.configprovider.ConfigProvider;
import com.android.dialer.configprovider.ConfigProviderBindings;
@@ -63,8 +65,15 @@ public final class ConcreteCreator {
throw new NullPointerException("Provided context was null");
}
- if ((Build.VERSION.SDK_INT < BUILD_CODE_FLOOR || Build.VERSION.SDK_INT > BUILD_CODE_CEILING)
- || !configProvider.getBoolean("assisted_dialing_enabled", false)) {
+ if (!isAssistedDialingEnabled(configProvider)) {
+ LogUtil.i("ConcreteCreator.createNewAssistedDialingMediator", "feature not enabled");
+ return new AssistedDialingMediatorStub();
+ }
+
+ if (!PreferenceManager.getDefaultSharedPreferences(context)
+ .getBoolean(context.getString(R.string.assisted_dialing_setting_toggle_key), false)) {
+ LogUtil.i("ConcreteCreator.createNewAssistedDialingMediator", "disabled by local setting");
+
return new AssistedDialingMediatorStub();
}
@@ -74,4 +83,16 @@ public final class ConcreteCreator {
return new AssistedDialingMediatorImpl(
new LocationDetector(telephonyManager), new NumberTransformer(constraints));
}
+
+ /** Returns a boolean indicating whether or not the assisted dialing feature is enabled. */
+ public static boolean isAssistedDialingEnabled(@NonNull ConfigProvider configProvider) {
+ if (configProvider == null) {
+ LogUtil.i("ConcreteCreator.isAssistedDialingEnabled", "provided configProvider was null");
+ throw new NullPointerException("Provided configProvider was null");
+ }
+
+ return (Build.VERSION.SDK_INT >= BUILD_CODE_FLOOR
+ && Build.VERSION.SDK_INT <= BUILD_CODE_CEILING)
+ && configProvider.getBoolean("assisted_dialing_enabled", false);
+ }
}
diff --git a/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml b/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml
new file mode 100644
index 000000000..6625dff07
--- /dev/null
+++ b/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2017 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.dialer.assisteddialing">
+
+ <uses-sdk
+ android:minSdkVersion="23"
+ android:targetSdkVersion="24"/>
+
+</manifest> \ No newline at end of file
diff --git a/java/com/android/dialer/assisteddialing/ui/AssistedDialingSettingFragment.java b/java/com/android/dialer/assisteddialing/ui/AssistedDialingSettingFragment.java
new file mode 100644
index 000000000..8847448cd
--- /dev/null
+++ b/java/com/android/dialer/assisteddialing/ui/AssistedDialingSettingFragment.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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.dialer.assisteddialing.ui;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+/** The setting for Assisted Dialing */
+public class AssistedDialingSettingFragment extends PreferenceFragment {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.assisted_dialing_setting);
+ }
+}
diff --git a/java/com/android/dialer/assisteddialing/ui/res/values/string.xml b/java/com/android/dialer/assisteddialing/ui/res/values/string.xml
new file mode 100644
index 000000000..cd159bfd5
--- /dev/null
+++ b/java/com/android/dialer/assisteddialing/ui/res/values/string.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 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
+ -->
+
+<resources>
+ <!-- Label for a setting enabling assisted dialing [CHAR LIMIT=40]-->
+ <string name="assisted_dialing_setting_title">Assisted dialing</string>
+
+ <!-- Label for a setting enabling assisted dialing switch preference-->
+ <string name="assisted_dialing_setting_summary">Automatically correct the phone number prefix when traveling and calling international numbers</string>
+
+ <!-- Key for the assisted dialing setting toggle-->
+ <string name="assisted_dialing_setting_toggle_key" translatable="false">assisted_dialing_setting_toggle_key</string>
+</resources> \ No newline at end of file
diff --git a/java/com/android/dialer/assisteddialing/ui/res/xml/assisted_dialing_setting.xml b/java/com/android/dialer/assisteddialing/ui/res/xml/assisted_dialing_setting.xml
new file mode 100644
index 000000000..8e3c62dde
--- /dev/null
+++ b/java/com/android/dialer/assisteddialing/ui/res/xml/assisted_dialing_setting.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ Copyright (C) 2017 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.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <SwitchPreference
+ android:defaultValue="false"
+ android:key="@string/assisted_dialing_setting_toggle_key"
+ android:title="@string/assisted_dialing_setting_title"
+ android:summary="@string/assisted_dialing_setting_summary" />
+
+</PreferenceScreen> \ No newline at end of file
diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
index a5f1425f8..589fe6384 100644
--- a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
+++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
@@ -60,6 +60,7 @@ class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper {
.toString();
/** Deletes all but the first maxRows rows (by timestamp) to keep the table a manageable size. */
+ // TODO(zachh): Prevent voicemails from being garbage collected.
private static final String CREATE_TRIGGER_SQL =
"create trigger delete_old_rows after insert on "
+ AnnotatedCallLog.TABLE
@@ -79,12 +80,20 @@ class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper {
+ AnnotatedCallLog.TABLE
+ " )); end;";
+ private static final String CREATE_INDEX_ON_CALL_TYPE_SQL =
+ "create index call_type_index on "
+ + AnnotatedCallLog.TABLE
+ + " ("
+ + AnnotatedCallLog.CALL_TYPE
+ + ");";
+
@Override
public void onCreate(SQLiteDatabase db) {
LogUtil.enterBlock("AnnotatedCallLogDatabaseHelper.onCreate");
long startTime = System.currentTimeMillis();
db.execSQL(CREATE_TABLE_SQL);
db.execSQL(String.format(Locale.US, CREATE_TRIGGER_SQL, maxRows, maxRows));
+ db.execSQL(CREATE_INDEX_ON_CALL_TYPE_SQL);
// TODO(zachh): Consider logging impression.
LogUtil.i(
"AnnotatedCallLogDatabaseHelper.onCreate",
diff --git a/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java b/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java
index b680bd57d..f501792f9 100644
--- a/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java
+++ b/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java
@@ -337,30 +337,30 @@ public class ContactInfoHelper {
return ContactInfo.EMPTY;
}
- Cursor phoneLookupCursor = null;
- try {
- String[] projection = PhoneQuery.getPhoneLookupProjection(uri);
- phoneLookupCursor = mContext.getContentResolver().query(uri, projection, null, null, null);
- } catch (NullPointerException e) {
- LogUtil.e("ContactInfoHelper.lookupContactFromUri", "phone lookup", e);
- // Trap NPE from pre-N CP2
- return null;
- }
- if (phoneLookupCursor == null) {
- LogUtil.d("ContactInfoHelper.lookupContactFromUri", "phoneLookupCursor is null");
- return null;
- }
+ try (Cursor phoneLookupCursor =
+ mContext
+ .getContentResolver()
+ .query(uri, PhoneQuery.getPhoneLookupProjection(uri), null, null, null)) {
+ if (phoneLookupCursor == null) {
+ LogUtil.d("ContactInfoHelper.lookupContactFromUri", "phoneLookupCursor is null");
+ return null;
+ }
- try {
if (!phoneLookupCursor.moveToFirst()) {
return ContactInfo.EMPTY;
}
- String lookupKey = phoneLookupCursor.getString(PhoneQuery.LOOKUP_KEY);
- ContactInfo contactInfo = createPhoneLookupContactInfo(phoneLookupCursor, lookupKey);
+
+ Cursor matchedCursor =
+ PhoneNumberHelper.getCursorMatchForContactLookupUri(
+ phoneLookupCursor, PhoneQuery.MATCHED_NUMBER, uri);
+ if (matchedCursor == null) {
+ return ContactInfo.EMPTY;
+ }
+
+ String lookupKey = matchedCursor.getString(PhoneQuery.LOOKUP_KEY);
+ ContactInfo contactInfo = createPhoneLookupContactInfo(matchedCursor, lookupKey);
fillAdditionalContactInfo(mContext, contactInfo);
return contactInfo;
- } finally {
- phoneLookupCursor.close();
}
}
diff --git a/java/com/android/dialer/phonenumberutil/PhoneNumberHelper.java b/java/com/android/dialer/phonenumberutil/PhoneNumberHelper.java
index cc9b73081..84cbb6947 100644
--- a/java/com/android/dialer/phonenumberutil/PhoneNumberHelper.java
+++ b/java/com/android/dialer/phonenumberutil/PhoneNumberHelper.java
@@ -17,6 +17,8 @@
package com.android.dialer.phonenumberutil;
import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
import android.os.Trace;
import android.provider.CallLog;
import android.support.annotation.Nullable;
@@ -24,6 +26,7 @@ import android.telecom.PhoneAccountHandle;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.compat.CompatUtils;
import com.android.dialer.compat.telephony.TelephonyManagerCompat;
@@ -47,6 +50,78 @@ public class PhoneNumberHelper {
}
/**
+ * Find the cursor pointing to a number that matches the number in a contact lookup URI.
+ *
+ * <p>When determining whether two phone numbers are identical enough for caller ID purposes, the
+ * Contacts Provider uses {@link PhoneNumberUtils#compare(String, String)}, which ignores special
+ * dialable characters such as '#', '*', '+', etc. This makes it possible for the cursor returned
+ * by the Contacts Provider to have multiple rows even when the URI asks for a specific number.
+ *
+ * <p>For example, suppose the user has two contacts whose numbers are "#123" and "123",
+ * respectively. When the URI asks for number "123", both numbers will be returned. Therefore, the
+ * following strategy is employed to find a match.
+ *
+ * <p>If the cursor points to a global phone number (i.e., a number that can be accepted by {@link
+ * PhoneNumberUtils#isGlobalPhoneNumber(String)}) and the lookup number in the URI is a PARTIAL
+ * match, return the cursor.
+ *
+ * <p>If the cursor points to a number that is not a global phone number, return the cursor iff
+ * the lookup number in the URI is an EXACT match.
+ *
+ * <p>Return null in all other circumstances.
+ *
+ * @param cursor A cursor returned by the Contacts Provider.
+ * @param columnIndexForNumber The index of the column where phone numbers are stored. It is the
+ * caller's responsibility to pass the correct column index.
+ * @param contactLookupUri A URI used to retrieve a contact via the Contacts Provider. It is the
+ * caller's responsibility to ensure the URI is one that asks for a specific phone number.
+ * @return The cursor considered as a match by the description above or null if no such cursor can
+ * be found.
+ */
+ public static Cursor getCursorMatchForContactLookupUri(
+ Cursor cursor, int columnIndexForNumber, Uri contactLookupUri) {
+ if (cursor == null || contactLookupUri == null) {
+ return null;
+ }
+
+ if (!cursor.moveToFirst()) {
+ return null;
+ }
+
+ Assert.checkArgument(
+ 0 <= columnIndexForNumber && columnIndexForNumber < cursor.getColumnCount());
+
+ String lookupNumber = contactLookupUri.getLastPathSegment();
+ if (lookupNumber == null) {
+ return null;
+ }
+
+ boolean isMatchFound;
+ do {
+ // All undialable characters should be converted/removed before comparing the lookup number
+ // and the existing contact number.
+ String rawExistingContactNumber =
+ PhoneNumberUtils.stripSeparators(
+ PhoneNumberUtils.convertKeypadLettersToDigits(
+ cursor.getString(columnIndexForNumber)));
+ String rawQueryNumber =
+ PhoneNumberUtils.stripSeparators(
+ PhoneNumberUtils.convertKeypadLettersToDigits(lookupNumber));
+
+ isMatchFound =
+ PhoneNumberUtils.isGlobalPhoneNumber(rawExistingContactNumber)
+ ? rawExistingContactNumber.contains(rawQueryNumber)
+ : rawExistingContactNumber.equals(rawQueryNumber);
+
+ if (isMatchFound) {
+ return cursor;
+ }
+ } while (cursor.moveToNext());
+
+ return null;
+ }
+
+ /**
* Returns true if the given number is the number of the configured voicemail. To be able to
* mock-out this, it is not a static method.
*/
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailCallLogAdapter.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
index b40c8630e..71178ceba 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailCallLogAdapter.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
@@ -15,41 +15,40 @@
*/
package com.android.dialer.voicemail.listui;
+import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.dialer.common.LogUtil;
-import com.android.dialer.voicemail.datasources.VoicemailData;
-import java.util.List;
/** {@link RecyclerView.Adapter} for the new voicemail call log fragment. */
-final class NewVoicemailCallLogAdapter extends RecyclerView.Adapter<NewVoicemailCallLogViewHolder> {
+final class NewVoicemailAdapter extends RecyclerView.Adapter<NewVoicemailViewHolder> {
- private final List<VoicemailData> voicemailData;
+ private final Cursor cursor;
- NewVoicemailCallLogAdapter(List<VoicemailData> dataSet) {
- voicemailData = dataSet;
+ /** @param cursor whose projection is {@link VoicemailCursorLoader.VOICEMAIL_COLUMNS} */
+ NewVoicemailAdapter(Cursor cursor) {
+ this.cursor = cursor;
}
@Override
- public NewVoicemailCallLogViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
-
+ public NewVoicemailViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
- View v = inflater.inflate(R.layout.new_voicemail_call_log_entry, viewGroup, false);
- NewVoicemailCallLogViewHolder newVoicemailCallLogViewHolder =
- new NewVoicemailCallLogViewHolder(v);
- return newVoicemailCallLogViewHolder;
+ View view = inflater.inflate(R.layout.new_voicemail_call_log_entry, viewGroup, false);
+ NewVoicemailViewHolder newVoicemailViewHolder = new NewVoicemailViewHolder(view);
+ return newVoicemailViewHolder;
}
@Override
- public void onBindViewHolder(NewVoicemailCallLogViewHolder viewHolder, int position) {
+ public void onBindViewHolder(NewVoicemailViewHolder viewHolder, int position) {
LogUtil.i("onBindViewHolder", "position" + position);
- viewHolder.bind(voicemailData.get(position));
+ cursor.moveToPosition(position);
+ viewHolder.bind(cursor);
}
@Override
public int getItemCount() {
- return voicemailData.size();
+ return cursor.getCount();
}
}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailCallLogViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailCallLogViewHolder.java
deleted file mode 100644
index 9ec768464..000000000
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailCallLogViewHolder.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2017 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.dialer.voicemail.listui;
-
-import android.support.v7.widget.RecyclerView;
-import android.view.View;
-import android.widget.TextView;
-import com.android.dialer.voicemail.datasources.VoicemailData;
-
-/** {@link RecyclerView.ViewHolder} for the new voicemail call log. */
-final class NewVoicemailCallLogViewHolder extends RecyclerView.ViewHolder {
-
- private final TextView primaryTextView;
- private final TextView secondaryTextView;
- private final TextView transcriptionTextView;
-
- NewVoicemailCallLogViewHolder(View view) {
- super(view);
- primaryTextView = (TextView) view.findViewById(R.id.primary_text);
- secondaryTextView = (TextView) view.findViewById(R.id.secondary_text);
- transcriptionTextView = (TextView) view.findViewById(R.id.transcription_text);
- }
-
- void bind(VoicemailData voicemailData) {
- primaryTextView.setText(voicemailData.name());
- secondaryTextView.setText(getVoicemailLocationDateAndDuration(voicemailData));
- transcriptionTextView.setText(voicemailData.transcription());
- }
-
- private String getVoicemailLocationDateAndDuration(VoicemailData voicemailData) {
- return voicemailData.location()
- + " · "
- + voicemailData.date()
- + " · "
- + voicemailData.duration();
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
index 3629b7551..1912e1e3f 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
@@ -16,49 +16,50 @@
package com.android.dialer.voicemail.listui;
+import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager.LoaderCallbacks;
+import android.support.v4.content.Loader;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.dialer.common.LogUtil;
-import com.android.dialer.voicemail.datasources.VoicemailData;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
/** Fragment for Dialer Voicemail Tab. */
-public final class NewVoicemailFragment extends Fragment {
+public final class NewVoicemailFragment extends Fragment implements LoaderCallbacks<Cursor> {
+
+ private RecyclerView recyclerView;
+
@Nullable
@Override
public View onCreateView(
LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.new_voicemail_call_log_fragment, container, false);
- RecyclerView recyclerView =
- (RecyclerView) view.findViewById(R.id.new_voicemail_call_log_recycler_view);
- recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+ recyclerView = view.findViewById(R.id.new_voicemail_call_log_recycler_view);
+ getLoaderManager().restartLoader(0, null, this);
+ return view;
+ }
- // TODO(uabdullah): To be removed once we hook up the UI to the voicemail backend
- List<VoicemailData> voicemailData = new ArrayList<>();
- Random rand = new Random();
- for (int i = 0; i < 50; i++) {
- VoicemailData mocked =
- VoicemailData.builder()
- .setName("Fatima Abdullah " + i)
- .setLocation("San Francisco, CA")
- .setDate("March " + (rand.nextInt(30) + 1))
- .setDuration("00:" + (rand.nextInt(50) + 10))
- .setTranscription(
- "This is a transcription text message that literally means nothing.")
- .build();
- voicemailData.add(mocked);
- }
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ LogUtil.enterBlock("NewVoicemailFragment.onCreateLoader");
+ return new VoicemailCursorLoader(getContext());
+ }
- LogUtil.i("onCreateView", "size of input:" + voicemailData.size());
- recyclerView.setAdapter(new NewVoicemailCallLogAdapter(voicemailData));
- return view;
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ LogUtil.i("NewVoicemailFragment.onCreateLoader", "cursor size is %d", data.getCount());
+ recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+ recyclerView.setAdapter(new NewVoicemailAdapter(data));
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+ LogUtil.enterBlock("NewVoicemailFragment.onLoaderReset");
+ recyclerView.setAdapter(null);
}
}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
new file mode 100644
index 000000000..daa24c86c
--- /dev/null
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 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.dialer.voicemail.listui;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.QuickContactBadge;
+import android.widget.TextView;
+import com.android.dialer.contactphoto.ContactPhotoManager;
+import com.android.dialer.lettertile.LetterTileDrawable;
+import com.android.dialer.voicemail.model.VoicemailEntry;
+
+/** {@link RecyclerView.ViewHolder} for the new voicemail tab. */
+final class NewVoicemailViewHolder extends RecyclerView.ViewHolder {
+
+ private final Context context;
+ private final TextView primaryTextView;
+ private final QuickContactBadge quickContactBadge;
+
+ NewVoicemailViewHolder(View view) {
+ super(view);
+ this.context = view.getContext();
+ primaryTextView = (TextView) view.findViewById(R.id.primary_text);
+ quickContactBadge = view.findViewById(R.id.quick_contact_photo);
+ }
+
+ void bind(Cursor cursor) {
+ VoicemailEntry voicemailEntry = VoicemailCursorLoader.toVoicemailEntry(cursor);
+ primaryTextView.setText(VoicemailEntryText.buildPrimaryVoicemailText(context, voicemailEntry));
+ setPhoto(voicemailEntry);
+ }
+
+ // TODO(uabdullah): Consider/Implement TYPE (e.g Spam, TYPE_VOICEMAIL)
+ private void setPhoto(VoicemailEntry voicemailEntry) {
+ ContactPhotoManager.getInstance(context)
+ .loadDialerThumbnailOrPhoto(
+ quickContactBadge,
+ voicemailEntry.lookupUri() == null ? null : Uri.parse(voicemailEntry.lookupUri()),
+ voicemailEntry.photoId(),
+ voicemailEntry.photoUri() == null ? null : Uri.parse(voicemailEntry.photoUri()),
+ voicemailEntry.name(),
+ LetterTileDrawable.TYPE_DEFAULT);
+ }
+}
diff --git a/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java b/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java
new file mode 100644
index 000000000..5a4176542
--- /dev/null
+++ b/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 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.dialer.voicemail.listui;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.provider.CallLog.Calls;
+import android.support.v4.content.CursorLoader;
+import com.android.dialer.DialerPhoneNumber;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
+import com.android.dialer.voicemail.model.VoicemailEntry;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+/** CursorLoader for the annotated call log (voicemails only). */
+final class VoicemailCursorLoader extends CursorLoader {
+
+ // When adding columns be sure to update {@link #VoicemailCursorLoader.toVoicemailEntry}.
+ public static final String[] VOICEMAIL_COLUMNS =
+ new String[] {
+ AnnotatedCallLog._ID,
+ AnnotatedCallLog.TIMESTAMP,
+ AnnotatedCallLog.NAME,
+ AnnotatedCallLog.NUMBER,
+ AnnotatedCallLog.FORMATTED_NUMBER,
+ AnnotatedCallLog.PHOTO_URI,
+ AnnotatedCallLog.PHOTO_ID,
+ AnnotatedCallLog.LOOKUP_URI,
+ AnnotatedCallLog.GEOCODED_LOCATION,
+ AnnotatedCallLog.CALL_TYPE
+ };
+
+ // Indexes for VOICEMAIL_COLUMNS
+ private static final int ID = 0;
+ private static final int TIMESTAMP = 1;
+ private static final int NAME = 2;
+ private static final int NUMBER = 3;
+ private static final int FORMATTED_NUMBER = 4;
+ private static final int PHOTO_URI = 5;
+ private static final int PHOTO_ID = 6;
+ private static final int LOOKUP_URI = 7;
+ private static final int GEOCODED_LOCATION = 8;
+ private static final int CALL_TYPE = 9;
+
+ // TODO(zachh): Optimize indexes
+ VoicemailCursorLoader(Context context) {
+ super(
+ context,
+ AnnotatedCallLog.CONTENT_URI,
+ VOICEMAIL_COLUMNS,
+ AnnotatedCallLog.CALL_TYPE + " = ?",
+ new String[] {Integer.toString(Calls.VOICEMAIL_TYPE)},
+ AnnotatedCallLog.TIMESTAMP + " DESC");
+ }
+
+ /** Creates a new {@link VoicemailEntry} from the provided cursor using the current position. */
+ static VoicemailEntry toVoicemailEntry(Cursor cursor) {
+ DialerPhoneNumber number;
+ try {
+ number = DialerPhoneNumber.parseFrom(cursor.getBlob(NUMBER));
+ } catch (InvalidProtocolBufferException e) {
+ throw new IllegalStateException("Couldn't parse DialerPhoneNumber bytes");
+ }
+
+ return VoicemailEntry.builder()
+ .setId(cursor.getInt(ID))
+ .setTimestamp(cursor.getLong(TIMESTAMP))
+ .setName(cursor.getString(NAME))
+ .setNumber(number)
+ .setFormattedNumber(cursor.getString(FORMATTED_NUMBER))
+ .setPhotoUri(cursor.getString(PHOTO_URI))
+ .setPhotoId(cursor.getLong(PHOTO_ID))
+ .setLookupUri(cursor.getString(LOOKUP_URI))
+ .setGeocodedLocation(cursor.getString(GEOCODED_LOCATION))
+ .setCallType(cursor.getInt(CALL_TYPE))
+ .build();
+ }
+}
diff --git a/java/com/android/dialer/voicemail/listui/VoicemailEntryText.java b/java/com/android/dialer/voicemail/listui/VoicemailEntryText.java
new file mode 100644
index 000000000..cf2fef253
--- /dev/null
+++ b/java/com/android/dialer/voicemail/listui/VoicemailEntryText.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 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.dialer.voicemail.listui;
+
+import android.content.Context;
+import android.text.TextUtils;
+import com.android.dialer.voicemail.model.VoicemailEntry;
+
+/**
+ * Computes the primary text for voicemail entries.
+ *
+ * <p>These text values are shown in the voicemail tab.
+ */
+public class VoicemailEntryText {
+
+ public static String buildPrimaryVoicemailText(Context context, VoicemailEntry data) {
+ StringBuilder primaryText = new StringBuilder();
+ if (!TextUtils.isEmpty(data.name())) {
+ primaryText.append(data.name());
+ } else if (!TextUtils.isEmpty(data.formattedNumber())) {
+ primaryText.append(data.formattedNumber());
+ } else {
+ // TODO(uabdullah): Handle CallLog.Calls.PRESENTATION_*, including Verizon restricted numbers.
+ primaryText.append(context.getText(R.string.voicemail_entry_unknown));
+ }
+ return primaryText.toString();
+ }
+}
diff --git a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_entry.xml b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_entry.xml
index 01c0ee12e..82ccf88d2 100644
--- a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_entry.xml
+++ b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_entry.xml
@@ -31,7 +31,6 @@
android:layout_height="@dimen/call_log_entry_photo_size"
android:layout_centerVertical="true"
android:padding="@dimen/call_log_entry_photo_padding"
- android:background="@color/dialer_secondary_color"
android:focusable="true"/>
<LinearLayout
@@ -42,6 +41,7 @@
android:layout_toStartOf="@+id/menu_button"
android:orientation="vertical">
+ <!--TODO(uabdullah): Resolve text clipping on top of primary text -->
<TextView
android:id="@+id/primary_text"
style="@style/PrimaryText"
diff --git a/java/com/android/dialer/voicemail/listui/res/values/strings.xml b/java/com/android/dialer/voicemail/listui/res/values/strings.xml
new file mode 100644
index 000000000..39c368a5a
--- /dev/null
+++ b/java/com/android/dialer/voicemail/listui/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 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
+ -->
+<resources>
+ <!-- String used to display voicemails from unknown numbers in the voicemail tab. [CHAR LIMIT=30] -->
+ <string name="voicemail_entry_unknown">Unknown</string>
+</resources> \ No newline at end of file
diff --git a/java/com/android/dialer/voicemail/model/VoicemailEntry.java b/java/com/android/dialer/voicemail/model/VoicemailEntry.java
new file mode 100644
index 000000000..00e1757dc
--- /dev/null
+++ b/java/com/android/dialer/voicemail/model/VoicemailEntry.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 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.dialer.voicemail.model;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import com.android.dialer.DialerPhoneNumber;
+import com.google.auto.value.AutoValue;
+
+/** Data class containing the contents of a voicemail entry from the AnnotatedCallLog. */
+@AutoValue
+public abstract class VoicemailEntry {
+
+ public static Builder builder() {
+ return new AutoValue_VoicemailEntry.Builder()
+ .setId(0)
+ .setTimestamp(0)
+ .setNumber(DialerPhoneNumber.getDefaultInstance())
+ .setPhotoId(0)
+ .setCallType(0);
+ }
+
+ public abstract int id();
+
+ public abstract long timestamp();
+
+ @NonNull
+ public abstract DialerPhoneNumber number();
+
+ @Nullable
+ public abstract String name();
+
+ @Nullable
+ public abstract String formattedNumber();
+
+ @Nullable
+ public abstract String photoUri();
+
+ public abstract long photoId();
+
+ @Nullable
+ public abstract String lookupUri();
+
+ @Nullable
+ public abstract String geocodedLocation();
+
+ public abstract int callType();
+
+ /** Builder for {@link VoicemailEntry}. */
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder setId(int id);
+
+ public abstract Builder setTimestamp(long timestamp);
+
+ public abstract Builder setNumber(@NonNull DialerPhoneNumber number);
+
+ public abstract Builder setName(@Nullable String name);
+
+ public abstract Builder setFormattedNumber(@Nullable String formattedNumber);
+
+ public abstract Builder setPhotoUri(@Nullable String photoUri);
+
+ public abstract Builder setPhotoId(long photoId);
+
+ public abstract Builder setLookupUri(@Nullable String lookupUri);
+
+ public abstract Builder setGeocodedLocation(@Nullable String geocodedLocation);
+
+ public abstract Builder setCallType(int callType);
+
+ public abstract VoicemailEntry build();
+ }
+}
diff --git a/java/com/android/incallui/CallerInfo.java b/java/com/android/incallui/CallerInfo.java
index cc1a60a5b..809ed594c 100644
--- a/java/com/android/incallui/CallerInfo.java
+++ b/java/com/android/incallui/CallerInfo.java
@@ -192,141 +192,145 @@ public class CallerInfo {
*
* @param context the context used to retrieve string constants
* @param contactRef the URI to attach to this CallerInfo object
- * @param cursor the first object in the cursor is used to build the CallerInfo object.
+ * @param cursor the first matching object in the cursor is used to build the CallerInfo object.
* @return the CallerInfo which contains the caller id for the given number. The returned
* CallerInfo is null if no number is supplied.
*/
public static CallerInfo getCallerInfo(Context context, Uri contactRef, Cursor cursor) {
CallerInfo info = new CallerInfo();
- info.photoResource = 0;
- info.phoneLabel = null;
- info.numberType = 0;
- info.numberLabel = null;
info.cachedPhoto = null;
- info.isCachedPhotoCurrent = false;
info.contactExists = false;
+ info.contactRefUri = contactRef;
+ info.isCachedPhotoCurrent = false;
+ info.name = null;
+ info.needUpdate = false;
+ info.numberLabel = null;
+ info.numberType = 0;
+ info.phoneLabel = null;
+ info.photoResource = 0;
info.userType = ContactsUtils.USER_TYPE_CURRENT;
Log.v(TAG, "getCallerInfo() based on cursor...");
- if (cursor != null) {
- if (cursor.moveToFirst()) {
- // TODO: photo_id is always available but not taken
- // care of here. Maybe we should store it in the
- // CallerInfo object as well.
-
- long contactId = 0L;
- int columnIndex;
-
- // Look for the name
- columnIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME);
- if (columnIndex != -1) {
- info.name = cursor.getString(columnIndex);
- }
-
- // Look for the number
- columnIndex = cursor.getColumnIndex(PhoneLookup.NUMBER);
- if (columnIndex != -1) {
- info.phoneNumber = cursor.getString(columnIndex);
- }
-
- // Look for the normalized number
- columnIndex = cursor.getColumnIndex(PhoneLookup.NORMALIZED_NUMBER);
- if (columnIndex != -1) {
- info.normalizedNumber = cursor.getString(columnIndex);
- }
-
- // Look for the label/type combo
- columnIndex = cursor.getColumnIndex(PhoneLookup.LABEL);
- if (columnIndex != -1) {
- int typeColumnIndex = cursor.getColumnIndex(PhoneLookup.TYPE);
- if (typeColumnIndex != -1) {
- info.numberType = cursor.getInt(typeColumnIndex);
- info.numberLabel = cursor.getString(columnIndex);
- info.phoneLabel =
- Phone.getTypeLabel(context.getResources(), info.numberType, info.numberLabel)
- .toString();
- }
- }
-
- // cache the lookup key for later use to create lookup URIs
- columnIndex = cursor.getColumnIndex(PhoneLookup.LOOKUP_KEY);
- if (columnIndex != -1) {
- info.lookupKeyOrNull = cursor.getString(columnIndex);
- }
-
- // Look for the person_id.
- columnIndex = getColumnIndexForPersonId(contactRef, cursor);
- if (columnIndex != -1) {
- contactId = cursor.getLong(columnIndex);
- // QuickContacts in M doesn't support enterprise contact id
- if (contactId != 0
- && (VERSION.SDK_INT >= VERSION_CODES.N
- || !Contacts.isEnterpriseContactId(contactId))) {
- info.contactIdOrZero = contactId;
- Log.v(TAG, "==> got info.contactIdOrZero: " + info.contactIdOrZero);
- }
- } else {
- // No valid columnIndex, so we can't look up person_id.
- Log.v(TAG, "Couldn't find contactId column for " + contactRef);
- // Watch out: this means that anything that depends on
- // person_id will be broken (like contact photo lookups in
- // the in-call UI, for example.)
- }
-
- // Display photo URI.
- columnIndex = cursor.getColumnIndex(PhoneLookup.PHOTO_URI);
- if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) {
- info.contactDisplayPhotoUri = Uri.parse(cursor.getString(columnIndex));
- } else {
- info.contactDisplayPhotoUri = null;
- }
-
- // look for the custom ringtone, create from the string stored
- // in the database.
- columnIndex = cursor.getColumnIndex(PhoneLookup.CUSTOM_RINGTONE);
- if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) {
- if (TextUtils.isEmpty(cursor.getString(columnIndex))) {
- // make it consistent with frameworks/base/.../CallerInfo.java
- info.contactRingtoneUri = Uri.EMPTY;
- } else {
- info.contactRingtoneUri = Uri.parse(cursor.getString(columnIndex));
- }
- } else {
- info.contactRingtoneUri = null;
- }
-
- // look for the send to voicemail flag, set it to true only
- // under certain circumstances.
- columnIndex = cursor.getColumnIndex(PhoneLookup.SEND_TO_VOICEMAIL);
- info.shouldSendToVoicemail = (columnIndex != -1) && ((cursor.getInt(columnIndex)) == 1);
- info.contactExists = true;
-
- // Determine userType by directoryId and contactId
- final String directory =
- contactRef == null
- ? null
- : contactRef.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
- Long directoryId = null;
- if (directory != null) {
- try {
- directoryId = Long.parseLong(directory);
- } catch (NumberFormatException e) {
- // do nothing
- }
- }
- info.userType = ContactsUtils.determineUserType(directoryId, contactId);
-
- info.nameAlternative =
- ContactInfoHelper.lookUpDisplayNameAlternative(
- context, info.lookupKeyOrNull, info.userType, directoryId);
+ if (cursor == null || !cursor.moveToFirst()) {
+ return info;
+ }
+
+ // TODO: photo_id is always available but not taken
+ // care of here. Maybe we should store it in the
+ // CallerInfo object as well.
+
+ long contactId = 0L;
+ int columnIndex;
+
+ // If the cursor has the phone number column, find the one that matches the lookup number in the
+ // URI.
+ columnIndex = cursor.getColumnIndex(PhoneLookup.NUMBER);
+ if (columnIndex != -1 && contactRef != null) {
+ cursor = PhoneNumberHelper.getCursorMatchForContactLookupUri(cursor, columnIndex, contactRef);
+ if (cursor != null) {
+ info.phoneNumber = cursor.getString(columnIndex);
+ } else {
+ return info;
}
- cursor.close();
}
- info.needUpdate = false;
- info.name = normalize(info.name);
- info.contactRefUri = contactRef;
+ // Look for the name
+ columnIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME);
+ if (columnIndex != -1) {
+ info.name = normalize(cursor.getString(columnIndex));
+ }
+
+ // Look for the normalized number
+ columnIndex = cursor.getColumnIndex(PhoneLookup.NORMALIZED_NUMBER);
+ if (columnIndex != -1) {
+ info.normalizedNumber = cursor.getString(columnIndex);
+ }
+
+ // Look for the label/type combo
+ columnIndex = cursor.getColumnIndex(PhoneLookup.LABEL);
+ if (columnIndex != -1) {
+ int typeColumnIndex = cursor.getColumnIndex(PhoneLookup.TYPE);
+ if (typeColumnIndex != -1) {
+ info.numberType = cursor.getInt(typeColumnIndex);
+ info.numberLabel = cursor.getString(columnIndex);
+ info.phoneLabel =
+ Phone.getTypeLabel(context.getResources(), info.numberType, info.numberLabel)
+ .toString();
+ }
+ }
+
+ // cache the lookup key for later use to create lookup URIs
+ columnIndex = cursor.getColumnIndex(PhoneLookup.LOOKUP_KEY);
+ if (columnIndex != -1) {
+ info.lookupKeyOrNull = cursor.getString(columnIndex);
+ }
+
+ // Look for the person_id.
+ columnIndex = getColumnIndexForPersonId(contactRef, cursor);
+ if (columnIndex != -1) {
+ contactId = cursor.getLong(columnIndex);
+ // QuickContacts in M doesn't support enterprise contact id
+ if (contactId != 0
+ && (VERSION.SDK_INT >= VERSION_CODES.N || !Contacts.isEnterpriseContactId(contactId))) {
+ info.contactIdOrZero = contactId;
+ Log.v(TAG, "==> got info.contactIdOrZero: " + info.contactIdOrZero);
+ }
+ } else {
+ // No valid columnIndex, so we can't look up person_id.
+ Log.v(TAG, "Couldn't find contactId column for " + contactRef);
+ // Watch out: this means that anything that depends on
+ // person_id will be broken (like contact photo lookups in
+ // the in-call UI, for example.)
+ }
+
+ // Display photo URI.
+ columnIndex = cursor.getColumnIndex(PhoneLookup.PHOTO_URI);
+ if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) {
+ info.contactDisplayPhotoUri = Uri.parse(cursor.getString(columnIndex));
+ } else {
+ info.contactDisplayPhotoUri = null;
+ }
+
+ // look for the custom ringtone, create from the string stored
+ // in the database.
+ columnIndex = cursor.getColumnIndex(PhoneLookup.CUSTOM_RINGTONE);
+ if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) {
+ if (TextUtils.isEmpty(cursor.getString(columnIndex))) {
+ // make it consistent with frameworks/base/.../CallerInfo.java
+ info.contactRingtoneUri = Uri.EMPTY;
+ } else {
+ info.contactRingtoneUri = Uri.parse(cursor.getString(columnIndex));
+ }
+ } else {
+ info.contactRingtoneUri = null;
+ }
+
+ // look for the send to voicemail flag, set it to true only
+ // under certain circumstances.
+ columnIndex = cursor.getColumnIndex(PhoneLookup.SEND_TO_VOICEMAIL);
+ info.shouldSendToVoicemail = (columnIndex != -1) && ((cursor.getInt(columnIndex)) == 1);
+ info.contactExists = true;
+
+ // Determine userType by directoryId and contactId
+ final String directory =
+ contactRef == null
+ ? null
+ : contactRef.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
+ Long directoryId = null;
+ if (directory != null) {
+ try {
+ directoryId = Long.parseLong(directory);
+ } catch (NumberFormatException e) {
+ // do nothing
+ }
+ }
+ info.userType = ContactsUtils.determineUserType(directoryId, contactId);
+
+ info.nameAlternative =
+ ContactInfoHelper.lookUpDisplayNameAlternative(
+ context, info.lookupKeyOrNull, info.userType, directoryId);
+ cursor.close();
return info;
}