From 30b973450f12cf0b694c7bf06018830a698ce40a Mon Sep 17 00:00:00 2001 From: Eric Erfanian Date: Tue, 17 Oct 2017 15:43:46 -0700 Subject: Add temporary assisted dialing setting to Dialer. Bug: 63994464 Test: integration test PiperOrigin-RevId: 172499750 Change-Id: I7a7c23b403f649c1bbec0bb068e1285e02fddd22 --- .../app/settings/DialerSettingsActivity.java | 18 +++++++++++++ .../dialer/assisteddialing/ConcreteCreator.java | 25 +++++++++++++++-- .../dialer/assisteddialing/ui/AndroidManifest.xml | 22 +++++++++++++++ .../ui/AssistedDialingSettingFragment.java | 31 ++++++++++++++++++++++ .../assisteddialing/ui/res/values/string.xml | 27 +++++++++++++++++++ .../ui/res/xml/assisted_dialing_setting.xml | 26 ++++++++++++++++++ 6 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml create mode 100644 java/com/android/dialer/assisteddialing/ui/AssistedDialingSettingFragment.java create mode 100644 java/com/android/dialer/assisteddialing/ui/res/values/string.xml create mode 100644 java/com/android/dialer/assisteddialing/ui/res/xml/assisted_dialing_setting.xml (limited to 'java') 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 @@ + + + + + + \ 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 @@ + + + + + + Assisted dialing + + + Automatically correct the phone number prefix when traveling and calling international numbers + + + assisted_dialing_setting_toggle_key + \ 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 @@ + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 68cc4733e1619e1b6b7f6d5f52ab057cc48525bb Mon Sep 17 00:00:00 2001 From: uabdullah Date: Tue, 17 Oct 2017 13:24:05 -0700 Subject: Display Voicemail Contact Name and Photo in Voicemail Fragment. This CL lays the foundation of querying the annotated call log, retrieving only the voicemail entries and some of the voicemail information in the Voicemail tab. This CL only displays the name/number as well as the corresponding photo of the voicemails present on the device. WANT_LGTM=zachh SCREENSHOT: http://screen/YYBG8T0Ma0J Bug: 33006245, 64882313 Test: Unit tests and manual verification. PiperOrigin-RevId: 172504512 Change-Id: Ie7187b021abf42d1a4522458a1ab28537a7c222c --- .../database/AnnotatedCallLogDatabaseHelper.java | 9 +++ .../voicemail/listui/NewVoicemailAdapter.java | 54 +++++++++++++ .../listui/NewVoicemailCallLogAdapter.java | 55 ------------- .../listui/NewVoicemailCallLogViewHolder.java | 50 ------------ .../voicemail/listui/NewVoicemailFragment.java | 53 ++++++------- .../voicemail/listui/NewVoicemailViewHolder.java | 60 ++++++++++++++ .../voicemail/listui/VoicemailCursorLoader.java | 91 ++++++++++++++++++++++ .../voicemail/listui/VoicemailEntryText.java | 42 ++++++++++ .../res/layout/new_voicemail_call_log_entry.xml | 2 +- .../dialer/voicemail/listui/res/values/strings.xml | 20 +++++ .../dialer/voicemail/model/VoicemailEntry.java | 89 +++++++++++++++++++++ 11 files changed, 393 insertions(+), 132 deletions(-) create mode 100644 java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java delete mode 100644 java/com/android/dialer/voicemail/listui/NewVoicemailCallLogAdapter.java delete mode 100644 java/com/android/dialer/voicemail/listui/NewVoicemailCallLogViewHolder.java create mode 100644 java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java create mode 100644 java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java create mode 100644 java/com/android/dialer/voicemail/listui/VoicemailEntryText.java create mode 100644 java/com/android/dialer/voicemail/listui/res/values/strings.xml create mode 100644 java/com/android/dialer/voicemail/model/VoicemailEntry.java (limited to 'java') 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/voicemail/listui/NewVoicemailAdapter.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java new file mode 100644 index 000000000..71178ceba --- /dev/null +++ b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java @@ -0,0 +1,54 @@ +/* + * 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.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; + +/** {@link RecyclerView.Adapter} for the new voicemail call log fragment. */ +final class NewVoicemailAdapter extends RecyclerView.Adapter { + + private final Cursor cursor; + + /** @param cursor whose projection is {@link VoicemailCursorLoader.VOICEMAIL_COLUMNS} */ + NewVoicemailAdapter(Cursor cursor) { + this.cursor = cursor; + } + + @Override + public NewVoicemailViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext()); + View view = inflater.inflate(R.layout.new_voicemail_call_log_entry, viewGroup, false); + NewVoicemailViewHolder newVoicemailViewHolder = new NewVoicemailViewHolder(view); + return newVoicemailViewHolder; + } + + @Override + public void onBindViewHolder(NewVoicemailViewHolder viewHolder, int position) { + LogUtil.i("onBindViewHolder", "position" + position); + cursor.moveToPosition(position); + viewHolder.bind(cursor); + } + + @Override + public int getItemCount() { + return cursor.getCount(); + } +} diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailCallLogAdapter.java b/java/com/android/dialer/voicemail/listui/NewVoicemailCallLogAdapter.java deleted file mode 100644 index b40c8630e..000000000 --- a/java/com/android/dialer/voicemail/listui/NewVoicemailCallLogAdapter.java +++ /dev/null @@ -1,55 +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.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 { - - private final List voicemailData; - - NewVoicemailCallLogAdapter(List dataSet) { - voicemailData = dataSet; - } - - @Override - public NewVoicemailCallLogViewHolder 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; - } - - @Override - public void onBindViewHolder(NewVoicemailCallLogViewHolder viewHolder, int position) { - LogUtil.i("onBindViewHolder", "position" + position); - viewHolder.bind(voicemailData.get(position)); - } - - @Override - public int getItemCount() { - return voicemailData.size(); - } -} 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 { + + 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 = 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 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 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 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. + * + *

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"/> + + + + + Unknown + \ 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(); + } +} -- cgit v1.2.3 From 6f78d935ff64f178e9fe8891082c18578d4e4b74 Mon Sep 17 00:00:00 2001 From: linyuh Date: Tue, 17 Oct 2017 13:31:27 -0700 Subject: Stop showing partially matched numbers that are not global phone numbers. When determining whether two phone numbers are identical enough for caller ID purposes, the Contacts Provider 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. 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. If the cursor points to a global phone number (i.e., a number that can be accepted by PhoneNumberUtils#isGlobalPhoneNumber(String)) and the lookup number in the URI is a PARTIAL match, the cursor is a match. If the cursor points to a number that is not a global phone number, the cursor is a match iff the lookup number in the URI is an EXACT match. There is no matched cursor in all other circumstances. UI demo: Suppose the user has a contact named "Service1" with number "#123". Before: Incall UI after the user dials "123": https://photos.app.goo.gl/xFWCD4qy2VR3YEuJ2 Call log UI after the call ends: https://photos.app.goo.gl/FT28GdTBy1dtANtI2 After: Incall UI after the user dials "123": https://photos.app.goo.gl/Io3BisQmsyfnvitV2 Call log UI after the call ends: https://photos.app.goo.gl/6GgRrmx75yUTga3B3 Bug: 30225112 Test: PhoneNumberHelperTest PiperOrigin-RevId: 172505648 Change-Id: Ida554313455ff9ce40432897681f89f58d64af04 --- .../dialer/phonenumbercache/ContactInfoHelper.java | 36 +-- .../dialer/phonenumberutil/PhoneNumberHelper.java | 75 +++++++ java/com/android/incallui/CallerInfo.java | 246 +++++++++++---------- 3 files changed, 218 insertions(+), 139 deletions(-) (limited to 'java') 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; @@ -46,6 +49,78 @@ public class PhoneNumberHelper { && !isLegacyUnknownNumbers(number); } + /** + * Find the cursor pointing to a number that matches the number in a contact lookup URI. + * + *

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. + * + *

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. + * + *

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. + * + *

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. + * + *

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/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; } -- cgit v1.2.3