From ea7890cd5e829ed3f0b5f726561c569690af2030 Mon Sep 17 00:00:00 2001 From: Eric Erfanian Date: Mon, 19 Jun 2017 12:40:59 -0700 Subject: Update AOSP Dialer source from internal google3 repository at cl/159428781. Test: make, treehugger This CL updates the AOSP Dialer source with all the changes that have gone into the private google3 repository. This includes all the changes from cl/158012278 (6/05/2017) to cl/159428781 (6/19/2017). This goal of these drops is to keep the AOSP source in sync with the internal google3 repository. Currently these sync are done by hand with very minor modifications to the internal source code. See the Android.mk file for list of modifications. Our current goal is to do frequent drops (daily if possible) and eventually switched to an automated process. Merged-In: Ie60a84b3936efd0ea3d95d7c86bf96d2b1663030 Change-Id: If1fa394df2609f0d38b4f794c83f4db3f1006484 --- java/com/android/dialer/app/Bindings.java | 28 -- java/com/android/dialer/app/DialtactsActivity.java | 94 +++-- .../dialer/app/bindings/DialerBindings.java | 25 -- .../dialer/app/bindings/DialerBindingsFactory.java | 26 -- .../dialer/app/bindings/DialerBindingsStub.java | 48 --- .../dialer/app/calllog/CallLogActivity.java | 34 +- .../android/dialer/app/calllog/CallLogAdapter.java | 160 ++++++-- .../dialer/app/calllog/CallLogAsyncTaskUtil.java | 6 +- .../dialer/app/calllog/CallLogFragment.java | 98 ++++- .../app/calllog/CallLogListItemViewHolder.java | 145 ++++++- .../calllog/CallLogNotificationsQueryHelper.java | 92 +++-- .../app/calllog/CallLogNotificationsService.java | 115 ++++-- .../dialer/app/calllog/CallLogReceiver.java | 4 +- .../dialer/app/calllog/ClearCallLogDialog.java | 2 +- .../app/calllog/DefaultVoicemailNotifier.java | 451 --------------------- .../app/calllog/DialerQuickContactBadge.java | 63 +++ .../android/dialer/app/calllog/IntentProvider.java | 5 +- .../app/calllog/LegacyVoicemailNotifier.java | 156 +++++++ .../dialer/app/calllog/MissedCallNotifier.java | 116 ++++-- .../dialer/app/calllog/PhoneAccountHandles.java | 62 --- .../app/calllog/VisualVoicemailNotifier.java | 291 +++++++++++++ .../app/calllog/VisualVoicemailUpdateTask.java | 168 ++++++++ .../dialer/app/calllog/VoicemailQueryHandler.java | 44 +- .../calllogcache/CallLogCacheLollipopMr1.java | 30 +- .../dialer/app/contactinfo/ContactInfoCache.java | 2 +- .../dialer/app/dialpad/DialpadFragment.java | 9 + .../app/legacybindings/DialerLegacyBindings.java | 1 + .../legacybindings/DialerLegacyBindingsStub.java | 2 + .../dialer/app/list/AllContactsFragment.java | 12 +- .../app/list/DialerPhoneNumberListAdapter.java | 13 +- .../dialer/app/list/DialtactsPagerAdapter.java | 4 +- .../com/android/dialer/app/list/ListsFragment.java | 65 +-- .../dialer/app/list/OldSpeedDialFragment.java | 11 +- .../dialer/app/list/PhoneFavoriteTileView.java | 2 + .../dialer/app/list/PhoneFavoritesTileAdapter.java | 6 +- .../dialer/app/list/RegularSearchFragment.java | 13 +- .../android/dialer/app/list/SearchFragment.java | 23 +- .../dialer/app/list/SmartDialSearchFragment.java | 18 +- .../app/manifests/activities/AndroidManifest.xml | 2 + .../dialer/app/res/layout/call_log_fragment.xml | 30 ++ .../dialer/app/res/layout/call_log_list_item.xml | 2 +- .../dialer/app/res/layout/lists_fragment.xml | 39 -- .../dialer/app/res/menu/dialtacts_options.xml | 3 + .../android/dialer/app/res/values-af/strings.xml | 11 +- .../android/dialer/app/res/values-am/strings.xml | 11 +- .../android/dialer/app/res/values-ar/strings.xml | 15 +- .../android/dialer/app/res/values-az/strings.xml | 11 +- .../dialer/app/res/values-b+sr+Latn/strings.xml | 12 +- .../android/dialer/app/res/values-be/strings.xml | 13 +- .../android/dialer/app/res/values-bg/strings.xml | 11 +- .../android/dialer/app/res/values-bn/strings.xml | 11 +- .../android/dialer/app/res/values-bs/strings.xml | 12 +- .../android/dialer/app/res/values-ca/strings.xml | 15 +- .../android/dialer/app/res/values-cs/strings.xml | 13 +- .../android/dialer/app/res/values-da/strings.xml | 13 +- .../android/dialer/app/res/values-de/strings.xml | 11 +- .../android/dialer/app/res/values-el/strings.xml | 11 +- .../dialer/app/res/values-en-rAU/strings.xml | 11 +- .../dialer/app/res/values-en-rGB/strings.xml | 11 +- .../dialer/app/res/values-en-rIN/strings.xml | 11 +- .../dialer/app/res/values-es-rUS/strings.xml | 11 +- .../android/dialer/app/res/values-es/strings.xml | 11 +- .../android/dialer/app/res/values-et/strings.xml | 11 +- .../android/dialer/app/res/values-eu/strings.xml | 11 +- .../android/dialer/app/res/values-fa/strings.xml | 11 +- .../android/dialer/app/res/values-fi/strings.xml | 11 +- .../dialer/app/res/values-fr-rCA/strings.xml | 11 +- .../android/dialer/app/res/values-fr/strings.xml | 11 +- .../android/dialer/app/res/values-gl/strings.xml | 11 +- .../android/dialer/app/res/values-gu/strings.xml | 11 +- .../android/dialer/app/res/values-hi/strings.xml | 11 +- .../android/dialer/app/res/values-hr/strings.xml | 12 +- .../android/dialer/app/res/values-hu/strings.xml | 11 +- .../android/dialer/app/res/values-hy/strings.xml | 13 +- .../android/dialer/app/res/values-in/strings.xml | 11 +- .../android/dialer/app/res/values-is/strings.xml | 11 +- .../android/dialer/app/res/values-it/strings.xml | 11 +- .../android/dialer/app/res/values-iw/strings.xml | 13 +- .../android/dialer/app/res/values-ja/strings.xml | 11 +- .../android/dialer/app/res/values-ka/strings.xml | 11 +- .../android/dialer/app/res/values-kk/strings.xml | 11 +- .../android/dialer/app/res/values-km/strings.xml | 11 +- .../android/dialer/app/res/values-kn/strings.xml | 11 +- .../android/dialer/app/res/values-ko/strings.xml | 11 +- .../android/dialer/app/res/values-ky/strings.xml | 11 +- .../android/dialer/app/res/values-lo/strings.xml | 11 +- .../android/dialer/app/res/values-lt/strings.xml | 13 +- .../android/dialer/app/res/values-lv/strings.xml | 12 +- .../android/dialer/app/res/values-mk/strings.xml | 11 +- .../android/dialer/app/res/values-ml/strings.xml | 11 +- .../android/dialer/app/res/values-mn/strings.xml | 11 +- .../android/dialer/app/res/values-mr/strings.xml | 11 +- .../android/dialer/app/res/values-ms/strings.xml | 11 +- .../android/dialer/app/res/values-my/strings.xml | 11 +- .../android/dialer/app/res/values-nb/strings.xml | 11 +- .../android/dialer/app/res/values-ne/strings.xml | 11 +- .../android/dialer/app/res/values-nl/strings.xml | 11 +- .../android/dialer/app/res/values-no/strings.xml | 11 +- .../android/dialer/app/res/values-pa/strings.xml | 11 +- .../android/dialer/app/res/values-pl/strings.xml | 13 +- .../dialer/app/res/values-pt-rBR/strings.xml | 11 +- .../dialer/app/res/values-pt-rPT/strings.xml | 11 +- .../android/dialer/app/res/values-pt/strings.xml | 11 +- .../android/dialer/app/res/values-ro/strings.xml | 12 +- .../android/dialer/app/res/values-ru/strings.xml | 13 +- .../android/dialer/app/res/values-si/strings.xml | 11 +- .../android/dialer/app/res/values-sk/strings.xml | 13 +- .../android/dialer/app/res/values-sl/strings.xml | 13 +- .../android/dialer/app/res/values-sq/strings.xml | 11 +- .../android/dialer/app/res/values-sr/strings.xml | 12 +- .../android/dialer/app/res/values-sv/strings.xml | 11 +- .../android/dialer/app/res/values-sw/strings.xml | 11 +- .../android/dialer/app/res/values-ta/strings.xml | 11 +- .../android/dialer/app/res/values-te/strings.xml | 11 +- .../android/dialer/app/res/values-th/strings.xml | 11 +- .../android/dialer/app/res/values-tl/strings.xml | 11 +- .../android/dialer/app/res/values-tr/strings.xml | 11 +- .../android/dialer/app/res/values-uk/strings.xml | 13 +- .../android/dialer/app/res/values-ur/strings.xml | 11 +- .../android/dialer/app/res/values-uz/strings.xml | 11 +- .../android/dialer/app/res/values-vi/strings.xml | 11 +- .../dialer/app/res/values-zh-rCN/strings.xml | 11 +- .../dialer/app/res/values-zh-rHK/strings.xml | 11 +- .../dialer/app/res/values-zh-rTW/strings.xml | 11 +- .../android/dialer/app/res/values-zu/strings.xml | 11 +- java/com/android/dialer/app/res/values/dimens.xml | 5 + java/com/android/dialer/app/res/values/strings.xml | 63 +-- java/com/android/dialer/app/res/values/styles.xml | 7 +- .../LegacyVoicemailNotificationReceiver.java | 22 +- .../app/voicemail/VoicemailPlaybackPresenter.java | 5 +- .../error/OmtpVoicemailMessageCreator.java | 6 + .../error/VoicemailStatusCorruptionHandler.java | 2 +- .../error/VoicemailTosMessageCreator.java | 301 ++++++++++++++ .../error/Vvm3VoicemailMessageCreator.java | 150 +------ .../error/res/layout/voicemail_tos_fragment.xml | 16 +- .../app/voicemail/error/res/values-af/strings.xml | 16 +- .../app/voicemail/error/res/values-am/strings.xml | 16 +- .../app/voicemail/error/res/values-ar/strings.xml | 16 +- .../app/voicemail/error/res/values-az/strings.xml | 16 +- .../error/res/values-b+sr+Latn/strings.xml | 16 +- .../app/voicemail/error/res/values-be/strings.xml | 16 +- .../app/voicemail/error/res/values-bg/strings.xml | 16 +- .../app/voicemail/error/res/values-bn/strings.xml | 16 +- .../app/voicemail/error/res/values-bs/strings.xml | 16 +- .../app/voicemail/error/res/values-ca/strings.xml | 16 +- .../app/voicemail/error/res/values-cs/strings.xml | 16 +- .../app/voicemail/error/res/values-da/strings.xml | 16 +- .../app/voicemail/error/res/values-de/strings.xml | 16 +- .../app/voicemail/error/res/values-el/strings.xml | 16 +- .../voicemail/error/res/values-en-rAU/strings.xml | 16 +- .../voicemail/error/res/values-en-rGB/strings.xml | 16 +- .../voicemail/error/res/values-en-rIN/strings.xml | 16 +- .../voicemail/error/res/values-es-rUS/strings.xml | 16 +- .../app/voicemail/error/res/values-es/strings.xml | 16 +- .../app/voicemail/error/res/values-et/strings.xml | 16 +- .../app/voicemail/error/res/values-eu/strings.xml | 16 +- .../app/voicemail/error/res/values-fa/strings.xml | 16 +- .../app/voicemail/error/res/values-fi/strings.xml | 16 +- .../voicemail/error/res/values-fr-rCA/strings.xml | 16 +- .../app/voicemail/error/res/values-fr/strings.xml | 16 +- .../app/voicemail/error/res/values-gl/strings.xml | 16 +- .../app/voicemail/error/res/values-gu/strings.xml | 16 +- .../app/voicemail/error/res/values-hi/strings.xml | 16 +- .../app/voicemail/error/res/values-hr/strings.xml | 16 +- .../app/voicemail/error/res/values-hu/strings.xml | 16 +- .../app/voicemail/error/res/values-hy/strings.xml | 16 +- .../app/voicemail/error/res/values-in/strings.xml | 16 +- .../app/voicemail/error/res/values-is/strings.xml | 16 +- .../app/voicemail/error/res/values-it/strings.xml | 16 +- .../app/voicemail/error/res/values-iw/strings.xml | 16 +- .../app/voicemail/error/res/values-ja/strings.xml | 16 +- .../app/voicemail/error/res/values-ka/strings.xml | 16 +- .../app/voicemail/error/res/values-kk/strings.xml | 16 +- .../app/voicemail/error/res/values-km/strings.xml | 16 +- .../app/voicemail/error/res/values-kn/strings.xml | 16 +- .../app/voicemail/error/res/values-ko/strings.xml | 16 +- .../app/voicemail/error/res/values-ky/strings.xml | 16 +- .../app/voicemail/error/res/values-lo/strings.xml | 16 +- .../app/voicemail/error/res/values-lt/strings.xml | 16 +- .../app/voicemail/error/res/values-lv/strings.xml | 16 +- .../app/voicemail/error/res/values-mk/strings.xml | 16 +- .../app/voicemail/error/res/values-ml/strings.xml | 16 +- .../app/voicemail/error/res/values-mn/strings.xml | 16 +- .../app/voicemail/error/res/values-mr/strings.xml | 16 +- .../app/voicemail/error/res/values-ms/strings.xml | 16 +- .../app/voicemail/error/res/values-my/strings.xml | 16 +- .../app/voicemail/error/res/values-nb/strings.xml | 16 +- .../app/voicemail/error/res/values-ne/strings.xml | 16 +- .../app/voicemail/error/res/values-nl/strings.xml | 16 +- .../app/voicemail/error/res/values-no/strings.xml | 16 +- .../app/voicemail/error/res/values-pa/strings.xml | 16 +- .../app/voicemail/error/res/values-pl/strings.xml | 16 +- .../voicemail/error/res/values-pt-rBR/strings.xml | 16 +- .../voicemail/error/res/values-pt-rPT/strings.xml | 16 +- .../app/voicemail/error/res/values-pt/strings.xml | 16 +- .../app/voicemail/error/res/values-ro/strings.xml | 16 +- .../app/voicemail/error/res/values-ru/strings.xml | 16 +- .../app/voicemail/error/res/values-si/strings.xml | 16 +- .../app/voicemail/error/res/values-sk/strings.xml | 16 +- .../app/voicemail/error/res/values-sl/strings.xml | 16 +- .../app/voicemail/error/res/values-sq/strings.xml | 16 +- .../app/voicemail/error/res/values-sr/strings.xml | 16 +- .../app/voicemail/error/res/values-sv/strings.xml | 16 +- .../app/voicemail/error/res/values-sw/strings.xml | 18 +- .../app/voicemail/error/res/values-ta/strings.xml | 16 +- .../app/voicemail/error/res/values-te/strings.xml | 16 +- .../app/voicemail/error/res/values-th/strings.xml | 16 +- .../app/voicemail/error/res/values-tl/strings.xml | 16 +- .../app/voicemail/error/res/values-tr/strings.xml | 16 +- .../app/voicemail/error/res/values-uk/strings.xml | 16 +- .../app/voicemail/error/res/values-ur/strings.xml | 16 +- .../app/voicemail/error/res/values-uz/strings.xml | 16 +- .../app/voicemail/error/res/values-vi/strings.xml | 16 +- .../voicemail/error/res/values-zh-rCN/strings.xml | 16 +- .../voicemail/error/res/values-zh-rHK/strings.xml | 16 +- .../voicemail/error/res/values-zh-rTW/strings.xml | 16 +- .../app/voicemail/error/res/values-zu/strings.xml | 16 +- .../app/voicemail/error/res/values/strings.xml | 37 +- .../dialer/app/widget/SearchEditTextLayout.java | 2 +- 219 files changed, 3337 insertions(+), 2051 deletions(-) delete mode 100644 java/com/android/dialer/app/bindings/DialerBindings.java delete mode 100644 java/com/android/dialer/app/bindings/DialerBindingsFactory.java delete mode 100644 java/com/android/dialer/app/bindings/DialerBindingsStub.java delete mode 100644 java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java create mode 100644 java/com/android/dialer/app/calllog/DialerQuickContactBadge.java create mode 100644 java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java delete mode 100644 java/com/android/dialer/app/calllog/PhoneAccountHandles.java create mode 100644 java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java create mode 100644 java/com/android/dialer/app/calllog/VisualVoicemailUpdateTask.java create mode 100644 java/com/android/dialer/app/voicemail/error/VoicemailTosMessageCreator.java (limited to 'java/com/android/dialer/app') diff --git a/java/com/android/dialer/app/Bindings.java b/java/com/android/dialer/app/Bindings.java index 2beb40184..c8cf27eb2 100644 --- a/java/com/android/dialer/app/Bindings.java +++ b/java/com/android/dialer/app/Bindings.java @@ -17,9 +17,6 @@ package com.android.dialer.app; import android.content.Context; -import com.android.dialer.app.bindings.DialerBindings; -import com.android.dialer.app.bindings.DialerBindingsFactory; -import com.android.dialer.app.bindings.DialerBindingsStub; import com.android.dialer.app.legacybindings.DialerLegacyBindings; import com.android.dialer.app.legacybindings.DialerLegacyBindingsFactory; import com.android.dialer.app.legacybindings.DialerLegacyBindingsStub; @@ -28,28 +25,10 @@ import java.util.Objects; /** Accessor for the in call UI bindings. */ public class Bindings { - private static DialerBindings instance; private static DialerLegacyBindings legacyInstance; private Bindings() {} - public static DialerBindings get(Context context) { - Objects.requireNonNull(context); - if (instance != null) { - return instance; - } - - Context application = context.getApplicationContext(); - if (application instanceof DialerBindingsFactory) { - instance = ((DialerBindingsFactory) application).newDialerBindings(); - } - - if (instance == null) { - instance = new DialerBindingsStub(); - } - return instance; - } - public static DialerLegacyBindings getLegacy(Context context) { Objects.requireNonNull(context); if (legacyInstance != null) { @@ -67,11 +46,4 @@ public class Bindings { return legacyInstance; } - public static void setForTesting(DialerBindings testInstance) { - instance = testInstance; - } - - public static void setLegacyBindingForTesting(DialerLegacyBindings testLegacyInstance) { - legacyInstance = testLegacyInstance; - } } diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java index b5e615075..527dbff18 100644 --- a/java/com/android/dialer/app/DialtactsActivity.java +++ b/java/com/android/dialer/app/DialtactsActivity.java @@ -71,10 +71,12 @@ import com.android.contacts.common.widget.FloatingActionButtonController; import com.android.dialer.animation.AnimUtils; import com.android.dialer.animation.AnimationListenerAdapter; import com.android.dialer.app.calllog.CallLogActivity; +import com.android.dialer.app.calllog.CallLogAdapter; import com.android.dialer.app.calllog.CallLogFragment; import com.android.dialer.app.calllog.CallLogNotificationsService; import com.android.dialer.app.dialpad.DialpadFragment; import com.android.dialer.app.list.DialtactsPagerAdapter; +import com.android.dialer.app.list.DialtactsPagerAdapter.TabIndex; import com.android.dialer.app.list.DragDropController; import com.android.dialer.app.list.ListsFragment; import com.android.dialer.app.list.OldSpeedDialFragment; @@ -91,8 +93,8 @@ import com.android.dialer.callcomposer.CallComposerActivity; import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.callintent.CallSpecificAppData; import com.android.dialer.common.Assert; -import com.android.dialer.common.ConfigProviderBindings; import com.android.dialer.common.LogUtil; +import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.dialer.database.Database; import com.android.dialer.database.DialerDatabaseHelper; import com.android.dialer.interactions.PhoneNumberInteraction; @@ -100,21 +102,24 @@ import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorCo import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; import com.android.dialer.logging.ScreenEvent; +import com.android.dialer.logging.UiAction; +import com.android.dialer.main.Main; +import com.android.dialer.main.MainComponent; import com.android.dialer.p13n.inference.P13nRanking; import com.android.dialer.p13n.inference.protocol.P13nRanker; import com.android.dialer.p13n.inference.protocol.P13nRanker.P13nRefreshCompleteListener; import com.android.dialer.p13n.logging.P13nLogger; import com.android.dialer.p13n.logging.P13nLogging; +import com.android.dialer.performancereport.PerformanceReport; import com.android.dialer.postcall.PostCall; import com.android.dialer.proguard.UsedByReflection; -import com.android.dialer.searchfragment.NewSearchFragment; +import com.android.dialer.searchfragment.list.NewSearchFragment; import com.android.dialer.simulator.Simulator; import com.android.dialer.simulator.SimulatorComponent; import com.android.dialer.smartdial.SmartDialNameMatcher; import com.android.dialer.smartdial.SmartDialPrefix; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.DialerUtils; -import com.android.dialer.util.IntentUtil; import com.android.dialer.util.PermissionsUtil; import com.android.dialer.util.TouchPointManager; import com.android.dialer.util.TransactionSafeActivity; @@ -132,6 +137,7 @@ public class DialtactsActivity extends TransactionSafeActivity DialpadFragment.OnDialpadQueryChangedListener, OnListFragmentScrolledListener, CallLogFragment.HostInterface, + CallLogAdapter.OnActionModeStateChangedListener, DialpadFragment.HostInterface, OldSpeedDialFragment.HostInterface, SearchFragment.HostInterface, @@ -149,6 +155,7 @@ public class DialtactsActivity extends TransactionSafeActivity private static final String ACTION_SHOW_TAB = "ACTION_SHOW_TAB"; @VisibleForTesting public static final String EXTRA_SHOW_TAB = "EXTRA_SHOW_TAB"; public static final String EXTRA_CLEAR_NEW_VOICEMAILS = "EXTRA_CLEAR_NEW_VOICEMAILS"; + private static final String KEY_LAST_TAB = "last_tab"; private static final String TAG = "DialtactsActivity"; private static final String KEY_IN_REGULAR_SEARCH_UI = "in_regular_search_ui"; private static final String KEY_IN_DIALPAD_SEARCH_UI = "in_dialpad_search_ui"; @@ -232,6 +239,9 @@ public class DialtactsActivity extends TransactionSafeActivity private P13nLogger mP13nLogger; private P13nRanker mP13nRanker; + public boolean isMultiSelectModeEnabled; + + private boolean isLastTabEnabled; AnimationListenerAdapter mSlideInListener = new AnimationListenerAdapter() { @@ -263,6 +273,11 @@ public class DialtactsActivity extends TransactionSafeActivity // no need to do anything here. return; } + + if (count != 0) { + PerformanceReport.recordClick(UiAction.Type.TEXT_CHANGE_WITH_INPUT); + } + if (DEBUG) { LogUtil.v("DialtactsActivity.onTextChanged", "called with new query: " + newText); LogUtil.v("DialtactsActivity.onTextChanged", "previous query: " + mSearchQuery); @@ -299,6 +314,7 @@ public class DialtactsActivity extends TransactionSafeActivity @Override public void onClick(View v) { if (!isInSearchUi()) { + PerformanceReport.recordClick(UiAction.Type.OPEN_SEARCH); mActionBarController.onSearchBoxTapped(); enterSearchUi( false /* smartDialSearch */, mSearchView.getText().toString(), true /* animate */); @@ -316,9 +332,13 @@ public class DialtactsActivity extends TransactionSafeActivity if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) { if (TextUtils.isEmpty(mSearchView.getText().toString())) { // If the search term is empty, close the search UI. + PerformanceReport.recordClick(UiAction.Type.CLOSE_SEARCH_WITH_HIDE_BUTTON); maybeExitSearchUi(); } else { // If the search term is not empty, show the dialpad fab. + if (!mFloatingActionButtonController.isVisible()) { + PerformanceReport.recordClick(UiAction.Type.HIDE_KEYBOARD_IN_SEARCH); + } showFabInSearchUi(); } } @@ -365,6 +385,7 @@ public class DialtactsActivity extends TransactionSafeActivity super.onCreate(savedInstanceState); mFirstLaunch = true; + isLastTabEnabled = ConfigProviderBindings.get(this).getBoolean("last_tab_enabled", false); final Resources resources = getResources(); mActionBarHeight = resources.getDimensionPixelSize(R.dimen.action_bar_height_large); @@ -490,6 +511,13 @@ public class DialtactsActivity extends TransactionSafeActivity Trace.beginSection(TAG + " onResume"); super.onResume(); + // Some calls may not be recorded (eg. from quick contact), + // so we should restart recording after these calls. (Recorded call is stopped) + PostCall.restartPerformanceRecordingIfARecentCallExist(this); + if (!PerformanceReport.isRecording()) { + PerformanceReport.startRecording(); + } + mStateSaved = false; if (mFirstLaunch) { displayFragment(getIntent()); @@ -552,7 +580,8 @@ public class DialtactsActivity extends TransactionSafeActivity } if (getIntent().getBooleanExtra(EXTRA_CLEAR_NEW_VOICEMAILS, false)) { - CallLogNotificationsService.markNewVoicemailsAsOld(this, null); + LogUtil.i("DialtactsActivity.onResume", "clearing all new voicemails"); + CallLogNotificationsService.markAllNewVoicemailsAsOld(this); } } @@ -603,6 +632,10 @@ public class DialtactsActivity extends TransactionSafeActivity && !getSystemService(KeyguardManager.class).isKeyguardLocked()) { mListsFragment.markMissedCallsAsReadAndRemoveNotifications(); } + DialerUtils.getDefaultSharedPreferenceForDeviceProtectedStorageContext(this) + .edit() + .putInt(KEY_LAST_TAB, mListsFragment.getCurrentTabIndex()) + .apply(); } @Override @@ -676,13 +709,8 @@ public class DialtactsActivity extends TransactionSafeActivity public void onClick(View view) { int resId = view.getId(); if (resId == R.id.floating_action_button) { - if (mListsFragment.getCurrentTabIndex() == DialtactsPagerAdapter.TAB_INDEX_ALL_CONTACTS - && !mInRegularSearch - && !mInDialpadSearch) { - DialerUtils.startActivityWithErrorToast( - this, IntentUtil.getNewContactIntent(), R.string.add_contact_not_available); - Logger.get(this).logImpression(DialerImpression.Type.NEW_CONTACT_FAB); - } else if (!mIsDialpadShown) { + if (!mIsDialpadShown) { + PerformanceReport.recordClick(UiAction.Type.OPEN_DIALPAD); mInCallDialpadUp = false; showDialpadFragment(true); PostCall.closePrompt(); @@ -712,6 +740,7 @@ public class DialtactsActivity extends TransactionSafeActivity int resId = item.getItemId(); if (resId == R.id.menu_history) { + PerformanceReport.recordClick(UiAction.Type.OPEN_CALL_HISTORY); final Intent intent = new Intent(this, CallLogActivity.class); startActivity(intent); } else if (resId == R.id.menu_clear_frequents) { @@ -722,6 +751,9 @@ public class DialtactsActivity extends TransactionSafeActivity handleMenuSettings(); Logger.get(this).logScreenView(ScreenEvent.Type.SETTINGS, this); return true; + } else if (resId == R.id.menu_new_ui_launcher_shortcut) { + MainComponent.get(this).getMain().createNewUiLauncherShortcut(this); + return true; } return false; } @@ -1020,6 +1052,16 @@ public class DialtactsActivity extends TransactionSafeActivity if (showDialpadChooser && !mDialpadFragment.isVisible()) { mInCallDialpadUp = true; } + } else if (isLastTabEnabled) { + @TabIndex + int tabIndex = + DialerUtils.getDefaultSharedPreferenceForDeviceProtectedStorageContext(this) + .getInt(KEY_LAST_TAB, DialtactsPagerAdapter.TAB_INDEX_SPEED_DIAL); + // If voicemail tab is saved and its availability changes, we still move to the voicemail tab + // but it is quickly removed and shown the contacts tab. + if (mListsFragment != null) { + mListsFragment.showTab(tabIndex); + } } } @@ -1195,6 +1237,8 @@ public class DialtactsActivity extends TransactionSafeActivity @Override public void onBackPressed() { + PerformanceReport.recordClick(UiAction.Type.PRESS_ANDROID_BACK_BUTTON); + if (mStateSaved) { return; } @@ -1279,6 +1323,7 @@ public class DialtactsActivity extends TransactionSafeActivity if (mInDialpadSearch && mSmartDialSearchFragment != null && !mSmartDialSearchFragment.isShowingPermissionRequest()) { + PerformanceReport.recordClick(UiAction.Type.CLOSE_DIALPAD); hideDialpadFragment(true /* animate */, true /* clearDialpad */); return true; } @@ -1287,6 +1332,7 @@ public class DialtactsActivity extends TransactionSafeActivity @Override public void onListFragmentScrollStateChange(int scrollState) { + PerformanceReport.recordScrollStateChange(scrollState); if (scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { hideDialpadFragment(true, false); DialerUtils.hideInputMethod(mParentLayout); @@ -1413,18 +1459,6 @@ public class DialtactsActivity extends TransactionSafeActivity int tabIndex = mListsFragment.getCurrentTabIndex(); mPreviouslySelectedTabIndex = tabIndex; mFloatingActionButtonController.setVisible(true); - if (tabIndex == DialtactsPagerAdapter.TAB_INDEX_ALL_CONTACTS - && !mInRegularSearch - && !mInDialpadSearch) { - mFloatingActionButtonController.changeIcon( - getResources().getDrawable(R.drawable.quantum_ic_person_add_white_24, null), - getResources().getString(R.string.search_shortcut_create_new_contact)); - } else { - mFloatingActionButtonController.changeIcon( - getResources().getDrawable(R.drawable.quantum_ic_dialpad_white_24, null), - getResources().getString(R.string.action_menu_dialpad_button)); - } - timeTabSelected = SystemClock.elapsedRealtime(); } @@ -1509,6 +1543,16 @@ public class DialtactsActivity extends TransactionSafeActivity Arrays.toString(grantResults))); } + @Override + public void onActionModeStateChanged(boolean isEnabled) { + isMultiSelectModeEnabled = isEnabled; + } + + @Override + public boolean isActionModeStateEnabled() { + return isMultiSelectModeEnabled; + } + /** Popup menu accessible from the search bar */ protected class OptionsPopupMenu extends PopupMenu { @@ -1538,6 +1582,10 @@ public class DialtactsActivity extends TransactionSafeActivity simulatorMenuItem.setVisible(false); } + Main dialtacts = MainComponent.get(context).getMain(); + menu.findItem(R.id.menu_new_ui_launcher_shortcut) + .setVisible(dialtacts.isNewUiEnabled(context)); + super.show(); } } diff --git a/java/com/android/dialer/app/bindings/DialerBindings.java b/java/com/android/dialer/app/bindings/DialerBindings.java deleted file mode 100644 index e1f517860..000000000 --- a/java/com/android/dialer/app/bindings/DialerBindings.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2016 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.app.bindings; - -import com.android.dialer.common.ConfigProvider; - -/** This interface allows the container application to customize the dialer. */ -public interface DialerBindings { - - ConfigProvider getConfigProvider(); -} diff --git a/java/com/android/dialer/app/bindings/DialerBindingsFactory.java b/java/com/android/dialer/app/bindings/DialerBindingsFactory.java deleted file mode 100644 index 9f209f99e..000000000 --- a/java/com/android/dialer/app/bindings/DialerBindingsFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2016 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.app.bindings; - -/** - * This interface should be implementated by the Application subclass. It allows the dialer module - * to get references to the DialerBindings. - */ -public interface DialerBindingsFactory { - - DialerBindings newDialerBindings(); -} diff --git a/java/com/android/dialer/app/bindings/DialerBindingsStub.java b/java/com/android/dialer/app/bindings/DialerBindingsStub.java deleted file mode 100644 index f56743fa5..000000000 --- a/java/com/android/dialer/app/bindings/DialerBindingsStub.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2016 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.app.bindings; - -import com.android.dialer.common.ConfigProvider; - -/** Default implementation for dialer bindings. */ -public class DialerBindingsStub implements DialerBindings { - private ConfigProvider configProvider; - - @Override - public ConfigProvider getConfigProvider() { - if (configProvider == null) { - configProvider = - new ConfigProvider() { - @Override - public String getString(String key, String defaultValue) { - return defaultValue; - } - - @Override - public long getLong(String key, long defaultValue) { - return defaultValue; - } - - @Override - public boolean getBoolean(String key, boolean defaultValue) { - return defaultValue; - } - }; - } - return configProvider; - } -} diff --git a/java/com/android/dialer/app/calllog/CallLogActivity.java b/java/com/android/dialer/app/calllog/CallLogActivity.java index 443171d3f..6433af9a6 100644 --- a/java/com/android/dialer/app/calllog/CallLogActivity.java +++ b/java/com/android/dialer/app/calllog/CallLogActivity.java @@ -34,6 +34,9 @@ import com.android.dialer.app.R; import com.android.dialer.database.CallLogQueryHandler; import com.android.dialer.logging.Logger; import com.android.dialer.logging.ScreenEvent; +import com.android.dialer.logging.UiAction; +import com.android.dialer.performancereport.PerformanceReport; +import com.android.dialer.postcall.PostCall; import com.android.dialer.util.TransactionSafeActivity; import com.android.dialer.util.ViewUtil; @@ -48,7 +51,6 @@ public class CallLogActivity extends TransactionSafeActivity private ViewPagerTabs mViewPagerTabs; private ViewPagerAdapter mViewPagerAdapter; private CallLogFragment mAllCallsFragment; - private CallLogFragment mMissedCallsFragment; private String[] mTabTitles; private boolean mIsResumed; @@ -93,9 +95,16 @@ public class CallLogActivity extends TransactionSafeActivity @Override protected void onResume() { + // Some calls may not be recorded (eg. from quick contact), + // so we should restart recording after these calls. (Recorded call is stopped) + PostCall.restartPerformanceRecordingIfARecentCallExist(this); + if (!PerformanceReport.isRecording()) { + PerformanceReport.startRecording(); + } + mIsResumed = true; super.onResume(); - sendScreenViewForChildFragment(mViewPager.getCurrentItem()); + sendScreenViewForChildFragment(); } @Override @@ -129,6 +138,7 @@ public class CallLogActivity extends TransactionSafeActivity } if (item.getItemId() == android.R.id.home) { + PerformanceReport.recordClick(UiAction.Type.CLOSE_CALL_HISTORY_WITH_CANCEL_BUTTON); final Intent intent = new Intent(this, DialtactsActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); @@ -148,7 +158,7 @@ public class CallLogActivity extends TransactionSafeActivity @Override public void onPageSelected(int position) { if (mIsResumed) { - sendScreenViewForChildFragment(position); + sendScreenViewForChildFragment(); } mViewPagerTabs.onPageSelected(position); } @@ -158,7 +168,7 @@ public class CallLogActivity extends TransactionSafeActivity mViewPagerTabs.onPageScrollStateChanged(state); } - private void sendScreenViewForChildFragment(int position) { + private void sendScreenViewForChildFragment() { Logger.get(this).logScreenView(ScreenEvent.Type.CALL_LOG_FILTER, this); } @@ -169,6 +179,12 @@ public class CallLogActivity extends TransactionSafeActivity return position; } + @Override + public void onBackPressed() { + PerformanceReport.recordClick(UiAction.Type.PRESS_ANDROID_BACK_BUTTON); + super.onBackPressed(); + } + /** Adapter for the view pager. */ public class ViewPagerAdapter extends FragmentPagerAdapter { @@ -189,20 +205,16 @@ public class CallLogActivity extends TransactionSafeActivity CallLogQueryHandler.CALL_TYPE_ALL, true /* isCallLogActivity */); case TAB_INDEX_MISSED: return new CallLogFragment(Calls.MISSED_TYPE, true /* isCallLogActivity */); + default: + throw new IllegalStateException("No fragment at position " + position); } - throw new IllegalStateException("No fragment at position " + position); } @Override public Object instantiateItem(ViewGroup container, int position) { final CallLogFragment fragment = (CallLogFragment) super.instantiateItem(container, position); - switch (position) { - case TAB_INDEX_ALL: + if (position == TAB_INDEX_ALL) { mAllCallsFragment = fragment; - break; - case TAB_INDEX_MISSED: - mMissedCallsFragment = fragment; - break; } return fragment; } diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java index 3357ee2f1..f1d051a8c 100644 --- a/java/com/android/dialer/app/calllog/CallLogAdapter.java +++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java @@ -19,6 +19,7 @@ package com.android.dialer.app.calllog; import android.app.Activity; import android.content.ContentUris; import android.content.DialogInterface; +import android.content.DialogInterface.OnCancelListener; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; @@ -52,7 +53,6 @@ import android.view.ViewGroup; import com.android.contacts.common.ContactsUtils; import com.android.contacts.common.compat.PhoneNumberUtilsCompat; import com.android.contacts.common.preference.ContactsPreferences; -import com.android.dialer.app.Bindings; import com.android.dialer.app.DialtactsActivity; import com.android.dialer.app.R; import com.android.dialer.app.calllog.CallLogGroupBuilder.GroupCreator; @@ -66,10 +66,10 @@ import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry; import com.android.dialer.calllogutils.PhoneAccountUtils; import com.android.dialer.calllogutils.PhoneCallDetails; import com.android.dialer.common.Assert; -import com.android.dialer.common.ConfigProviderBindings; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.AsyncTaskExecutor; import com.android.dialer.common.concurrent.AsyncTaskExecutors; +import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.dialer.enrichedcall.EnrichedCallCapabilities; import com.android.dialer.enrichedcall.EnrichedCallComponent; import com.android.dialer.enrichedcall.EnrichedCallManager; @@ -80,6 +80,8 @@ import com.android.dialer.lightbringer.LightbringerListener; import com.android.dialer.logging.ContactSource; import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; +import com.android.dialer.logging.UiAction; +import com.android.dialer.performancereport.PerformanceReport; import com.android.dialer.phonenumbercache.CallLogQuery; import com.android.dialer.phonenumbercache.ContactInfo; import com.android.dialer.phonenumbercache.ContactInfoHelper; @@ -119,6 +121,7 @@ public class CallLogAdapter extends GroupingListAdapter protected final CallLogCache mCallLogCache; private final CallFetcher mCallFetcher; + private final OnActionModeStateChangedListener mActionModeStateChangedListener; private final MultiSelectRemoveView mMultiSelectRemoveView; @NonNull private final FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler; private final int mActivityType; @@ -159,6 +162,7 @@ public class CallLogAdapter extends GroupingListAdapter MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.actionbar_delete, menu); mMultiSelectRemoveView.showMultiSelectRemoveView(true); + mActionModeStateChangedListener.onActionModeStateChanged(true); return true; } @@ -173,6 +177,7 @@ public class CallLogAdapter extends GroupingListAdapter @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { if (item.getItemId() == R.id.action_bar_delete_menu_item) { + Logger.get(mActivity).logImpression(DialerImpression.Type.MULTISELECT_TAP_DELETE_ICON); if (selectedItems.size() > 0) { showDeleteSelectedItemsDialog(); } @@ -195,52 +200,68 @@ public class CallLogAdapter extends GroupingListAdapter selectAllMode = false; deselectAllMode = false; mMultiSelectRemoveView.showMultiSelectRemoveView(false); + mActionModeStateChangedListener.onActionModeStateChanged(false); notifyDataSetChanged(); } }; - // Todo (uabdullah): Use plurals http://b/37751831 private void showDeleteSelectedItemsDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); - Assert.checkArgument(selectedItems.size() > 0); - String voicemailString = - selectedItems.size() == 1 - ? mActivity.getResources().getString(R.string.voicemailMultiSelectVoicemail) - : mActivity.getResources().getString(R.string.voicemailMultiSelectVoicemails); - String deleteVoicemailTitle = - mActivity - .getResources() - .getString(R.string.voicemailMultiSelectDialogTitle, voicemailString); SparseArray voicemailsToDeleteOnConfirmation = selectedItems.clone(); - builder.setTitle(deleteVoicemailTitle); - - builder.setPositiveButton( - mActivity.getResources().getString(R.string.voicemailMultiSelectDeleteConfirm), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - deleteSelectedItems(voicemailsToDeleteOnConfirmation); - mActionMode.finish(); - dialog.cancel(); - } - }); - - builder.setNegativeButton( - mActivity.getResources().getString(R.string.voicemailMultiSelectDeleteCancel), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - - AlertDialog dialog = builder.create(); - dialog.show(); + new AlertDialog.Builder(mActivity, R.style.AlertDialogCustom) + .setCancelable(true) + .setTitle( + mActivity + .getResources() + .getQuantityString( + R.plurals.delete_voicemails_confirmation_dialog_title, selectedItems.size())) + .setPositiveButton( + R.string.voicemailMultiSelectDeleteConfirm, + new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int button) { + LogUtil.i( + "CallLogAdapter.showDeleteSelectedItemsDialog", + "onClick, these items to delete " + voicemailsToDeleteOnConfirmation); + deleteSelectedItems(voicemailsToDeleteOnConfirmation); + mActionMode.finish(); + dialog.cancel(); + Logger.get(mActivity) + .logImpression( + DialerImpression.Type.MULTISELECT_DELETE_ENTRY_VIA_CONFIRMATION_DIALOG); + } + }) + .setOnCancelListener( + new OnCancelListener() { + @Override + public void onCancel(DialogInterface dialogInterface) { + Logger.get(mActivity) + .logImpression( + DialerImpression.Type + .MULTISELECT_CANCEL_CONFIRMATION_DIALOG_VIA_CANCEL_TOUCH); + dialogInterface.cancel(); + } + }) + .setNegativeButton( + R.string.voicemailMultiSelectDeleteCancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int button) { + Logger.get(mActivity) + .logImpression( + DialerImpression.Type + .MULTISELECT_CANCEL_CONFIRMATION_DIALOG_VIA_CANCEL_BUTTON); + dialog.cancel(); + } + }) + .show(); + Logger.get(mActivity) + .logImpression(DialerImpression.Type.MULTISELECT_DISPLAY_DELETE_CONFIRMATION_DIALOG); } private void deleteSelectedItems(SparseArray voicemailsToDelete) { for (int i = 0; i < voicemailsToDelete.size(); i++) { String voicemailUri = voicemailsToDelete.get(voicemailsToDelete.keyAt(i)); + LogUtil.i("CallLogAdapter.deleteSelectedItems", "deleting uri:" + voicemailUri); CallLogAsyncTaskUtil.deleteVoicemail(mActivity, Uri.parse(voicemailUri), null); } } @@ -254,8 +275,13 @@ public class CallLogAdapter extends GroupingListAdapter && mVoicemailPlaybackPresenter != null) { if (v.getId() == R.id.primary_action_view || v.getId() == R.id.quick_contact_photo) { if (mActionMode == null) { + Logger.get(mActivity) + .logImpression( + DialerImpression.Type.MULTISELECT_LONG_PRESS_ENTER_MULTI_SELECT_MODE); mActionMode = v.startActionMode(mActionModeCallback); } + Logger.get(mActivity) + .logImpression(DialerImpression.Type.MULTISELECT_LONG_PRESS_TAP_ENTRY); CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder) v.getTag(); viewHolder.quickContactView.setVisibility(View.GONE); viewHolder.checkBoxView.setVisibility(View.VISIBLE); @@ -272,6 +298,8 @@ public class CallLogAdapter extends GroupingListAdapter new View.OnClickListener() { @Override public void onClick(View v) { + PerformanceReport.recordClick(UiAction.Type.CLICK_CALL_LOG_ITEM); + CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder) v.getTag(); if (viewHolder == null) { return; @@ -282,8 +310,12 @@ public class CallLogAdapter extends GroupingListAdapter mMultiSelectRemoveView.setSelectAllModeToFalse(); int id = getVoicemailId(viewHolder.voicemailUri); if (selectedItems.get(id) != null) { + Logger.get(mActivity) + .logImpression(DialerImpression.Type.MULTISELECT_SINGLE_PRESS_UNSELECT_ENTRY); uncheckMarkCallLogEntry(viewHolder, id); } else { + Logger.get(mActivity) + .logImpression(DialerImpression.Type.MULTISELECT_SINGLE_PRESS_SELECT_ENTRY); checkMarkCallLogEntry(viewHolder); } return; @@ -343,6 +375,8 @@ public class CallLogAdapter extends GroupingListAdapter private void updateActionBar() { if (mActionMode == null && selectedItems.size() > 0) { + Logger.get(mActivity) + .logImpression(DialerImpression.Type.MULTISELECT_ROTATE_AND_SHOW_ACTION_MODE); mActivity.startActionMode(mActionModeCallback); } if (mActionMode != null) { @@ -413,6 +447,7 @@ public class CallLogAdapter extends GroupingListAdapter ViewGroup alertContainer, CallFetcher callFetcher, MultiSelectRemoveView multiSelectRemoveView, + OnActionModeStateChangedListener actionModeStateChangedListener, CallLogCache callLogCache, ContactInfoCache contactInfoCache, VoicemailPlaybackPresenter voicemailPlaybackPresenter, @@ -422,6 +457,7 @@ public class CallLogAdapter extends GroupingListAdapter mActivity = activity; mCallFetcher = callFetcher; + mActionModeStateChangedListener = actionModeStateChangedListener; mMultiSelectRemoveView = multiSelectRemoveView; mVoicemailPlaybackPresenter = voicemailPlaybackPresenter; if (mVoicemailPlaybackPresenter != null) { @@ -484,12 +520,23 @@ public class CallLogAdapter extends GroupingListAdapter outState.putLong(KEY_EXPANDED_ROW_ID, mCurrentlyExpandedRowId); ArrayList listOfSelectedItems = new ArrayList<>(); + if (selectedItems.size() > 0) { for (int i = 0; i < selectedItems.size(); i++) { - listOfSelectedItems.add(Integer.toString(selectedItems.keyAt(i))); + int id = selectedItems.keyAt(i); + String voicemailUri = selectedItems.valueAt(i); + LogUtil.i( + "CallLogAdapter.onSaveInstanceState", "index %d, id=%d, uri=%s ", i, id, voicemailUri); + listOfSelectedItems.add(voicemailUri); } } outState.putStringArrayList(KEY_ACTION_MODE, listOfSelectedItems); + + LogUtil.i( + "CallLogAdapter.onSaveInstanceState", + "saved: %d, selectedItemsSize:%d", + listOfSelectedItems.size(), + selectedItems.size()); } public void onRestoreInstanceState(Bundle savedInstanceState) { @@ -498,16 +545,31 @@ public class CallLogAdapter extends GroupingListAdapter savedInstanceState.getInt(KEY_EXPANDED_POSITION, RecyclerView.NO_POSITION); mCurrentlyExpandedRowId = savedInstanceState.getLong(KEY_EXPANDED_ROW_ID, NO_EXPANDED_LIST_ITEM); - // Restoring multi selected entries ArrayList listOfSelectedItems = savedInstanceState.getStringArrayList(KEY_ACTION_MODE); + LogUtil.i( + "CallLogAdapter.onRestoreInstanceState", + "restored selectedItemsList:%d", + listOfSelectedItems.size()); + if (!listOfSelectedItems.isEmpty()) { for (int i = 0; i < listOfSelectedItems.size(); i++) { - String voicemailId = listOfSelectedItems.get(i); - int id = Integer.parseInt(voicemailId); - selectedItems.put(id, voicemailId); + String voicemailUri = listOfSelectedItems.get(i); + int id = getVoicemailId(voicemailUri); + LogUtil.i( + "CallLogAdapter.onRestoreInstanceState", + "restoring selected index %d, id=%d, uri=%s ", + i, + id, + voicemailUri); + selectedItems.put(id, voicemailUri); } + + LogUtil.i( + "CallLogAdapter.onRestoreInstance", + "restored selectedItems %s", + selectedItems.toString()); updateActionBar(); } } @@ -597,6 +659,7 @@ public class CallLogAdapter extends GroupingListAdapter mBlockReportSpamListener, mExpandCollapseListener, mLongPressListener, + mActionModeStateChangedListener, mCallLogCache, mCallLogListItemHelper, mVoicemailPlaybackPresenter); @@ -622,7 +685,7 @@ public class CallLogAdapter extends GroupingListAdapter Trace.beginSection("onBindViewHolder: " + position); switch (getItemViewType(position)) { case VIEW_TYPE_ALERT: - //Do nothing + // Do nothing break; default: bindCallLogListViewHolder(viewHolder, position); @@ -931,8 +994,7 @@ public class CallLogAdapter extends GroupingListAdapter details.countryIso, details.cachedContactInfo, position - < Bindings.get(mActivity) - .getConfigProvider() + < ConfigProviderBindings.get(mActivity) .getLong("number_of_call_to_do_remote_lookup", 5L)); } CharSequence formattedNumber = @@ -1318,6 +1380,14 @@ public class CallLogAdapter extends GroupingListAdapter void fetchCalls(); } + /** Interface used to allow single tap multi select for contact photos. */ + public interface OnActionModeStateChangedListener { + + void onActionModeStateChanged(boolean isEnabled); + + boolean isActionModeStateEnabled(); + } + /** Interface used to hide the fragments. */ public interface MultiSelectRemoveView { diff --git a/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java b/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java index a5553d134..10866aae2 100644 --- a/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java +++ b/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java @@ -28,6 +28,7 @@ import android.provider.VoicemailContract.Voicemails; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; +import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.AsyncTaskExecutor; import com.android.dialer.common.concurrent.AsyncTaskExecutors; import com.android.dialer.util.PermissionsUtil; @@ -45,6 +46,7 @@ public class CallLogAsyncTaskUtil { public static void markVoicemailAsRead( @NonNull final Context context, @NonNull final Uri voicemailUri) { + LogUtil.enterBlock("CallLogAsyncTaskUtil.markVoicemailAsRead, voicemailUri: " + voicemailUri); if (sAsyncTaskExecutor == null) { initTaskExecutor(); } @@ -66,9 +68,7 @@ public class CallLogAsyncTaskUtil { uploadVoicemailLocalChangesToServer(context); } - Intent intent = new Intent(context, CallLogNotificationsService.class); - intent.setAction(CallLogNotificationsService.ACTION_MARK_NEW_VOICEMAILS_AS_OLD); - context.startService(intent); + CallLogNotificationsService.markAllNewVoicemailsAsOld(context); return null; } }); diff --git a/java/com/android/dialer/app/calllog/CallLogFragment.java b/java/com/android/dialer/app/calllog/CallLogFragment.java index 1571c1aef..b03a4ad64 100644 --- a/java/com/android/dialer/app/calllog/CallLogFragment.java +++ b/java/com/android/dialer/app/calllog/CallLogFragment.java @@ -35,14 +35,20 @@ import android.provider.ContactsContract; import android.support.annotation.CallSuper; import android.support.annotation.Nullable; import android.support.v13.app.FragmentCompat; +import android.support.v13.app.FragmentCompat.OnRequestPermissionsResultCallback; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; import com.android.dialer.app.Bindings; import com.android.dialer.app.R; +import com.android.dialer.app.calllog.CallLogAdapter.CallFetcher; +import com.android.dialer.app.calllog.CallLogAdapter.MultiSelectRemoveView; import com.android.dialer.app.calllog.calllogcache.CallLogCache; import com.android.dialer.app.contactinfo.ContactInfoCache; import com.android.dialer.app.contactinfo.ContactInfoCache.OnContactInfoChangedListener; @@ -53,37 +59,44 @@ import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.database.CallLogQueryHandler; +import com.android.dialer.database.CallLogQueryHandler.Listener; import com.android.dialer.location.GeoUtil; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; import com.android.dialer.oem.CequintCallerIdManager; +import com.android.dialer.performancereport.PerformanceReport; import com.android.dialer.phonenumbercache.ContactInfoHelper; import com.android.dialer.util.PermissionsUtil; import com.android.dialer.widget.EmptyContentView; import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener; +import java.util.Arrays; /** * Displays a list of call log entries. To filter for a particular kind of call (all, missed or * voicemails), specify it in the constructor. */ public class CallLogFragment extends Fragment - implements CallLogQueryHandler.Listener, - CallLogAdapter.CallFetcher, - CallLogAdapter.MultiSelectRemoveView, + implements Listener, + CallFetcher, + MultiSelectRemoveView, OnEmptyViewActionButtonClickedListener, - FragmentCompat.OnRequestPermissionsResultCallback, - CallLogModalAlertManager.Listener { + OnRequestPermissionsResultCallback, + CallLogModalAlertManager.Listener, + OnClickListener { private static final String KEY_FILTER_TYPE = "filter_type"; private static final String KEY_LOG_LIMIT = "log_limit"; private static final String KEY_DATE_LIMIT = "date_limit"; private static final String KEY_IS_CALL_LOG_ACTIVITY = "is_call_log_activity"; private static final String KEY_HAS_READ_CALL_LOG_PERMISSION = "has_read_call_log_permission"; private static final String KEY_REFRESH_DATA_REQUIRED = "refresh_data_required"; + private static final String KEY_SELECT_ALL_MODE = "select_all_mode_checked"; // No limit specified for the number of logs to show; use the CallLogQueryHandler's default. private static final int NO_LOG_LIMIT = -1; // No date-based filtering. private static final int NO_DATE_LIMIT = 0; - private static final int READ_CALL_LOG_PERMISSION_REQUEST_CODE = 1; + private static final int PHONE_PERMISSIONS_REQUEST_CODE = 1; private static final int EVENT_UPDATE_DISPLAY = 1; @@ -92,6 +105,9 @@ public class CallLogFragment extends Fragment // See issue 6363009 private final ContentObserver mCallLogObserver = new CustomContentObserver(); private final ContentObserver mContactsObserver = new CustomContentObserver(); + private View mMultiSelectUnSelectAllViewContent; + private TextView mSelectUnselectAllViewText; + private ImageView mSelectUnselectAllIcon; private RecyclerView mRecyclerView; private LinearLayoutManager mLayoutManager; private CallLogAdapter mAdapter; @@ -125,6 +141,7 @@ public class CallLogFragment extends Fragment * True if this instance of the CallLogFragment shown in the CallLogActivity. */ private boolean mIsCallLogActivity = false; + private boolean selectAllMode; private final Handler mDisplayUpdateHandler = new Handler() { @Override @@ -196,6 +213,7 @@ public class CallLogFragment extends Fragment mIsCallLogActivity = state.getBoolean(KEY_IS_CALL_LOG_ACTIVITY, mIsCallLogActivity); mHasReadCallLogPermission = state.getBoolean(KEY_HAS_READ_CALL_LOG_PERMISSION, false); mRefreshDataRequired = state.getBoolean(KEY_REFRESH_DATA_REQUIRED, mRefreshDataRequired); + selectAllMode = state.getBoolean(KEY_SELECT_ALL_MODE, false); } final Activity activity = getActivity(); @@ -292,12 +310,20 @@ public class CallLogFragment extends Fragment mRecyclerView.setHasFixedSize(true); mLayoutManager = new LinearLayoutManager(getActivity()); mRecyclerView.setLayoutManager(mLayoutManager); + PerformanceReport.logOnScrollStateChange(mRecyclerView); mEmptyListView = (EmptyContentView) view.findViewById(R.id.empty_list_view); mEmptyListView.setImage(R.drawable.empty_call_log); mEmptyListView.setActionClickedListener(this); mModalAlertView = (ViewGroup) view.findViewById(R.id.modal_message_container); mModalAlertManager = new CallLogModalAlertManager(LayoutInflater.from(getContext()), mModalAlertView, this); + mMultiSelectUnSelectAllViewContent = + view.findViewById(R.id.multi_select_select_all_view_content); + mSelectUnselectAllViewText = (TextView) view.findViewById(R.id.select_all_view_text); + mSelectUnselectAllIcon = (ImageView) view.findViewById(R.id.select_all_view_icon); + mMultiSelectUnSelectAllViewContent.setOnClickListener(null); + mSelectUnselectAllIcon.setOnClickListener(this); + mSelectUnselectAllViewText.setOnClickListener(this); } protected void setupData() { @@ -320,6 +346,9 @@ public class CallLogFragment extends Fragment mRecyclerView, this, this, + activityType == CallLogAdapter.ACTIVITY_TYPE_DIALTACTS + ? (CallLogAdapter.OnActionModeStateChangedListener) getActivity() + : null, CallLogCache.getCallLogCache(getActivity()), mContactInfoCache, getVoicemailPlaybackPresenter(), @@ -338,9 +367,18 @@ public class CallLogFragment extends Fragment public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setupData(); + updateSelectAllState(savedInstanceState); mAdapter.onRestoreInstanceState(savedInstanceState); } + private void updateSelectAllState(Bundle savedInstanceState) { + if (savedInstanceState != null) { + if (savedInstanceState.getBoolean(KEY_SELECT_ALL_MODE, false)) { + updateSelectAllIcon(); + } + } + } + @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); @@ -420,7 +458,7 @@ public class CallLogFragment extends Fragment outState.putBoolean(KEY_IS_CALL_LOG_ACTIVITY, mIsCallLogActivity); outState.putBoolean(KEY_HAS_READ_CALL_LOG_PERMISSION, mHasReadCallLogPermission); outState.putBoolean(KEY_REFRESH_DATA_REQUIRED, mRefreshDataRequired); - + outState.putBoolean(KEY_SELECT_ALL_MODE, selectAllMode); mAdapter.onSaveInstanceState(outState); } @@ -518,7 +556,8 @@ public class CallLogFragment extends Fragment if (mKeyguardManager != null && !mKeyguardManager.inKeyguardRestrictedInputMode() && mCallTypeFilter == Calls.VOICEMAIL_TYPE) { - CallLogNotificationsService.markNewVoicemailsAsOld(getActivity(), null); + LogUtil.i("CallLogFragment.updateOnTransition", "clearing all new voicemails"); + CallLogNotificationsService.markAllNewVoicemailsAsOld(getActivity()); } } @@ -529,9 +568,14 @@ public class CallLogFragment extends Fragment return; } - if (!PermissionsUtil.hasPermission(activity, READ_CALL_LOG)) { - FragmentCompat.requestPermissions( - this, new String[] {READ_CALL_LOG}, READ_CALL_LOG_PERMISSION_REQUEST_CODE); + String[] deniedPermissions = + PermissionsUtil.getPermissionsCurrentlyDenied( + getContext(), PermissionsUtil.allPhoneGroupPermissionsUsedInDialer); + if (deniedPermissions.length > 0) { + LogUtil.i( + "CallLogFragment.onEmptyViewActionButtonClicked", + "Requesting permissions: " + Arrays.toString(deniedPermissions)); + FragmentCompat.requestPermissions(this, deniedPermissions, PHONE_PERMISSIONS_REQUEST_CODE); } else if (!mIsCallLogActivity) { // Show dialpad if we are not in the call log activity. ((HostInterface) activity).showDialpad(); @@ -541,7 +585,7 @@ public class CallLogFragment extends Fragment @Override public void onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults) { - if (requestCode == READ_CALL_LOG_PERMISSION_REQUEST_CODE) { + if (requestCode == PHONE_PERMISSIONS_REQUEST_CODE) { if (grantResults.length >= 1 && PackageManager.PERMISSION_GRANTED == grantResults[0]) { // Force a refresh of the data since we were missing the permission before this. mRefreshDataRequired = true; @@ -606,12 +650,40 @@ public class CallLogFragment extends Fragment @Override public void showMultiSelectRemoveView(boolean show) { + mMultiSelectUnSelectAllViewContent.setVisibility(show ? View.VISIBLE : View.GONE); + mMultiSelectUnSelectAllViewContent.setAlpha(show ? 0 : 1); + mMultiSelectUnSelectAllViewContent.animate().alpha(show ? 1 : 0).start(); ((ListsFragment) getParentFragment()).showMultiSelectRemoveView(show); } @Override public void setSelectAllModeToFalse() { - ((ListsFragment) getParentFragment()).setSelectAllModeToFalse(); + selectAllMode = false; + mSelectUnselectAllIcon.setImageDrawable( + getContext().getDrawable(R.drawable.ic_empty_check_mark_white_24dp)); + } + + @Override + public void onClick(View v) { + selectAllMode = !selectAllMode; + if (selectAllMode) { + Logger.get(v.getContext()).logImpression(DialerImpression.Type.MULTISELECT_SELECT_ALL); + } else { + Logger.get(v.getContext()).logImpression(DialerImpression.Type.MULTISELECT_UNSELECT_ALL); + } + updateSelectAllIcon(); + } + + private void updateSelectAllIcon() { + if (selectAllMode) { + mSelectUnselectAllIcon.setImageDrawable( + getContext().getDrawable(R.drawable.ic_check_mark_blue_24dp)); + getAdapter().onAllSelected(); + } else { + mSelectUnselectAllIcon.setImageDrawable( + getContext().getDrawable(R.drawable.ic_empty_check_mark_white_24dp)); + getAdapter().onAllDeselected(); + } } public interface HostInterface { diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java index a9a4d1d42..c59f0dd61 100644 --- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java +++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java @@ -26,23 +26,25 @@ import android.os.AsyncTask; import android.provider.CallLog; import android.provider.CallLog.Calls; import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.support.annotation.IntDef; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; +import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telephony.PhoneNumberUtils; import android.text.BidiFormatter; import android.text.TextDirectionHeuristics; import android.text.TextUtils; import android.view.ContextMenu; +import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewStub; import android.widget.ImageButton; import android.widget.ImageView; -import android.widget.QuickContactBadge; import android.widget.TextView; import android.widget.Toast; import com.android.contacts.common.ClipboardUtils; @@ -54,6 +56,7 @@ import com.android.contacts.common.lettertiles.LetterTileDrawable.ContactType; import com.android.contacts.common.util.UriUtils; import com.android.dialer.app.DialtactsActivity; import com.android.dialer.app.R; +import com.android.dialer.app.calllog.CallLogAdapter.OnActionModeStateChangedListener; import com.android.dialer.app.calllog.calllogcache.CallLogCache; import com.android.dialer.app.voicemail.VoicemailPlaybackLayout; import com.android.dialer.app.voicemail.VoicemailPlaybackPresenter; @@ -61,11 +64,14 @@ import com.android.dialer.blocking.BlockedNumbersMigrator; import com.android.dialer.blocking.FilteredNumberCompat; import com.android.dialer.blocking.FilteredNumbersUtil; import com.android.dialer.callcomposer.CallComposerActivity; +import com.android.dialer.calldetails.CallDetailsActivity; import com.android.dialer.calldetails.CallDetailsEntries; -import com.android.dialer.common.ConfigProviderBindings; +import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.compat.CompatUtils; +import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.dialer.dialercontact.DialerContact; +import com.android.dialer.dialercontact.SimDetails; import com.android.dialer.lightbringer.Lightbringer; import com.android.dialer.lightbringer.LightbringerComponent; import com.android.dialer.logging.ContactSource; @@ -73,12 +79,16 @@ import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.InteractionEvent; import com.android.dialer.logging.Logger; import com.android.dialer.logging.ScreenEvent; +import com.android.dialer.logging.UiAction; +import com.android.dialer.performancereport.PerformanceReport; import com.android.dialer.phonenumbercache.CachedNumberLookupService; import com.android.dialer.phonenumbercache.ContactInfo; import com.android.dialer.phonenumbercache.PhoneNumberCache; import com.android.dialer.phonenumberutil.PhoneNumberHelper; import com.android.dialer.util.CallUtil; import com.android.dialer.util.DialerUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * This is an object containing references to views contained by the call log list item. This @@ -94,7 +104,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder /** The root view of the call log list item */ public final View rootView; /** The quick contact badge for the contact. */ - public final QuickContactBadge quickContactView; + public final DialerQuickContactBadge quickContactView; /** The primary action view of the entry. */ public final View primaryActionView; /** The details of the phone call. */ @@ -112,6 +122,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder private final CachedNumberLookupService mCachedNumberLookupService; private final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; private final OnClickListener mBlockReportListener; + @HostUi private final int hostUi; /** Whether the data fields are populated by the worker thread, ready to be shown. */ public boolean isLoaded; /** The view containing call log item actions. Null until the ViewStub is inflated. */ @@ -205,6 +216,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder public boolean lightbringerReady; private View.OnClickListener mExpandCollapseListener; + private final OnActionModeStateChangedListener onActionModeStateChangedListener; private final View.OnLongClickListener longPressListener; private boolean mVoicemailPrimaryActionButtonClicked; @@ -220,11 +232,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder OnClickListener blockReportListener, View.OnClickListener expandCollapseListener, View.OnLongClickListener longClickListener, + CallLogAdapter.OnActionModeStateChangedListener actionModeStateChangedListener, CallLogCache callLogCache, CallLogListItemHelper callLogListItemHelper, VoicemailPlaybackPresenter voicemailPlaybackPresenter, View rootView, - QuickContactBadge quickContactView, + DialerQuickContactBadge dialerQuickContactView, View primaryActionView, PhoneCallDetailsViews phoneCallDetailsViews, CardView callLogEntryView, @@ -234,6 +247,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder mContext = context; mExpandCollapseListener = expandCollapseListener; + onActionModeStateChangedListener = actionModeStateChangedListener; longPressListener = longClickListener; mCallLogCache = callLogCache; mCallLogListItemHelper = callLogListItemHelper; @@ -242,7 +256,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder mCachedNumberLookupService = PhoneNumberCache.get(mContext).getCachedNumberLookupService(); this.rootView = rootView; - this.quickContactView = quickContactView; + this.quickContactView = dialerQuickContactView; this.primaryActionView = primaryActionView; this.phoneCallDetailsViews = phoneCallDetailsViews; this.callLogEntryView = callLogEntryView; @@ -256,14 +270,17 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder phoneCallDetailsViews.callLocationAndDate.setElegantTextHeight(false); if (mContext instanceof CallLogActivity) { + hostUi = HostUi.CALL_HISTORY; Logger.get(mContext) .logQuickContactOnTouch( quickContactView, InteractionEvent.Type.OPEN_QUICK_CONTACT_FROM_CALL_HISTORY, true); } else if (mVoicemailPlaybackPresenter == null) { + hostUi = HostUi.CALL_LOG; Logger.get(mContext) .logQuickContactOnTouch( quickContactView, InteractionEvent.Type.OPEN_QUICK_CONTACT_FROM_CALL_LOG, true); } else { + hostUi = HostUi.VOICEMAIL; Logger.get(mContext) .logQuickContactOnTouch( quickContactView, InteractionEvent.Type.OPEN_QUICK_CONTACT_FROM_VOICEMAIL, false); @@ -282,6 +299,8 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder CallLogAdapter.ENABLE_CALL_LOG_MULTI_SELECT_FLAG)) { primaryActionView.setOnLongClickListener(longPressListener); quickContactView.setOnLongClickListener(longPressListener); + quickContactView.setMulitSelectListeners( + mExpandCollapseListener, onActionModeStateChangedListener); } else { primaryActionView.setOnCreateContextMenuListener(this); } @@ -293,6 +312,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder OnClickListener blockReportListener, View.OnClickListener expandCollapseListener, View.OnLongClickListener longClickListener, + CallLogAdapter.OnActionModeStateChangedListener actionModeStateChangeListener, CallLogCache callLogCache, CallLogListItemHelper callLogListItemHelper, VoicemailPlaybackPresenter voicemailPlaybackPresenter) { @@ -302,11 +322,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder blockReportListener, expandCollapseListener, longClickListener, + actionModeStateChangeListener, callLogCache, callLogListItemHelper, voicemailPlaybackPresenter, view, - (QuickContactBadge) view.findViewById(R.id.quick_contact_photo), + (DialerQuickContactBadge) view.findViewById(R.id.quick_contact_photo), view.findViewById(R.id.primary_action_view), PhoneCallDetailsViews.fromView(view), (CardView) view.findViewById(R.id.call_log_row), @@ -315,6 +336,11 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder } public static CallLogListItemViewHolder createForTest(Context context) { + return createForTest(context, null); + } + + static CallLogListItemViewHolder createForTest( + Context context, VoicemailPlaybackPresenter voicemailPlaybackPresenter) { Resources resources = context.getResources(); CallLogCache callLogCache = CallLogCache.getCallLogCache(context); PhoneCallDetailsHelper phoneCallDetailsHelper = @@ -326,11 +352,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder null, null /* expandCollapseListener */, null, + null, callLogCache, new CallLogListItemHelper(phoneCallDetailsHelper, resources, callLogCache), - null /* voicemailPlaybackPresenter */, - new View(context), - new QuickContactBadge(context), + voicemailPlaybackPresenter, + LayoutInflater.from(context).inflate(R.layout.call_log_list_item, null), + new DialerQuickContactBadge(context), new View(context), PhoneCallDetailsViews.createForTest(context), new CardView(context), @@ -474,6 +501,17 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder // Treat as normal list item; show call button, if possible. if (PhoneNumberHelper.canPlaceCallsTo(number, numberPresentation)) { boolean isVoicemailNumber = mCallLogCache.isVoicemailNumber(accountHandle, number); + + if (!isVoicemailNumber && showLightbringerPrimaryButton()) { + primaryActionButtonView.setTag(IntentProvider.getLightbringerIntentProvider(number)); + primaryActionButtonView.setContentDescription( + TextUtils.expandTemplate( + mContext.getString(R.string.description_video_call_action), validNameOrNumber)); + primaryActionButtonView.setImageResource(R.drawable.quantum_ic_videocam_vd_theme_24); + primaryActionButtonView.setVisibility(View.VISIBLE); + return; + } + if (isVoicemailNumber) { // Call to generic voicemail number, in case there are multiple accounts. primaryActionButtonView.setTag(IntentProvider.getReturnVoicemailCallIntentProvider()); @@ -531,8 +569,15 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder return; } - if (!TextUtils.isEmpty(voicemailUri) && canPlaceCallToNumber) { + if (canPlaceCallToNumber) { + // Set up the call button but hide it by default (the primary action is to call so it is + // redundant). We then set it to be visible when appropriate below. This saves us having to + // remember to set it to GONE in multiple places. callButtonView.setTag(IntentProvider.getReturnCallIntentProvider(number)); + callButtonView.setVisibility(View.GONE); + } + + if (!TextUtils.isEmpty(voicemailUri) && canPlaceCallToNumber) { ((TextView) callButtonView.findViewById(R.id.call_action_text)) .setText( TextUtils.expandTemplate( @@ -547,13 +592,14 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder callTypeOrLocationView.setVisibility(View.GONE); } callButtonView.setVisibility(View.VISIBLE); - } else { - callButtonView.setVisibility(View.GONE); } if (hasPlacedCarrierVideoCall() || canSupportCarrierVideoCall()) { videoCallButtonView.setTag(IntentProvider.getReturnVideoCallIntentProvider(number)); videoCallButtonView.setVisibility(View.VISIBLE); + } else if (showLightbringerPrimaryButton()) { + callButtonView.setVisibility(View.VISIBLE); + videoCallButtonView.setVisibility(View.GONE); } else if (lightbringerReady) { videoCallButtonView.setTag(IntentProvider.getLightbringerIntentProvider(number)); videoCallButtonView.setVisibility(View.VISIBLE); @@ -585,8 +631,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder detailsButtonView.setVisibility(View.GONE); } else { detailsButtonView.setVisibility(View.VISIBLE); + boolean canReportCallerId = + mCachedNumberLookupService != null + && mCachedNumberLookupService.canReportAsInvalid(info.sourceType, info.objectId); detailsButtonView.setTag( - IntentProvider.getCallDetailIntentProvider(callDetailsEntries, buildContact())); + IntentProvider.getCallDetailIntentProvider( + callDetailsEntries, buildContact(), canReportCallerId)); } boolean isBlockedOrSpam = blockId != null || (isSpamFeatureEnabled && isSpam); @@ -634,6 +684,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder return false; } + private boolean showLightbringerPrimaryButton() { + return accountHandle != null + && accountHandle.getComponentName().equals(getLightbringer().getPhoneAccountComponentName()) + && lightbringerReady; + } + private static boolean hasDialableChar(CharSequence number) { if (TextUtils.isEmpty(number)) { return false; @@ -653,9 +709,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder if (accountHandle == null) { return false; } - if (accountHandle - .getComponentName() - .equals(getLightbringer().getPhoneAccountComponentName(mContext))) { + if (accountHandle.getComponentName().equals(getLightbringer().getPhoneAccountComponentName())) { return false; } return true; @@ -823,9 +877,14 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder // We check to see if we are starting a Lightbringer intent. The reason is Lightbringer // intents need to be started using startActivityForResult instead of the usual startActivity String packageName = intent.getPackage(); - if (packageName != null && packageName.equals(getLightbringer().getPackageName(mContext))) { + if (getLightbringer().getPackageName().equals(packageName)) { startLightbringerActivity(intent); } else { + if (intent.getComponent() != null + && CallDetailsActivity.class.getName().equals(intent.getComponent().getClassName())) { + // We are going to open call detail + PerformanceReport.recordClick(UiAction.Type.OPEN_CALL_DETAIL); + } DialerUtils.startActivityWithErrorToast(mContext, intent); } } @@ -860,6 +919,19 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder } /* phone number type (e.g. mobile) in second line of contact view */ contact.setNumberLabel(numberType); + + /* third line of contact view. */ + String accountLabel = mCallLogCache.getAccountLabel(accountHandle); + if (!TextUtils.isEmpty(accountLabel)) { + SimDetails.Builder simDetails = SimDetails.newBuilder().setNetwork(accountLabel); + int color = mCallLogCache.getAccountColor(accountHandle); + if (color == PhoneAccount.NO_HIGHLIGHT_COLOR) { + simDetails.setColor(R.color.secondary_text_color); + } else { + simDetails.setColor(color); + } + contact.setSimDetails(simDetails.build()); + } return contact.build(); } @@ -868,8 +940,38 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder Logger.get(mContext).logImpression(DialerImpression.Type.CALL_LOG_SEND_MESSAGE); } else if (id == R.id.add_to_existing_contact_action) { Logger.get(mContext).logImpression(DialerImpression.Type.CALL_LOG_ADD_TO_CONTACT); + switch (hostUi) { + case HostUi.CALL_HISTORY: + Logger.get(mContext) + .logImpression(DialerImpression.Type.ADD_TO_A_CONTACT_FROM_CALL_HISTORY); + break; + case HostUi.CALL_LOG: + Logger.get(mContext).logImpression(DialerImpression.Type.ADD_TO_A_CONTACT_FROM_CALL_LOG); + break; + case HostUi.VOICEMAIL: + Logger.get(mContext).logImpression(DialerImpression.Type.ADD_TO_A_CONTACT_FROM_VOICEMAIL); + break; + default: + throw Assert.createIllegalStateFailException(); + } } else if (id == R.id.create_new_contact_action) { Logger.get(mContext).logImpression(DialerImpression.Type.CALL_LOG_CREATE_NEW_CONTACT); + switch (hostUi) { + case HostUi.CALL_HISTORY: + Logger.get(mContext) + .logImpression(DialerImpression.Type.CREATE_NEW_CONTACT_FROM_CALL_HISTORY); + break; + case HostUi.CALL_LOG: + Logger.get(mContext) + .logImpression(DialerImpression.Type.CREATE_NEW_CONTACT_FROM_CALL_LOG); + break; + case HostUi.VOICEMAIL: + Logger.get(mContext) + .logImpression(DialerImpression.Type.CREATE_NEW_CONTACT_FROM_VOICEMAIL); + break; + default: + throw Assert.createIllegalStateFailException(); + } } } @@ -1021,6 +1123,15 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder Logger.get(mContext).logScreenView(ScreenEvent.Type.CALL_LOG_CONTEXT_MENU, (Activity) mContext); } + /** Specifies where the view holder belongs. */ + @IntDef({HostUi.CALL_LOG, HostUi.CALL_HISTORY, HostUi.VOICEMAIL}) + @Retention(RetentionPolicy.SOURCE) + private @interface HostUi { + int CALL_LOG = 0; + int CALL_HISTORY = 1; + int VOICEMAIL = 2; + } + public interface OnClickListener { void onBlockReportSpam( diff --git a/java/com/android/dialer/app/calllog/CallLogNotificationsQueryHelper.java b/java/com/android/dialer/app/calllog/CallLogNotificationsQueryHelper.java index e169b8de9..43e03e9fd 100644 --- a/java/com/android/dialer/app/calllog/CallLogNotificationsQueryHelper.java +++ b/java/com/android/dialer/app/calllog/CallLogNotificationsQueryHelper.java @@ -18,7 +18,6 @@ package com.android.dialer.app.calllog; import android.Manifest; import android.annotation.TargetApi; -import android.app.NotificationManager; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; @@ -27,6 +26,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.Build.VERSION_CODES; import android.provider.CallLog.Calls; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.WorkerThread; import android.support.v4.os.UserManagerCompat; @@ -36,7 +36,6 @@ import com.android.dialer.app.R; import com.android.dialer.calllogutils.PhoneNumberDisplayUtil; import com.android.dialer.common.LogUtil; import com.android.dialer.location.GeoUtil; -import com.android.dialer.notification.GroupedNotificationUtil; import com.android.dialer.phonenumbercache.ContactInfo; import com.android.dialer.phonenumbercache.ContactInfoHelper; import com.android.dialer.util.PermissionsUtil; @@ -46,7 +45,6 @@ import java.util.List; /** Helper class operating on call log notifications. */ public class CallLogNotificationsQueryHelper { - private static final String TAG = "CallLogNotifHelper"; private final Context mContext; private final NewCallsQuery mNewCallsQuery; private final ContactInfoHelper mContactInfoHelper; @@ -74,44 +72,58 @@ public class CallLogNotificationsQueryHelper { countryIso); } + public static void markAllMissedCallsInCallLogAsRead(@NonNull Context context) { + markMissedCallsInCallLogAsRead(context, null); + } + + public static void markSingleMissedCallInCallLogAsRead( + @NonNull Context context, @Nullable Uri callUri) { + if (callUri == null) { + LogUtil.e( + "CallLogNotificationsQueryHelper.markSingleMissedCallInCallLogAsRead", + "call URI is null, unable to mark call as read"); + } else { + markMissedCallsInCallLogAsRead(context, callUri); + } + } + /** - * Removes the missed call notifications and marks calls as read. If a callUri is provided, only - * that call is marked as read. + * If callUri is null then calls with a matching callUri are marked as read, otherwise all calls + * are marked as read. */ @WorkerThread - public static void removeMissedCallNotifications(Context context, @Nullable Uri callUri) { - // Call log is only accessible when unlocked. If that's the case, clear the list of - // new missed calls from the call log. - if (UserManagerCompat.isUserUnlocked(context) && PermissionsUtil.hasPhonePermissions(context)) { - ContentValues values = new ContentValues(); - values.put(Calls.NEW, 0); - values.put(Calls.IS_READ, 1); - StringBuilder where = new StringBuilder(); - where.append(Calls.NEW); - where.append(" = 1 AND "); - where.append(Calls.TYPE); - where.append(" = ?"); - try { - context - .getContentResolver() - .update( - callUri == null ? Calls.CONTENT_URI : callUri, - values, - where.toString(), - new String[] {Integer.toString(Calls.MISSED_TYPE)}); - } catch (IllegalArgumentException e) { - LogUtil.e( - "CallLogNotificationsQueryHelper.removeMissedCallNotifications", - "contacts provider update command failed", - e); - } + private static void markMissedCallsInCallLogAsRead(Context context, @Nullable Uri callUri) { + if (!UserManagerCompat.isUserUnlocked(context)) { + LogUtil.e("CallLogNotificationsQueryHelper.markMissedCallsInCallLogAsRead", "locked"); + return; + } + if (!PermissionsUtil.hasPhonePermissions(context)) { + LogUtil.e("CallLogNotificationsQueryHelper.markMissedCallsInCallLogAsRead", "no permission"); + return; } - GroupedNotificationUtil.removeNotification( - context.getSystemService(NotificationManager.class), - callUri != null ? callUri.toString() : null, - R.id.notification_missed_call, - MissedCallNotifier.NOTIFICATION_TAG); + ContentValues values = new ContentValues(); + values.put(Calls.NEW, 0); + values.put(Calls.IS_READ, 1); + StringBuilder where = new StringBuilder(); + where.append(Calls.NEW); + where.append(" = 1 AND "); + where.append(Calls.TYPE); + where.append(" = ?"); + try { + context + .getContentResolver() + .update( + callUri == null ? Calls.CONTENT_URI : callUri, + values, + where.toString(), + new String[] {Integer.toString(Calls.MISSED_TYPE)}); + } catch (IllegalArgumentException e) { + LogUtil.e( + "CallLogNotificationsQueryHelper.markMissedCallsInCallLogAsRead", + "contacts provider update command failed", + e); + } } /** Create a new instance of {@link NewCallsQuery}. */ @@ -281,7 +293,9 @@ public class CallLogNotificationsQueryHelper { @TargetApi(VERSION_CODES.M) public List query(int type) { if (!PermissionsUtil.hasPermission(mContext, Manifest.permission.READ_CALL_LOG)) { - LogUtil.w(TAG, "No READ_CALL_LOG permission, returning null for calls lookup."); + LogUtil.w( + "CallLogNotificationsQueryHelper.DefaultNewCallsQuery.query", + "no READ_CALL_LOG permission, returning null for calls lookup."); return null; } final String selection = String.format("%s = 1 AND %s = ?", Calls.NEW, Calls.TYPE); @@ -302,7 +316,9 @@ public class CallLogNotificationsQueryHelper { } return newCalls; } catch (RuntimeException e) { - LogUtil.w(TAG, "Exception when querying Contacts Provider for calls lookup"); + LogUtil.w( + "CallLogNotificationsQueryHelper.DefaultNewCallsQuery.query", + "exception when querying Contacts Provider for calls lookup"); return null; } } diff --git a/java/com/android/dialer/app/calllog/CallLogNotificationsService.java b/java/com/android/dialer/app/calllog/CallLogNotificationsService.java index 7dfd2cb69..be1ebfb6d 100644 --- a/java/com/android/dialer/app/calllog/CallLogNotificationsService.java +++ b/java/com/android/dialer/app/calllog/CallLogNotificationsService.java @@ -17,12 +17,13 @@ package com.android.dialer.app.calllog; import android.app.IntentService; +import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.os.Handler; -import android.os.Looper; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; import com.android.dialer.common.LogUtil; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.PermissionsUtil; @@ -43,16 +44,20 @@ import com.android.dialer.util.PermissionsUtil; */ public class CallLogNotificationsService extends IntentService { - /** Action to mark all the new voicemails as old. */ - public static final String ACTION_MARK_NEW_VOICEMAILS_AS_OLD = - "com.android.dialer.calllog.ACTION_MARK_NEW_VOICEMAILS_AS_OLD"; + private static final String ACTION_MARK_ALL_NEW_VOICEMAILS_AS_OLD = + "com.android.dialer.calllog.ACTION_MARK_ALL_NEW_VOICEMAILS_AS_OLD"; - /** Action to mark all the new missed calls as old. */ - public static final String ACTION_MARK_NEW_MISSED_CALLS_AS_OLD = - "com.android.dialer.calllog.ACTION_MARK_NEW_MISSED_CALLS_AS_OLD"; + private static final String ACTION_MARK_SINGLE_NEW_VOICEMAIL_AS_OLD = + "com.android.dialer.calllog.ACTION_MARK_SINGLE_NEW_VOICEMAIL_AS_OLD "; - /** Action to update missed call notifications with a post call note. */ - public static final String ACTION_INCOMING_POST_CALL = + @VisibleForTesting + static final String ACTION_CANCEL_ALL_MISSED_CALLS = + "com.android.dialer.calllog.ACTION_CANCEL_ALL_MISSED_CALLS"; + + private static final String ACTION_CANCEL_SINGLE_MISSED_CALL = + "com.android.dialer.calllog.ACTION_CANCEL_SINGLE_MISSED_CALL"; + + private static final String ACTION_INCOMING_POST_CALL = "com.android.dialer.calllog.INCOMING_POST_CALL"; /** Action to call back a missed call. */ @@ -64,7 +69,7 @@ public class CallLogNotificationsService extends IntentService { * *

It must be a {@link String} */ - public static final String EXTRA_POST_CALL_NOTE = "POST_CALL_NOTE"; + private static final String EXTRA_POST_CALL_NOTE = "POST_CALL_NOTE"; /** * Extra to be included with {@link #ACTION_INCOMING_POST_CALL} to represent the phone number the @@ -72,10 +77,9 @@ public class CallLogNotificationsService extends IntentService { * *

It must be a {@link String} */ - public static final String EXTRA_POST_CALL_NUMBER = "POST_CALL_NUMBER"; + private static final String EXTRA_POST_CALL_NUMBER = "POST_CALL_NUMBER"; public static final int UNKNOWN_MISSED_CALL_COUNT = -1; - private VoicemailQueryHandler mVoicemailQueryHandler; public CallLogNotificationsService() { super("CallLogNotificationsService"); @@ -89,52 +93,95 @@ public class CallLogNotificationsService extends IntentService { context.startService(serviceIntent); } - public static void markNewVoicemailsAsOld(Context context, @Nullable Uri voicemailUri) { + public static void markAllNewVoicemailsAsOld(Context context) { + LogUtil.enterBlock("CallLogNotificationsService.markAllNewVoicemailsAsOld"); Intent serviceIntent = new Intent(context, CallLogNotificationsService.class); - serviceIntent.setAction(CallLogNotificationsService.ACTION_MARK_NEW_VOICEMAILS_AS_OLD); + serviceIntent.setAction(CallLogNotificationsService.ACTION_MARK_ALL_NEW_VOICEMAILS_AS_OLD); + context.startService(serviceIntent); + } + + public static void markSingleNewVoicemailAsOld(Context context, @Nullable Uri voicemailUri) { + LogUtil.enterBlock("CallLogNotificationsService.markSingleNewVoicemailAsOld"); + Intent serviceIntent = new Intent(context, CallLogNotificationsService.class); + serviceIntent.setAction(CallLogNotificationsService.ACTION_MARK_SINGLE_NEW_VOICEMAIL_AS_OLD); serviceIntent.setData(voicemailUri); context.startService(serviceIntent); } - public static void markNewMissedCallsAsOld(Context context, @Nullable Uri callUri) { + public static PendingIntent createMarkAllNewVoicemailsAsOldIntent(@NonNull Context context) { + Intent intent = new Intent(context, CallLogNotificationsService.class); + intent.setAction(CallLogNotificationsService.ACTION_MARK_ALL_NEW_VOICEMAILS_AS_OLD); + return PendingIntent.getService(context, 0, intent, 0); + } + + public static PendingIntent createMarkSingleNewVoicemailAsOldIntent( + @NonNull Context context, @Nullable Uri voicemailUri) { + Intent intent = new Intent(context, CallLogNotificationsService.class); + intent.setAction(CallLogNotificationsService.ACTION_MARK_SINGLE_NEW_VOICEMAIL_AS_OLD); + intent.setData(voicemailUri); + return PendingIntent.getService(context, 0, intent, 0); + } + + public static void cancelAllMissedCalls(@NonNull Context context) { + LogUtil.enterBlock("CallLogNotificationsService.cancelAllMissedCalls"); Intent serviceIntent = new Intent(context, CallLogNotificationsService.class); - serviceIntent.setAction(ACTION_MARK_NEW_MISSED_CALLS_AS_OLD); - serviceIntent.setData(callUri); + serviceIntent.setAction(ACTION_CANCEL_ALL_MISSED_CALLS); context.startService(serviceIntent); } + public static PendingIntent createCancelAllMissedCallsPendingIntent(@NonNull Context context) { + Intent intent = new Intent(context, CallLogNotificationsService.class); + intent.setAction(ACTION_CANCEL_ALL_MISSED_CALLS); + return PendingIntent.getService(context, 0, intent, 0); + } + + public static PendingIntent createCancelSingleMissedCallPendingIntent( + @NonNull Context context, @Nullable Uri callUri) { + Intent intent = new Intent(context, CallLogNotificationsService.class); + intent.setAction(ACTION_CANCEL_SINGLE_MISSED_CALL); + intent.setData(callUri); + return PendingIntent.getService(context, 0, intent, 0); + } + @Override protected void onHandleIntent(Intent intent) { if (intent == null) { - LogUtil.d("CallLogNotificationsService.onHandleIntent", "could not handle null intent"); + LogUtil.e("CallLogNotificationsService.onHandleIntent", "could not handle null intent"); return; } - if (!PermissionsUtil.hasPermission(this, android.Manifest.permission.READ_CALL_LOG)) { + if (!PermissionsUtil.hasPermission(this, android.Manifest.permission.READ_CALL_LOG) + || !PermissionsUtil.hasPermission(this, android.Manifest.permission.WRITE_CALL_LOG)) { + LogUtil.e("CallLogNotificationsService.onHandleIntent", "no READ_CALL_LOG permission"); return; } String action = intent.getAction(); + LogUtil.i("CallLogNotificationsService.onHandleIntent", "action: " + action); switch (action) { - case ACTION_MARK_NEW_VOICEMAILS_AS_OLD: - // VoicemailQueryHandler cannot be created on the IntentService worker thread. The completed - // callback might happen when the thread is dead. - Handler handler = new Handler(Looper.getMainLooper()); - handler.post( - () -> { - if (mVoicemailQueryHandler == null) { - mVoicemailQueryHandler = new VoicemailQueryHandler(this, getContentResolver()); - } - mVoicemailQueryHandler.markNewVoicemailsAsOld(intent.getData()); - }); + case ACTION_MARK_ALL_NEW_VOICEMAILS_AS_OLD: + VoicemailQueryHandler.markAllNewVoicemailsAsRead(this); + VisualVoicemailNotifier.cancelAllVoicemailNotifications(this); + break; + case ACTION_MARK_SINGLE_NEW_VOICEMAIL_AS_OLD: + Uri voicemailUri = intent.getData(); + VoicemailQueryHandler.markSingleNewVoicemailAsRead(this, voicemailUri); + VisualVoicemailNotifier.cancelSingleVoicemailNotification(this, voicemailUri); break; case ACTION_INCOMING_POST_CALL: String note = intent.getStringExtra(EXTRA_POST_CALL_NOTE); String phoneNumber = intent.getStringExtra(EXTRA_POST_CALL_NUMBER); MissedCallNotifier.getIstance(this).insertPostCallNotification(phoneNumber, note); break; - case ACTION_MARK_NEW_MISSED_CALLS_AS_OLD: - CallLogNotificationsQueryHelper.removeMissedCallNotifications(this, intent.getData()); + case ACTION_CANCEL_ALL_MISSED_CALLS: + CallLogNotificationsQueryHelper.markAllMissedCallsInCallLogAsRead(this); + MissedCallNotifier.cancelAllMissedCallNotifications(this); + TelecomUtil.cancelMissedCallsNotification(this); + break; + case ACTION_CANCEL_SINGLE_MISSED_CALL: + Uri callUri = intent.getData(); + CallLogNotificationsQueryHelper.markSingleMissedCallInCallLogAsRead(this, callUri); + MissedCallNotifier.cancelSingleMissedCallNotification(this, callUri); TelecomUtil.cancelMissedCallsNotification(this); break; case ACTION_CALL_BACK_FROM_MISSED_CALL_NOTIFICATION: @@ -145,7 +192,7 @@ public class CallLogNotificationsService extends IntentService { intent.getData()); break; default: - LogUtil.d("CallLogNotificationsService.onHandleIntent", "could not handle: " + intent); + LogUtil.e("CallLogNotificationsService.onHandleIntent", "no handler for action: " + action); break; } } diff --git a/java/com/android/dialer/app/calllog/CallLogReceiver.java b/java/com/android/dialer/app/calllog/CallLogReceiver.java index 172d00100..ce3132d12 100644 --- a/java/com/android/dialer/app/calllog/CallLogReceiver.java +++ b/java/com/android/dialer/app/calllog/CallLogReceiver.java @@ -39,10 +39,10 @@ public class CallLogReceiver extends BroadcastReceiver { if (VoicemailContract.ACTION_NEW_VOICEMAIL.equals(intent.getAction())) { checkVoicemailStatus(context); PendingResult pendingResult = goAsync(); - DefaultVoicemailNotifier.updateVoicemailNotifications(context, pendingResult::finish); + VisualVoicemailUpdateTask.scheduleTask(context, pendingResult::finish); } else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { PendingResult pendingResult = goAsync(); - DefaultVoicemailNotifier.updateVoicemailNotifications(context, pendingResult::finish); + VisualVoicemailUpdateTask.scheduleTask(context, pendingResult::finish); } else { LogUtil.w("CallLogReceiver.onReceive", "could not handle: " + intent); } diff --git a/java/com/android/dialer/app/calllog/ClearCallLogDialog.java b/java/com/android/dialer/app/calllog/ClearCallLogDialog.java index a01b89527..155a91618 100644 --- a/java/com/android/dialer/app/calllog/ClearCallLogDialog.java +++ b/java/com/android/dialer/app/calllog/ClearCallLogDialog.java @@ -54,7 +54,7 @@ public class ClearCallLogDialog extends DialogFragment { ProgressDialog.show( getActivity(), getString(R.string.clearCallLogProgress_title), "", true, false); progressDialog.setOwnerActivity(getActivity()); - CallLogNotificationsService.markNewMissedCallsAsOld(getContext(), null); + CallLogNotificationsService.cancelAllMissedCalls(getContext()); final AsyncTask task = new AsyncTask() { @Override diff --git a/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java b/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java deleted file mode 100644 index 1f45f7086..000000000 --- a/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright (C) 2011 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.app.calllog; - -import android.annotation.TargetApi; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.os.PersistableBundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; -import android.support.annotation.WorkerThread; -import android.support.v4.os.BuildCompat; -import android.support.v4.util.Pair; -import android.telecom.PhoneAccount; -import android.telecom.PhoneAccountHandle; -import android.telecom.TelecomManager; -import android.telephony.CarrierConfigManager; -import android.telephony.PhoneNumberUtils; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.ArrayMap; -import com.android.contacts.common.compat.TelephonyManagerCompat; -import com.android.contacts.common.util.ContactDisplayUtils; -import com.android.dialer.app.DialtactsActivity; -import com.android.dialer.app.R; -import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; -import com.android.dialer.app.contactinfo.ContactPhotoLoader; -import com.android.dialer.app.list.DialtactsPagerAdapter; -import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; -import com.android.dialer.blocking.FilteredNumbersUtil; -import com.android.dialer.calllogutils.PhoneAccountUtils; -import com.android.dialer.common.Assert; -import com.android.dialer.common.LogUtil; -import com.android.dialer.common.concurrent.DialerExecutor.Worker; -import com.android.dialer.common.concurrent.DialerExecutors; -import com.android.dialer.logging.DialerImpression; -import com.android.dialer.logging.Logger; -import com.android.dialer.notification.NotificationChannelManager; -import com.android.dialer.notification.NotificationChannelManager.Channel; -import com.android.dialer.phonenumbercache.ContactInfo; -import com.android.dialer.telecom.TelecomUtil; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -/** Shows a voicemail notification in the status bar. */ -public class DefaultVoicemailNotifier implements Worker { - - public static final String TAG = "VoicemailNotifier"; - - /** The tag used to identify notifications from this class. */ - static final String VISUAL_VOICEMAIL_NOTIFICATION_TAG = "DefaultVoicemailNotifier"; - /** The identifier of the notification of new voicemails. */ - private static final int VISUAL_VOICEMAIL_NOTIFICATION_ID = R.id.notification_visual_voicemail; - - private static final int LEGACY_VOICEMAIL_NOTIFICATION_ID = R.id.notification_legacy_voicemail; - private static final String LEGACY_VOICEMAIL_NOTIFICATION_TAG = "legacy_voicemail"; - - private final Context context; - private final CallLogNotificationsQueryHelper queryHelper; - private final FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler; - - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - DefaultVoicemailNotifier( - Context context, - CallLogNotificationsQueryHelper queryHelper, - FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler) { - this.context = context; - this.queryHelper = queryHelper; - this.filteredNumberAsyncQueryHandler = filteredNumberAsyncQueryHandler; - } - - public DefaultVoicemailNotifier(Context context) { - this( - context, - CallLogNotificationsQueryHelper.getInstance(context), - new FilteredNumberAsyncQueryHandler(context)); - } - - @Nullable - @Override - public Void doInBackground(@Nullable Void input) throws Throwable { - updateNotification(); - return null; - } - - /** - * Updates the notification and notifies of the call with the given URI. - * - *

Clears the notification if there are no new voicemails, and notifies if the given URI - * corresponds to a new voicemail. - * - *

It is not safe to call this method from the main thread. - */ - @VisibleForTesting - @WorkerThread - void updateNotification() { - Assert.isWorkerThread(); - // Lookup the list of new voicemails to include in the notification. - final List newCalls = queryHelper.getNewVoicemails(); - - if (newCalls == null) { - // Query failed, just return. - return; - } - - Resources resources = context.getResources(); - - // This represents a list of names to include in the notification. - String callers = null; - - // Maps each number into a name: if a number is in the map, it has already left a more - // recent voicemail. - final Map contactInfos = new ArrayMap<>(); - - // Iterate over the new voicemails to determine all the information above. - Iterator itr = newCalls.iterator(); - while (itr.hasNext()) { - NewCall newCall = itr.next(); - - // Skip notifying for numbers which are blocked. - if (!FilteredNumbersUtil.hasRecentEmergencyCall(context) - && filteredNumberAsyncQueryHandler.getBlockedIdSynchronous( - newCall.number, newCall.countryIso) - != null) { - itr.remove(); - - if (newCall.voicemailUri != null) { - // Delete the voicemail. - CallLogAsyncTaskUtil.deleteVoicemailSynchronous(context, newCall.voicemailUri); - } - continue; - } - - // Check if we already know the name associated with this number. - ContactInfo contactInfo = contactInfos.get(newCall.number); - if (contactInfo == null) { - contactInfo = - queryHelper.getContactInfo( - newCall.number, newCall.numberPresentation, newCall.countryIso); - contactInfos.put(newCall.number, contactInfo); - // This is a new caller. Add it to the back of the list of callers. - if (TextUtils.isEmpty(callers)) { - callers = contactInfo.name; - } else { - callers = - resources.getString( - R.string.notification_voicemail_callers_list, callers, contactInfo.name); - } - } - } - - if (newCalls.isEmpty()) { - // No voicemails to notify about - return; - } - - Notification.Builder groupSummary = - createNotificationBuilder() - .setContentTitle( - resources.getQuantityString( - R.plurals.notification_voicemail_title, newCalls.size(), newCalls.size())) - .setContentText(callers) - .setDeleteIntent(createMarkNewVoicemailsAsOldIntent(null)) - .setGroupSummary(true) - .setContentIntent(newVoicemailIntent(null)); - - if (BuildCompat.isAtLeastO()) { - groupSummary.setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN); - } - - NotificationChannelManager.applyChannel( - groupSummary, - context, - Channel.VOICEMAIL, - PhoneAccountHandles.getAccount(context, newCalls.get(0))); - - LogUtil.i(TAG, "Creating visual voicemail notification"); - getNotificationManager() - .notify( - VISUAL_VOICEMAIL_NOTIFICATION_TAG, - VISUAL_VOICEMAIL_NOTIFICATION_ID, - groupSummary.build()); - - for (NewCall voicemail : newCalls) { - getNotificationManager() - .notify( - voicemail.callsUri.toString(), - VISUAL_VOICEMAIL_NOTIFICATION_ID, - createNotificationForVoicemail(voicemail, contactInfos)); - } - } - - /** - * Replicates how packages/services/Telephony/NotificationMgr.java handles legacy voicemail - * notification. The notification will not be stackable because no information is available for - * individual voicemails. - */ - @TargetApi(VERSION_CODES.O) - public void notifyLegacyVoicemail( - @NonNull PhoneAccountHandle phoneAccountHandle, - int count, - String voicemailNumber, - PendingIntent callVoicemailIntent, - PendingIntent voicemailSettingIntent, - boolean isRefresh) { - Assert.isNotNull(phoneAccountHandle); - Assert.checkArgument(BuildCompat.isAtLeastO()); - TelephonyManager telephonyManager = - context - .getSystemService(TelephonyManager.class) - .createForPhoneAccountHandle(phoneAccountHandle); - if (telephonyManager == null) { - LogUtil.e(TAG, "invalid PhoneAccountHandle, ignoring"); - return; - } - LogUtil.i(TAG, "Creating legacy voicemail notification"); - - PersistableBundle carrierConfig = telephonyManager.getCarrierConfig(); - - String notificationTitle = - context - .getResources() - .getQuantityString(R.plurals.notification_voicemail_title, count, count); - - TelecomManager telecomManager = context.getSystemService(TelecomManager.class); - PhoneAccount phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle); - - String notificationText; - PendingIntent pendingIntent; - - if (voicemailSettingIntent != null) { - // If the voicemail number if unknown, instead of calling voicemail, take the user - // to the voicemail settings. - notificationText = context.getString(R.string.notification_voicemail_no_vm_number); - pendingIntent = voicemailSettingIntent; - } else { - if (PhoneAccountUtils.getSubscriptionPhoneAccounts(context).size() > 1) { - notificationText = phoneAccount.getShortDescription().toString(); - } else { - notificationText = - String.format( - context.getString(R.string.notification_voicemail_text_format), - PhoneNumberUtils.formatNumber(voicemailNumber)); - } - pendingIntent = callVoicemailIntent; - } - Notification.Builder builder = new Notification.Builder(context); - builder - .setSmallIcon(android.R.drawable.stat_notify_voicemail) - .setColor(context.getColor(R.color.dialer_theme_color)) - .setWhen(System.currentTimeMillis()) - .setContentTitle(notificationTitle) - .setContentText(notificationText) - .setContentIntent(pendingIntent) - .setSound(telephonyManager.getVoicemailRingtoneUri(phoneAccountHandle)) - .setOngoing( - carrierConfig.getBoolean( - CarrierConfigManager.KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL)) - .setOnlyAlertOnce(isRefresh); - - if (telephonyManager.isVoicemailVibrationEnabled(phoneAccountHandle)) { - builder.setDefaults(Notification.DEFAULT_VIBRATE); - } - - NotificationChannelManager.applyChannel( - builder, context, Channel.VOICEMAIL, phoneAccountHandle); - Notification notification = builder.build(); - getNotificationManager() - .notify(LEGACY_VOICEMAIL_NOTIFICATION_TAG, LEGACY_VOICEMAIL_NOTIFICATION_ID, notification); - } - - public void cancelLegacyNotification() { - LogUtil.i(TAG, "Clearing legacy voicemail notification"); - getNotificationManager() - .cancel(LEGACY_VOICEMAIL_NOTIFICATION_TAG, LEGACY_VOICEMAIL_NOTIFICATION_ID); - } - - /** - * Determines which ringtone Uri and Notification defaults to use when updating the notification - * for the given call. - */ - private Pair getNotificationInfo(@Nullable NewCall callToNotify) { - LogUtil.v(TAG, "getNotificationInfo"); - if (callToNotify == null) { - LogUtil.i(TAG, "callToNotify == null"); - return new Pair<>(null, 0); - } - PhoneAccountHandle accountHandle = PhoneAccountHandles.getAccount(context, callToNotify); - if (accountHandle == null) { - LogUtil.i(TAG, "No default phone account found, using default notification ringtone"); - return new Pair<>(null, Notification.DEFAULT_ALL); - } - return new Pair<>( - TelephonyManagerCompat.getVoicemailRingtoneUri(getTelephonyManager(), accountHandle), - getNotificationDefaults(accountHandle)); - } - - private int getNotificationDefaults(PhoneAccountHandle accountHandle) { - if (VERSION.SDK_INT >= VERSION_CODES.N) { - return TelephonyManagerCompat.isVoicemailVibrationEnabled( - getTelephonyManager(), accountHandle) - ? Notification.DEFAULT_VIBRATE - : 0; - } - return Notification.DEFAULT_ALL; - } - - /** Creates a pending intent that marks all new voicemails as old. */ - private PendingIntent createMarkNewVoicemailsAsOldIntent(@Nullable Uri voicemailUri) { - Intent intent = new Intent(context, CallLogNotificationsService.class); - intent.setAction(CallLogNotificationsService.ACTION_MARK_NEW_VOICEMAILS_AS_OLD); - intent.setData(voicemailUri); - return PendingIntent.getService(context, 0, intent, 0); - } - - private NotificationManager getNotificationManager() { - return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - } - - private TelephonyManager getTelephonyManager() { - return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - } - - private Notification createNotificationForVoicemail( - @NonNull NewCall voicemail, @NonNull Map contactInfos) { - Pair notificationInfo = getNotificationInfo(voicemail); - ContactInfo contactInfo = contactInfos.get(voicemail.number); - - Notification.Builder notificationBuilder = - createNotificationBuilder() - .setContentTitle( - context - .getResources() - .getQuantityString(R.plurals.notification_voicemail_title, 1, 1)) - .setContentText( - ContactDisplayUtils.getTtsSpannedPhoneNumber( - context.getResources(), - R.string.notification_new_voicemail_ticker, - contactInfo.name)) - .setWhen(voicemail.dateMs) - .setSound(notificationInfo.first) - .setDefaults(notificationInfo.second); - - if (voicemail.voicemailUri != null) { - notificationBuilder.setDeleteIntent( - createMarkNewVoicemailsAsOldIntent(voicemail.voicemailUri)); - } - - NotificationChannelManager.applyChannel( - notificationBuilder, - context, - Channel.VOICEMAIL, - PhoneAccountHandles.getAccount(context, voicemail)); - - ContactPhotoLoader loader = new ContactPhotoLoader(context, contactInfo); - Bitmap photoIcon = loader.loadPhotoIcon(); - if (photoIcon != null) { - notificationBuilder.setLargeIcon(photoIcon); - } - if (!TextUtils.isEmpty(voicemail.transcription)) { - Logger.get(context) - .logImpression(DialerImpression.Type.VVM_NOTIFICATION_CREATED_WITH_TRANSCRIPTION); - notificationBuilder.setStyle( - new Notification.BigTextStyle().bigText(voicemail.transcription)); - } - notificationBuilder.setContentIntent(newVoicemailIntent(voicemail)); - Logger.get(context).logImpression(DialerImpression.Type.VVM_NOTIFICATION_CREATED); - return notificationBuilder.build(); - } - - private Notification.Builder createNotificationBuilder() { - return new Notification.Builder(context) - .setSmallIcon(android.R.drawable.stat_notify_voicemail) - .setColor(context.getColor(R.color.dialer_theme_color)) - .setGroup(VISUAL_VOICEMAIL_NOTIFICATION_TAG) - .setOnlyAlertOnce(true) - .setAutoCancel(true); - } - - private PendingIntent newVoicemailIntent(@Nullable NewCall voicemail) { - Intent intent = - DialtactsActivity.getShowTabIntent(context, DialtactsPagerAdapter.TAB_INDEX_VOICEMAIL); - // TODO (b/35486204): scroll to this voicemail - if (voicemail != null) { - intent.setData(voicemail.voicemailUri); - } - intent.putExtra(DialtactsActivity.EXTRA_CLEAR_NEW_VOICEMAILS, true); - return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } - - /** - * Updates the voicemail notifications displayed. - * - * @param runnable Called when the async update task completes no matter if it succeeds or fails. - * May be null. - */ - static void updateVoicemailNotifications(Context context, Runnable runnable) { - if (!TelecomUtil.isDefaultDialer(context)) { - LogUtil.i( - "DefaultVoicemailNotifier.updateVoicemailNotifications", - "not default dialer, not scheduling update to voicemail notifications"); - return; - } - - DialerExecutors.createNonUiTaskBuilder(new DefaultVoicemailNotifier(context)) - .onSuccess( - output -> { - LogUtil.i( - "DefaultVoicemailNotifier.updateVoicemailNotifications", - "update voicemail notifications successful"); - if (runnable != null) { - runnable.run(); - } - }) - .onFailure( - throwable -> { - LogUtil.i( - "DefaultVoicemailNotifier.updateVoicemailNotifications", - "update voicemail notifications failed"); - if (runnable != null) { - runnable.run(); - } - }) - .build() - .executeParallel(null); - } -} diff --git a/java/com/android/dialer/app/calllog/DialerQuickContactBadge.java b/java/com/android/dialer/app/calllog/DialerQuickContactBadge.java new file mode 100644 index 000000000..a3aac41fa --- /dev/null +++ b/java/com/android/dialer/app/calllog/DialerQuickContactBadge.java @@ -0,0 +1,63 @@ +/* + * 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.app.calllog; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.QuickContactBadge; +import com.android.dialer.app.calllog.CallLogAdapter.OnActionModeStateChangedListener; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; + +/** Allows us to click the contact badge for non multi select mode. */ +class DialerQuickContactBadge extends QuickContactBadge { + + private View.OnClickListener mExtraOnClickListener; + private OnActionModeStateChangedListener onActionModeStateChangeListener; + + public DialerQuickContactBadge(Context context) { + super(context); + } + + public DialerQuickContactBadge(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public DialerQuickContactBadge(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void onClick(View v) { + if (mExtraOnClickListener != null + && onActionModeStateChangeListener.isActionModeStateEnabled()) { + Logger.get(v.getContext()) + .logImpression(DialerImpression.Type.MULTISELECT_SINGLE_PRESS_TAP_VIA_CONTACT_BADGE); + mExtraOnClickListener.onClick(v); + } else { + super.onClick(v); + } + } + + public void setMulitSelectListeners( + View.OnClickListener extraOnClickListener, + OnActionModeStateChangedListener actionModeStateChangeListener) { + mExtraOnClickListener = extraOnClickListener; + onActionModeStateChangeListener = actionModeStateChangeListener; + } +} diff --git a/java/com/android/dialer/app/calllog/IntentProvider.java b/java/com/android/dialer/app/calllog/IntentProvider.java index 9c3c18b60..e1ec9f509 100644 --- a/java/com/android/dialer/app/calllog/IntentProvider.java +++ b/java/com/android/dialer/app/calllog/IntentProvider.java @@ -117,11 +117,12 @@ public abstract class IntentProvider { * @return The call details intent provider. */ public static IntentProvider getCallDetailIntentProvider( - CallDetailsEntries callDetailsEntries, DialerContact contact) { + CallDetailsEntries callDetailsEntries, DialerContact contact, boolean canReportCallerId) { return new IntentProvider() { @Override public Intent getIntent(Context context) { - return CallDetailsActivity.newInstance(context, callDetailsEntries, contact); + return CallDetailsActivity.newInstance( + context, callDetailsEntries, contact, canReportCallerId); } }; } diff --git a/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java b/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java new file mode 100644 index 000000000..428c71677 --- /dev/null +++ b/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java @@ -0,0 +1,156 @@ +/* + * 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.app.calllog; + +import android.annotation.TargetApi; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.os.Build.VERSION_CODES; +import android.support.annotation.NonNull; +import android.support.v4.os.BuildCompat; +import android.telecom.PhoneAccount; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; +import android.telephony.CarrierConfigManager; +import android.telephony.PhoneNumberUtils; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import com.android.dialer.app.R; +import com.android.dialer.calllogutils.PhoneAccountUtils; +import com.android.dialer.common.Assert; +import com.android.dialer.common.LogUtil; +import com.android.dialer.notification.NotificationChannelManager; + +/** Shows a notification in the status bar for legacy vociemail. */ +@TargetApi(VERSION_CODES.O) +public final class LegacyVoicemailNotifier { + private static final String NOTIFICATION_TAG = "LegacyVoicemail"; + private static final int NOTIFICATION_ID = 1; + + /** + * Replicates how packages/services/Telephony/NotificationMgr.java handles legacy voicemail + * notification. The notification will not be stackable because no information is available for + * individual voicemails. + */ + public static void showNotification( + @NonNull Context context, + @NonNull PhoneAccountHandle handle, + int count, + String voicemailNumber, + PendingIntent callVoicemailIntent, + PendingIntent voicemailSettingsIntent, + boolean isRefresh) { + LogUtil.enterBlock("LegacyVoicemailNotifier.showNotification"); + Assert.isNotNull(handle); + Assert.checkArgument(BuildCompat.isAtLeastO()); + + TelephonyManager pinnedTelephonyManager = + context.getSystemService(TelephonyManager.class).createForPhoneAccountHandle(handle); + if (pinnedTelephonyManager == null) { + LogUtil.e("LegacyVoicemailNotifier.showNotification", "invalid PhoneAccountHandle"); + return; + } + + Notification notification = + createNotification( + context, + pinnedTelephonyManager, + handle, + count, + voicemailNumber, + callVoicemailIntent, + voicemailSettingsIntent, + isRefresh); + context + .getSystemService(NotificationManager.class) + .notify(NOTIFICATION_TAG, NOTIFICATION_ID, notification); + } + + @NonNull + private static Notification createNotification( + @NonNull Context context, + @NonNull TelephonyManager pinnedTelephonyManager, + @NonNull PhoneAccountHandle handle, + int count, + String voicemailNumber, + PendingIntent callVoicemailIntent, + PendingIntent voicemailSettingsIntent, + boolean isRefresh) { + String notificationTitle = + context + .getResources() + .getQuantityString(R.plurals.notification_voicemail_title, count, count); + boolean isOngoing = + pinnedTelephonyManager + .getCarrierConfig() + .getBoolean(CarrierConfigManager.KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL); + + String contentText; + PendingIntent contentIntent; + if (!TextUtils.isEmpty(voicemailNumber) && callVoicemailIntent != null) { + contentText = getNotificationText(context, handle, voicemailNumber); + contentIntent = callVoicemailIntent; + } else { + contentText = context.getString(R.string.notification_voicemail_no_vm_number); + contentIntent = voicemailSettingsIntent; + } + + Notification.Builder builder = + new Notification.Builder(context) + .setSmallIcon(android.R.drawable.stat_notify_voicemail) + .setColor(context.getColor(R.color.dialer_theme_color)) + .setWhen(System.currentTimeMillis()) + .setContentTitle(notificationTitle) + .setContentText(contentText) + .setContentIntent(contentIntent) + .setSound(pinnedTelephonyManager.getVoicemailRingtoneUri(handle)) + .setOngoing(isOngoing) + .setOnlyAlertOnce(isRefresh) + .setChannelId(NotificationChannelManager.getVoicemailChannelId(context, handle)); + + if (pinnedTelephonyManager.isVoicemailVibrationEnabled(handle)) { + builder.setDefaults(Notification.DEFAULT_VIBRATE); + } + + return builder.build(); + } + + @NonNull + private static String getNotificationText( + @NonNull Context context, PhoneAccountHandle handle, String voicemailNumber) { + if (PhoneAccountUtils.getSubscriptionPhoneAccounts(context).size() > 1) { + TelecomManager telecomManager = context.getSystemService(TelecomManager.class); + PhoneAccount phoneAccount = telecomManager.getPhoneAccount(handle); + return phoneAccount.getShortDescription().toString(); + } else { + return String.format( + context.getString(R.string.notification_voicemail_text_format), + PhoneNumberUtils.formatNumber(voicemailNumber)); + } + } + + public static void cancelNotification(@NonNull Context context) { + LogUtil.enterBlock("LegacyVoicemailNotifier.cancelNotification"); + Assert.checkArgument(BuildCompat.isAtLeastO()); + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + notificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID); + } + + private LegacyVoicemailNotifier() {} +} diff --git a/java/com/android/dialer/app/calllog/MissedCallNotifier.java b/java/com/android/dialer/app/calllog/MissedCallNotifier.java index dd13298bc..e0e3fdf3f 100644 --- a/java/com/android/dialer/app/calllog/MissedCallNotifier.java +++ b/java/com/android/dialer/app/calllog/MissedCallNotifier.java @@ -30,11 +30,13 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.annotation.WorkerThread; +import android.support.v4.os.BuildCompat; import android.support.v4.os.UserManagerCompat; import android.support.v4.util.Pair; import android.text.BidiFormatter; import android.text.TextDirectionHeuristics; import android.text.TextUtils; +import android.util.ArraySet; import com.android.contacts.common.ContactsUtils; import com.android.contacts.common.compat.PhoneNumberUtilsCompat; import com.android.dialer.app.DialtactsActivity; @@ -46,23 +48,20 @@ import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.DialerExecutor.Worker; -import com.android.dialer.notification.NotificationChannelManager; -import com.android.dialer.notification.NotificationChannelManager.Channel; +import com.android.dialer.notification.NotificationChannelId; import com.android.dialer.phonenumbercache.ContactInfo; import com.android.dialer.phonenumberutil.PhoneNumberHelper; import com.android.dialer.util.DialerUtils; import com.android.dialer.util.IntentUtil; -import java.util.HashSet; import java.util.List; import java.util.Set; /** Creates a notification for calls that the user missed (neither answered nor rejected). */ public class MissedCallNotifier implements Worker, Void> { - /** The tag used to identify notifications from this class. */ - static final String NOTIFICATION_TAG = "MissedCallNotifier"; - /** The identifier of the notification of new missed calls. */ - private static final int NOTIFICATION_ID = R.id.notification_missed_call; + static final String NOTIFICATION_TAG_PREFIX = "MissedCall_"; + static final String NOTIFICATION_GROUP = "MissedCall"; + private static final int NOTIFICATION_ID = 1; private final Context context; private final CallLogNotificationsQueryHelper callLogNotificationsQueryHelper; @@ -104,7 +103,8 @@ public class MissedCallNotifier implements Worker, Void> { if ((newCalls != null && newCalls.isEmpty()) || count == 0) { // No calls to notify about: clear the notification. - CallLogNotificationsQueryHelper.removeMissedCallNotifications(context, null); + CallLogNotificationsQueryHelper.markAllMissedCallsInCallLogAsRead(context); + cancelAllMissedCallNotifications(context); return; } @@ -146,7 +146,7 @@ public class MissedCallNotifier implements Worker, Void> { null, System.currentTimeMillis()); - //TODO: look up caller ID that is not in contacts. + // TODO: look up caller ID that is not in contacts. ContactInfo contactInfo = callLogNotificationsQueryHelper.getContactInfo( call.number, call.numberPresentation, call.countryIso); @@ -181,36 +181,39 @@ public class MissedCallNotifier implements Worker, Void> { publicSummaryBuilder .setContentTitle(context.getText(titleResId)) .setContentIntent(createCallLogPendingIntent()) - .setDeleteIntent(createClearMissedCallsPendingIntent(null)); + .setDeleteIntent( + CallLogNotificationsService.createCancelAllMissedCallsPendingIntent(context)); // Create the notification summary suitable for display when sensitive information is showing. groupSummary .setContentTitle(context.getText(titleResId)) .setContentText(expandedText) .setContentIntent(createCallLogPendingIntent()) - .setDeleteIntent(createClearMissedCallsPendingIntent(null)) + .setDeleteIntent( + CallLogNotificationsService.createCancelAllMissedCallsPendingIntent(context)) .setGroupSummary(useCallList) .setOnlyAlertOnce(useCallList) .setPublicVersion(publicSummaryBuilder.build()); - - NotificationChannelManager.applyChannel(groupSummary, context, Channel.MISSED_CALL, null); + if (BuildCompat.isAtLeastO()) { + groupSummary.setChannelId(NotificationChannelId.MISSED_CALL); + } Notification notification = groupSummary.build(); configureLedOnNotification(notification); LogUtil.i("MissedCallNotifier.updateMissedCallNotification", "adding missed call notification"); - getNotificationMgr().notify(NOTIFICATION_TAG, NOTIFICATION_ID, notification); + getNotificationMgr().notify(getNotificationTagForGroupSummary(), NOTIFICATION_ID, notification); if (useCallList) { // Do not repost active notifications to prevent erasing post call notes. NotificationManager manager = getNotificationMgr(); - Set activeTags = new HashSet<>(); + Set activeTags = new ArraySet<>(); for (StatusBarNotification activeNotification : manager.getActiveNotifications()) { activeTags.add(activeNotification.getTag()); } for (NewCall call : newCalls) { - String callTag = call.callsUri.toString(); + String callTag = getNotificationTagForCall(call); if (!activeTags.contains(callTag)) { manager.notify(callTag, NOTIFICATION_ID, getNotificationForCall(call, null)); } @@ -218,6 +221,59 @@ public class MissedCallNotifier implements Worker, Void> { } } + public static void cancelAllMissedCallNotifications(@NonNull Context context) { + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + for (StatusBarNotification notification : notificationManager.getActiveNotifications()) { + String tag = notification.getTag(); + if (tag != null && tag.startsWith(NOTIFICATION_TAG_PREFIX)) { + notificationManager.cancel(tag, notification.getId()); + } + } + } + + public static void cancelSingleMissedCallNotification( + @NonNull Context context, @Nullable Uri callUri) { + if (callUri == null) { + LogUtil.e( + "MissedCallNotifier.cancelSingleMissedCallNotification", + "unable to cancel notification, uri is null"); + return; + } + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + String callTag = getNotificationTagForCallUri(callUri); + String summaryTag = getNotificationTagForGroupSummary(); + int notificationCount = 0; + + for (StatusBarNotification notification : notificationManager.getActiveNotifications()) { + String currentTag = notification.getTag(); + if (currentTag == null) { + continue; + } + if (currentTag.equals(callTag)) { + notificationManager.cancel(notification.getTag(), notification.getId()); + } else if (currentTag.startsWith(NOTIFICATION_TAG_PREFIX) && !currentTag.equals(summaryTag)) { + notificationCount++; + } + } + + if (notificationCount == 0) { + // There are no more missed call notifications. Remove the summary notification too. + notificationManager.cancel(summaryTag, NOTIFICATION_ID); + } + } + + private static String getNotificationTagForGroupSummary() { + return NOTIFICATION_TAG_PREFIX + "GroupSummary"; + } + + private static String getNotificationTagForCall(@NonNull NewCall call) { + return getNotificationTagForCallUri(call.callsUri); + } + + private static String getNotificationTagForCallUri(@NonNull Uri callUri) { + return NOTIFICATION_TAG_PREFIX + callUri; + } + public void insertPostCallNotification(@NonNull String number, @NonNull String note) { List newCalls = callLogNotificationsQueryHelper.getNewMissedCalls(); if (newCalls != null && !newCalls.isEmpty()) { @@ -226,7 +282,9 @@ public class MissedCallNotifier implements Worker, Void> { // Update the first notification that matches our post call note sender. getNotificationMgr() .notify( - call.callsUri.toString(), NOTIFICATION_ID, getNotificationForCall(call, note)); + getNotificationTagForCall(call), + NOTIFICATION_ID, + getNotificationForCall(call, note)); break; } } @@ -308,7 +366,7 @@ public class MissedCallNotifier implements Worker, Void> { private Notification.Builder createNotificationBuilder() { return new Notification.Builder(context) - .setGroup(NOTIFICATION_TAG) + .setGroup(NOTIFICATION_GROUP) .setSmallIcon(android.R.drawable.stat_notify_missed_call) .setColor(context.getResources().getColor(R.color.dialer_theme_color, null)) .setAutoCancel(true) @@ -321,10 +379,14 @@ public class MissedCallNotifier implements Worker, Void> { Builder builder = createNotificationBuilder() .setWhen(call.dateMs) - .setDeleteIntent(createClearMissedCallsPendingIntent(call.callsUri)) + .setDeleteIntent( + CallLogNotificationsService.createCancelSingleMissedCallPendingIntent( + context, call.callsUri)) .setContentIntent(createCallLogPendingIntent(call.callsUri)); + if (BuildCompat.isAtLeastO()) { + builder.setChannelId(NotificationChannelId.MISSED_CALL); + } - NotificationChannelManager.applyChannel(builder, context, Channel.MISSED_CALL, null); return builder; } @@ -332,7 +394,8 @@ public class MissedCallNotifier implements Worker, Void> { @WorkerThread public void callBackFromMissedCall(String number, Uri callUri) { closeSystemDialogs(context); - CallLogNotificationsQueryHelper.removeMissedCallNotifications(context, callUri); + CallLogNotificationsQueryHelper.markSingleMissedCallInCallLogAsRead(context, callUri); + cancelSingleMissedCallNotification(context, callUri); DialerUtils.startActivityWithErrorToast( context, new CallIntentBuilder(number, CallInitiationType.Type.MISSED_CALL_NOTIFICATION) @@ -343,7 +406,8 @@ public class MissedCallNotifier implements Worker, Void> { /** Trigger an intent to send an sms from a missed call number. */ public void sendSmsFromMissedCall(String number, Uri callUri) { closeSystemDialogs(context); - CallLogNotificationsQueryHelper.removeMissedCallNotifications(context, callUri); + CallLogNotificationsQueryHelper.markSingleMissedCallInCallLogAsRead(context, callUri); + cancelSingleMissedCallNotification(context, callUri); DialerUtils.startActivityWithErrorToast( context, IntentUtil.getSendSmsIntent(number).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } @@ -371,14 +435,6 @@ public class MissedCallNotifier implements Worker, Void> { return PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT); } - /** Creates a pending intent that marks all new missed calls as old. */ - private PendingIntent createClearMissedCallsPendingIntent(@Nullable Uri callUri) { - Intent intent = new Intent(context, CallLogNotificationsService.class); - intent.setAction(CallLogNotificationsService.ACTION_MARK_NEW_MISSED_CALLS_AS_OLD); - intent.setData(callUri); - return PendingIntent.getService(context, 0, intent, 0); - } - private PendingIntent createCallBackPendingIntent(String number, @NonNull Uri callUri) { Intent intent = new Intent(context, CallLogNotificationsService.class); intent.setAction(CallLogNotificationsService.ACTION_CALL_BACK_FROM_MISSED_CALL_NOTIFICATION); diff --git a/java/com/android/dialer/app/calllog/PhoneAccountHandles.java b/java/com/android/dialer/app/calllog/PhoneAccountHandles.java deleted file mode 100644 index acffffb1d..000000000 --- a/java/com/android/dialer/app/calllog/PhoneAccountHandles.java +++ /dev/null @@ -1,62 +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.app.calllog; - -import android.content.ComponentName; -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.telecom.PhoneAccount; -import android.telecom.PhoneAccountHandle; -import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; -import com.android.dialer.common.LogUtil; -import com.android.dialer.telecom.TelecomUtil; -import java.util.List; - -/** Methods to help extract {@link PhoneAccount} information from database and Telecomm sources. */ -class PhoneAccountHandles { - - @Nullable - public static PhoneAccountHandle getAccount(@NonNull Context context, @Nullable NewCall call) { - PhoneAccountHandle handle; - if (call == null || call.accountComponentName == null || call.accountId == null) { - LogUtil.v( - "PhoneAccountUtils.getAccount", - "accountComponentName == null || callToNotify.accountId == null"); - handle = TelecomUtil.getDefaultOutgoingPhoneAccount(context, PhoneAccount.SCHEME_TEL); - if (handle == null) { - List callCapablePhoneAccounts = - TelecomUtil.getCallCapablePhoneAccounts(context); - if (!callCapablePhoneAccounts.isEmpty()) { - return callCapablePhoneAccounts.get(0); - } - return null; - } - } else { - handle = - new PhoneAccountHandle( - ComponentName.unflattenFromString(call.accountComponentName), call.accountId); - } - if (handle.getComponentName() != null) { - LogUtil.v( - "PhoneAccountUtils.getAccount", - "PhoneAccountHandle.ComponentInfo:" + handle.getComponentName()); - } else { - LogUtil.i("PhoneAccountUtils.getAccount", "PhoneAccountHandle.ComponentInfo: null"); - } - return handle; - } -} diff --git a/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java b/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java new file mode 100644 index 000000000..99fe466d8 --- /dev/null +++ b/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java @@ -0,0 +1,291 @@ +/* + * 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.app.calllog; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.service.notification.StatusBarNotification; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.os.BuildCompat; +import android.telecom.PhoneAccount; +import android.telecom.PhoneAccountHandle; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import com.android.contacts.common.util.ContactDisplayUtils; +import com.android.dialer.app.DialtactsActivity; +import com.android.dialer.app.R; +import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; +import com.android.dialer.app.contactinfo.ContactPhotoLoader; +import com.android.dialer.app.list.DialtactsPagerAdapter; +import com.android.dialer.common.LogUtil; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; +import com.android.dialer.notification.NotificationChannelManager; +import com.android.dialer.phonenumbercache.ContactInfo; +import com.android.dialer.telecom.TelecomUtil; +import java.util.List; +import java.util.Map; + +/** Shows a notification in the status bar for visual voicemail. */ +final class VisualVoicemailNotifier { + private static final String NOTIFICATION_TAG_PREFIX = "VisualVoicemail_"; + private static final String NOTIFICATION_GROUP = "VisualVoicemail"; + private static final int NOTIFICATION_ID = 1; + + public static void showNotifications( + @NonNull Context context, + @NonNull List newCalls, + @NonNull Map contactInfos, + @Nullable String callers) { + LogUtil.enterBlock("VisualVoicemailNotifier.showNotifications"); + PendingIntent deleteIntent = + CallLogNotificationsService.createMarkAllNewVoicemailsAsOldIntent(context); + String contentTitle = + context + .getResources() + .getQuantityString( + R.plurals.notification_voicemail_title, newCalls.size(), newCalls.size()); + Notification.Builder groupSummary = + createNotificationBuilder(context) + .setContentTitle(contentTitle) + .setContentText(callers) + .setDeleteIntent(deleteIntent) + .setGroupSummary(true) + .setContentIntent(newVoicemailIntent(context, null)); + + if (BuildCompat.isAtLeastO()) { + groupSummary.setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN); + PhoneAccountHandle handle = getAccountForCall(context, newCalls.get(0)); + groupSummary.setChannelId(NotificationChannelManager.getVoicemailChannelId(context, handle)); + } + + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + notificationManager.notify( + getNotificationTagForGroupSummary(), NOTIFICATION_ID, groupSummary.build()); + + for (NewCall voicemail : newCalls) { + notificationManager.notify( + getNotificationTagForVoicemail(voicemail), + NOTIFICATION_ID, + createNotificationForVoicemail(context, voicemail, contactInfos)); + } + } + + public static void cancelAllVoicemailNotifications(@NonNull Context context) { + LogUtil.enterBlock("VisualVoicemailNotifier.cancelAllVoicemailNotifications"); + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + for (StatusBarNotification notification : notificationManager.getActiveNotifications()) { + String tag = notification.getTag(); + if (tag != null && tag.startsWith(NOTIFICATION_TAG_PREFIX)) { + notificationManager.cancel(tag, notification.getId()); + } + } + } + + public static void cancelSingleVoicemailNotification( + @NonNull Context context, @Nullable Uri voicemailUri) { + LogUtil.enterBlock("VisualVoicemailNotifier.cancelSingleVoicemailNotification"); + if (voicemailUri == null) { + LogUtil.e("VisualVoicemailNotifier.cancelSingleVoicemailNotification", "uri is null"); + return; + } + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + String voicemailTag = getNotificationTagForUri(voicemailUri); + String summaryTag = getNotificationTagForGroupSummary(); + int notificationCount = 0; + + for (StatusBarNotification notification : notificationManager.getActiveNotifications()) { + String currentTag = notification.getTag(); + if (currentTag == null) { + continue; + } + if (currentTag.equals(voicemailTag)) { + notificationManager.cancel(notification.getTag(), notification.getId()); + } else if (currentTag.startsWith(NOTIFICATION_TAG_PREFIX) && !currentTag.equals(summaryTag)) { + notificationCount++; + } + } + + if (notificationCount == 0) { + // There are no more visual voicemail notifications. Remove the summary notification too. + notificationManager.cancel(summaryTag, NOTIFICATION_ID); + } + } + + private static String getNotificationTagForVoicemail(@NonNull NewCall voicemail) { + return getNotificationTagForUri(voicemail.voicemailUri); + } + + private static String getNotificationTagForUri(@NonNull Uri voicemailUri) { + return NOTIFICATION_TAG_PREFIX + voicemailUri; + } + + private static String getNotificationTagForGroupSummary() { + return NOTIFICATION_TAG_PREFIX + "GroupSummary"; + } + + private static Notification.Builder createNotificationBuilder(@NonNull Context context) { + return new Notification.Builder(context) + .setSmallIcon(android.R.drawable.stat_notify_voicemail) + .setColor(context.getColor(R.color.dialer_theme_color)) + .setGroup(NOTIFICATION_GROUP) + .setOnlyAlertOnce(true) + .setAutoCancel(true); + } + + private static Notification createNotificationForVoicemail( + @NonNull Context context, + @NonNull NewCall voicemail, + @NonNull Map contactInfos) { + PhoneAccountHandle handle = getAccountForCall(context, voicemail); + ContactInfo contactInfo = contactInfos.get(voicemail.number); + + Notification.Builder builder = + createNotificationBuilder(context) + .setContentTitle( + context + .getResources() + .getQuantityString(R.plurals.notification_voicemail_title, 1, 1)) + .setContentText( + ContactDisplayUtils.getTtsSpannedPhoneNumber( + context.getResources(), + R.string.notification_new_voicemail_ticker, + contactInfo.name)) + .setWhen(voicemail.dateMs) + .setSound(getVoicemailRingtoneUri(context, handle)) + .setDefaults(getNotificationDefaultFlags(context, handle)); + + if (voicemail.voicemailUri != null) { + builder.setDeleteIntent( + CallLogNotificationsService.createMarkSingleNewVoicemailAsOldIntent( + context, voicemail.voicemailUri)); + } + + if (BuildCompat.isAtLeastO()) { + builder.setChannelId(NotificationChannelManager.getVoicemailChannelId(context, handle)); + } + + ContactPhotoLoader loader = new ContactPhotoLoader(context, contactInfo); + Bitmap photoIcon = loader.loadPhotoIcon(); + if (photoIcon != null) { + builder.setLargeIcon(photoIcon); + } + if (!TextUtils.isEmpty(voicemail.transcription)) { + Logger.get(context) + .logImpression(DialerImpression.Type.VVM_NOTIFICATION_CREATED_WITH_TRANSCRIPTION); + builder.setStyle(new Notification.BigTextStyle().bigText(voicemail.transcription)); + } + builder.setContentIntent(newVoicemailIntent(context, voicemail)); + Logger.get(context).logImpression(DialerImpression.Type.VVM_NOTIFICATION_CREATED); + return builder.build(); + } + + @Nullable + private static Uri getVoicemailRingtoneUri( + @NonNull Context context, @Nullable PhoneAccountHandle handle) { + if (VERSION.SDK_INT < VERSION_CODES.N) { + return null; + } + if (handle == null) { + LogUtil.i("VisualVoicemailNotifier.getVoicemailRingtoneUri", "null handle, getting fallback"); + handle = getFallbackAccount(context); + if (handle == null) { + LogUtil.i( + "VisualVoicemailNotifier.getVoicemailRingtoneUri", + "no fallback handle, using null (default) ringtone"); + return null; + } + } + return context.getSystemService(TelephonyManager.class).getVoicemailRingtoneUri(handle); + } + + private static int getNotificationDefaultFlags( + @NonNull Context context, @Nullable PhoneAccountHandle handle) { + if (VERSION.SDK_INT < VERSION_CODES.N) { + return Notification.DEFAULT_ALL; + } + if (handle == null) { + LogUtil.i( + "VisualVoicemailNotifier.getNotificationDefaultFlags", "null handle, getting fallback"); + handle = getFallbackAccount(context); + if (handle == null) { + LogUtil.i( + "VisualVoicemailNotifier.getNotificationDefaultFlags", + "no fallback handle, using default vibration"); + return Notification.DEFAULT_ALL; + } + } + if (context.getSystemService(TelephonyManager.class).isVoicemailVibrationEnabled(handle)) { + return Notification.DEFAULT_VIBRATE; + } + return 0; + } + + private static PendingIntent newVoicemailIntent( + @NonNull Context context, @Nullable NewCall voicemail) { + Intent intent = + DialtactsActivity.getShowTabIntent(context, DialtactsPagerAdapter.TAB_INDEX_VOICEMAIL); + // TODO (b/35486204): scroll to this voicemail + if (voicemail != null) { + intent.setData(voicemail.voicemailUri); + } + intent.putExtra(DialtactsActivity.EXTRA_CLEAR_NEW_VOICEMAILS, true); + return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + } + + /** + * Gets a phone account for the given call entry. This could be null if SIM associated with the + * entry is no longer in the device or for other reasons (for example, modem reboot). + */ + @Nullable + public static PhoneAccountHandle getAccountForCall( + @NonNull Context context, @Nullable NewCall call) { + if (call == null || call.accountComponentName == null || call.accountId == null) { + return null; + } + return new PhoneAccountHandle( + ComponentName.unflattenFromString(call.accountComponentName), call.accountId); + } + + /** + * Gets any available phone account that can be used to get sound settings for voicemail. This is + * only called if the phone account for the voicemail entry can't be found. + */ + @Nullable + public static PhoneAccountHandle getFallbackAccount(@NonNull Context context) { + PhoneAccountHandle handle = + TelecomUtil.getDefaultOutgoingPhoneAccount(context, PhoneAccount.SCHEME_TEL); + if (handle == null) { + List handles = TelecomUtil.getCallCapablePhoneAccounts(context); + if (!handles.isEmpty()) { + handle = handles.get(0); + } + } + return handle; + } + + private VisualVoicemailNotifier() {} +} diff --git a/java/com/android/dialer/app/calllog/VisualVoicemailUpdateTask.java b/java/com/android/dialer/app/calllog/VisualVoicemailUpdateTask.java new file mode 100644 index 000000000..d6601be36 --- /dev/null +++ b/java/com/android/dialer/app/calllog/VisualVoicemailUpdateTask.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2011 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.app.calllog; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.WorkerThread; +import android.text.TextUtils; +import android.util.ArrayMap; +import com.android.dialer.app.R; +import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; +import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; +import com.android.dialer.blocking.FilteredNumbersUtil; +import com.android.dialer.common.Assert; +import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.DialerExecutor.Worker; +import com.android.dialer.common.concurrent.DialerExecutors; +import com.android.dialer.phonenumbercache.ContactInfo; +import com.android.dialer.telecom.TelecomUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** Updates voicemail notifications in the background. */ +class VisualVoicemailUpdateTask implements Worker { + @Nullable + @Override + public Void doInBackground(@NonNull Input input) throws Throwable { + updateNotification(input.context, input.queryHelper, input.queryHandler); + return null; + } + + /** + * Updates the notification and notifies of the call with the given URI. + * + *

Clears the notification if there are no new voicemails, and notifies if the given URI + * corresponds to a new voicemail. + */ + @WorkerThread + private static void updateNotification( + Context context, + CallLogNotificationsQueryHelper queryHelper, + FilteredNumberAsyncQueryHandler queryHandler) { + Assert.isWorkerThread(); + + List newCalls = queryHelper.getNewVoicemails(); + if (newCalls == null) { + return; + } + newCalls = filterBlockedNumbers(context, queryHandler, newCalls); + if (newCalls.isEmpty()) { + return; + } + + // This represents a list of names to include in the notification. + String callers = null; + + // Maps each number into a name: if a number is in the map, it has already left a more + // recent voicemail. + Map contactInfos = new ArrayMap<>(); + for (NewCall newCall : newCalls) { + if (!contactInfos.containsKey(newCall.number)) { + ContactInfo contactInfo = + queryHelper.getContactInfo( + newCall.number, newCall.numberPresentation, newCall.countryIso); + contactInfos.put(newCall.number, contactInfo); + + // This is a new caller. Add it to the back of the list of callers. + if (TextUtils.isEmpty(callers)) { + callers = contactInfo.name; + } else { + callers = + context.getString( + R.string.notification_voicemail_callers_list, callers, contactInfo.name); + } + } + } + VisualVoicemailNotifier.showNotifications(context, newCalls, contactInfos, callers); + } + + @WorkerThread + private static List filterBlockedNumbers( + Context context, FilteredNumberAsyncQueryHandler queryHandler, List newCalls) { + Assert.isWorkerThread(); + if (FilteredNumbersUtil.hasRecentEmergencyCall(context)) { + LogUtil.i( + "VisualVoicemailUpdateTask.filterBlockedNumbers", + "not filtering due to recent emergency call"); + return newCalls; + } + + List result = new ArrayList<>(); + for (NewCall newCall : newCalls) { + if (queryHandler.getBlockedIdSynchronous(newCall.number, newCall.countryIso) != null) { + LogUtil.i( + "VisualVoicemailUpdateTask.filterBlockedNumbers", + "found voicemail from blocked number, deleting"); + if (newCall.voicemailUri != null) { + // Delete the voicemail. + CallLogAsyncTaskUtil.deleteVoicemailSynchronous(context, newCall.voicemailUri); + } + } else { + result.add(newCall); + } + } + return result; + } + + /** Updates the voicemail notifications displayed. */ + static void scheduleTask(@NonNull Context context, @NonNull Runnable callback) { + Assert.isNotNull(context); + Assert.isNotNull(callback); + if (!TelecomUtil.isDefaultDialer(context)) { + LogUtil.i("VisualVoicemailUpdateTask.scheduleTask", "not default dialer, not running"); + callback.run(); + return; + } + + Input input = + new Input( + context, + CallLogNotificationsQueryHelper.getInstance(context), + new FilteredNumberAsyncQueryHandler(context)); + DialerExecutors.createNonUiTaskBuilder(new VisualVoicemailUpdateTask()) + .onSuccess( + output -> { + LogUtil.i("VisualVoicemailUpdateTask.scheduleTask", "update successful"); + callback.run(); + }) + .onFailure( + throwable -> { + LogUtil.i("VisualVoicemailUpdateTask.scheduleTask", "update failed: " + throwable); + callback.run(); + }) + .build() + .executeParallel(input); + } + + static class Input { + @NonNull final Context context; + @NonNull final CallLogNotificationsQueryHelper queryHelper; + @NonNull final FilteredNumberAsyncQueryHandler queryHandler; + + Input( + Context context, + CallLogNotificationsQueryHelper queryHelper, + FilteredNumberAsyncQueryHandler queryHandler) { + this.context = context; + this.queryHelper = queryHelper; + this.queryHandler = queryHandler; + } + } +} diff --git a/java/com/android/dialer/app/calllog/VoicemailQueryHandler.java b/java/com/android/dialer/app/calllog/VoicemailQueryHandler.java index 777f4c79f..2fbebdd30 100644 --- a/java/com/android/dialer/app/calllog/VoicemailQueryHandler.java +++ b/java/com/android/dialer/app/calllog/VoicemailQueryHandler.java @@ -15,7 +15,6 @@ */ package com.android.dialer.app.calllog; -import android.app.NotificationManager; import android.content.AsyncQueryHandler; import android.content.ContentResolver; import android.content.ContentValues; @@ -23,30 +22,49 @@ import android.content.Context; import android.net.Uri; import android.provider.CallLog.Calls; import android.support.annotation.MainThread; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import com.android.dialer.app.R; +import android.support.annotation.WorkerThread; import com.android.dialer.common.Assert; -import com.android.dialer.notification.GroupedNotificationUtil; +import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.ThreadUtil; /** Handles asynchronous queries to the call log for voicemail. */ public class VoicemailQueryHandler extends AsyncQueryHandler { - private static final String TAG = "VoicemailQueryHandler"; - /** The token for the query to mark all new voicemails as old. */ private static final int UPDATE_MARK_VOICEMAILS_AS_OLD_TOKEN = 50; - private Context mContext; - @MainThread - public VoicemailQueryHandler(Context context, ContentResolver contentResolver) { + private VoicemailQueryHandler(ContentResolver contentResolver) { super(contentResolver); Assert.isMainThread(); - mContext = context; + } + + @WorkerThread + public static void markAllNewVoicemailsAsRead(final @NonNull Context context) { + ThreadUtil.postOnUiThread( + () -> { + new VoicemailQueryHandler(context.getContentResolver()).markNewVoicemailsAsOld(null); + }); + } + + @WorkerThread + public static void markSingleNewVoicemailAsRead( + final @NonNull Context context, final Uri voicemailUri) { + if (voicemailUri == null) { + LogUtil.e("VoicemailQueryHandler.markSingleNewVoicemailAsRead", "voicemail URI is null"); + return; + } + ThreadUtil.postOnUiThread( + () -> { + new VoicemailQueryHandler(context.getContentResolver()) + .markNewVoicemailsAsOld(voicemailUri); + }); } /** Updates all new voicemails to mark them as old. */ - public void markNewVoicemailsAsOld(@Nullable Uri voicemailUri) { + private void markNewVoicemailsAsOld(@Nullable Uri voicemailUri) { // Mark all "new" voicemails as not new anymore. StringBuilder where = new StringBuilder(); where.append(Calls.NEW); @@ -70,11 +88,5 @@ public class VoicemailQueryHandler extends AsyncQueryHandler { voicemailUri == null ? new String[] {Integer.toString(Calls.VOICEMAIL_TYPE)} : new String[] {Integer.toString(Calls.VOICEMAIL_TYPE), voicemailUri.toString()}); - - GroupedNotificationUtil.removeNotification( - mContext.getSystemService(NotificationManager.class), - voicemailUri != null ? voicemailUri.toString() : null, - R.id.notification_visual_voicemail, - DefaultVoicemailNotifier.VISUAL_VOICEMAIL_NOTIFICATION_TAG); } } diff --git a/java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java b/java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java index 039998780..f85680649 100644 --- a/java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java +++ b/java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java @@ -17,15 +17,11 @@ package com.android.dialer.app.calllog.calllogcache; import android.content.Context; -import android.support.annotation.VisibleForTesting; import android.telecom.PhoneAccountHandle; -import android.text.TextUtils; import android.util.ArrayMap; -import android.util.Pair; import com.android.dialer.calllogutils.PhoneAccountUtils; -import com.android.dialer.phonenumberutil.PhoneNumberHelper; +import com.android.dialer.telecom.TelecomUtil; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; /** * This is the CallLogCache for versions of dialer Lollipop Mr1 and above with support for multi-SIM @@ -36,15 +32,6 @@ import java.util.concurrent.ConcurrentHashMap; */ class CallLogCacheLollipopMr1 extends CallLogCache { - /* - * Maps from a phone-account/number pair to a boolean because multiple numbers could return true - * for the voicemail number if those numbers are not pre-normalized. Access must be synchronzied - * as it's used in the background thread in CallLogAdapter. {@see CallLogAdapter#loadData} - */ - @VisibleForTesting - final Map, Boolean> mVoicemailQueryCache = - new ConcurrentHashMap<>(); - private final Map mPhoneAccountLabelCache = new ArrayMap<>(); private final Map mPhoneAccountColorCache = new ArrayMap<>(); private final Map mPhoneAccountCallWithNoteCache = new ArrayMap<>(); @@ -55,7 +42,6 @@ class CallLogCacheLollipopMr1 extends CallLogCache { @Override public void reset() { - mVoicemailQueryCache.clear(); mPhoneAccountLabelCache.clear(); mPhoneAccountColorCache.clear(); mPhoneAccountCallWithNoteCache.clear(); @@ -65,19 +51,7 @@ class CallLogCacheLollipopMr1 extends CallLogCache { @Override public boolean isVoicemailNumber(PhoneAccountHandle accountHandle, CharSequence number) { - if (TextUtils.isEmpty(number)) { - return false; - } - - Pair key = new Pair<>(accountHandle, number); - Boolean value = mVoicemailQueryCache.get(key); - if (value != null) { - return value; - } - boolean isVoicemail = - PhoneNumberHelper.isVoicemailNumber(mContext, accountHandle, number.toString()); - mVoicemailQueryCache.put(key, isVoicemail); - return isVoicemail; + return TelecomUtil.isVoicemailNumber(mContext, accountHandle, number.toString()); } @Override diff --git a/java/com/android/dialer/app/contactinfo/ContactInfoCache.java b/java/com/android/dialer/app/contactinfo/ContactInfoCache.java index 32bbf06b5..82fc229af 100644 --- a/java/com/android/dialer/app/contactinfo/ContactInfoCache.java +++ b/java/com/android/dialer/app/contactinfo/ContactInfoCache.java @@ -162,7 +162,7 @@ public class ContactInfoCache { ContactInfo info; if (request.isLocalRequest()) { info = mContactInfoHelper.lookupNumber(request.number, request.countryIso); - if (!info.contactExists) { + if (info != null && !info.contactExists) { // TODO: Maybe skip look up if it's already available in cached number lookup // service. long start = SystemClock.elapsedRealtime(); diff --git a/java/com/android/dialer/app/dialpad/DialpadFragment.java b/java/com/android/dialer/app/dialpad/DialpadFragment.java index c0b26c91a..d33943773 100644 --- a/java/com/android/dialer/app/dialpad/DialpadFragment.java +++ b/java/com/android/dialer/app/dialpad/DialpadFragment.java @@ -85,7 +85,9 @@ import com.android.dialer.common.LogUtil; import com.android.dialer.dialpadview.DialpadKeyButton; import com.android.dialer.dialpadview.DialpadView; import com.android.dialer.location.GeoUtil; +import com.android.dialer.logging.UiAction; import com.android.dialer.oem.MotorolaUtils; +import com.android.dialer.performancereport.PerformanceReport; import com.android.dialer.proguard.UsedByReflection; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.CallUtil; @@ -1015,6 +1017,8 @@ public class DialpadFragment extends Fragment */ private void handleDialButtonPressed() { if (isDigitsEmpty()) { // No number entered. + // No real call made, so treat it as a click + PerformanceReport.recordClick(UiAction.Type.PRESS_CALL_BUTTON_WITHOUT_CALLING); handleDialButtonClickWithEmptyDigits(); } else { final String number = mDigits.getText().toString(); @@ -1025,6 +1029,7 @@ public class DialpadFragment extends Fragment if (number != null && !TextUtils.isEmpty(mProhibitedPhoneNumberRegexp) && number.matches(mProhibitedPhoneNumberRegexp)) { + PerformanceReport.recordClick(UiAction.Type.PRESS_CALL_BUTTON_WITHOUT_CALLING); LogUtil.i( "DialpadFragment.handleDialButtonPressed", "The phone number is prohibited explicitly by a rule."); @@ -1061,6 +1066,10 @@ public class DialpadFragment extends Fragment startActivity(newFlashIntent()); } else { if (!TextUtils.isEmpty(mLastNumberDialed)) { + // Dialpad will be filled with last called number, + // but we don't want to record it as user action + PerformanceReport.setIgnoreActionOnce(UiAction.Type.TEXT_CHANGE_WITH_INPUT); + // Recall the last number dialed. mDigits.setText(mLastNumberDialed); diff --git a/java/com/android/dialer/app/legacybindings/DialerLegacyBindings.java b/java/com/android/dialer/app/legacybindings/DialerLegacyBindings.java index c208fd57d..a483af9e9 100644 --- a/java/com/android/dialer/app/legacybindings/DialerLegacyBindings.java +++ b/java/com/android/dialer/app/legacybindings/DialerLegacyBindings.java @@ -41,6 +41,7 @@ public interface DialerLegacyBindings { ViewGroup alertContainer, CallLogAdapter.CallFetcher callFetcher, CallLogAdapter.MultiSelectRemoveView multiSelectRemoveView, + CallLogAdapter.OnActionModeStateChangedListener actionModeStateChangedListener, CallLogCache callLogCache, ContactInfoCache contactInfoCache, VoicemailPlaybackPresenter voicemailPlaybackPresenter, diff --git a/java/com/android/dialer/app/legacybindings/DialerLegacyBindingsStub.java b/java/com/android/dialer/app/legacybindings/DialerLegacyBindingsStub.java index 19fa1a70c..488fbad68 100644 --- a/java/com/android/dialer/app/legacybindings/DialerLegacyBindingsStub.java +++ b/java/com/android/dialer/app/legacybindings/DialerLegacyBindingsStub.java @@ -35,6 +35,7 @@ public class DialerLegacyBindingsStub implements DialerLegacyBindings { ViewGroup alertContainer, CallLogAdapter.CallFetcher callFetcher, CallLogAdapter.MultiSelectRemoveView multiSelectRemoveView, + CallLogAdapter.OnActionModeStateChangedListener actionModeStateChangedListener, CallLogCache callLogCache, ContactInfoCache contactInfoCache, VoicemailPlaybackPresenter voicemailPlaybackPresenter, @@ -45,6 +46,7 @@ public class DialerLegacyBindingsStub implements DialerLegacyBindings { alertContainer, callFetcher, multiSelectRemoveView, + actionModeStateChangedListener, callLogCache, contactInfoCache, voicemailPlaybackPresenter, diff --git a/java/com/android/dialer/app/list/AllContactsFragment.java b/java/com/android/dialer/app/list/AllContactsFragment.java index f5fdb9e2d..32a99e795 100644 --- a/java/com/android/dialer/app/list/AllContactsFragment.java +++ b/java/com/android/dialer/app/list/AllContactsFragment.java @@ -38,6 +38,7 @@ import com.android.contacts.common.list.ContactEntryListFragment; import com.android.contacts.common.list.ContactListFilter; import com.android.contacts.common.list.DefaultContactListAdapter; import com.android.dialer.app.R; +import com.android.dialer.common.LogUtil; import com.android.dialer.compat.CompatUtils; import com.android.dialer.logging.InteractionEvent; import com.android.dialer.logging.Logger; @@ -46,6 +47,7 @@ import com.android.dialer.util.IntentUtil; import com.android.dialer.util.PermissionsUtil; import com.android.dialer.widget.EmptyContentView; import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener; +import java.util.Arrays; /** Fragments to show all contacts with phone numbers. */ public class AllContactsFragment extends ContactEntryListFragment @@ -173,9 +175,15 @@ public class AllContactsFragment extends ContactEntryListFragment 0) { + LogUtil.i( + "AllContactsFragment.onEmptyViewActionButtonClicked", + "Requesting permissions: " + Arrays.toString(deniedPermissions)); FragmentCompat.requestPermissions( - this, new String[] {READ_CONTACTS}, READ_CONTACTS_PERMISSION_REQUEST_CODE); + this, deniedPermissions, READ_CONTACTS_PERMISSION_REQUEST_CODE); } else { // Add new contact DialerUtils.startActivityWithErrorToast( diff --git a/java/com/android/dialer/app/list/DialerPhoneNumberListAdapter.java b/java/com/android/dialer/app/list/DialerPhoneNumberListAdapter.java index 04927cf7a..fc0bd3ccf 100644 --- a/java/com/android/dialer/app/list/DialerPhoneNumberListAdapter.java +++ b/java/com/android/dialer/app/list/DialerPhoneNumberListAdapter.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.res.Resources; import android.database.Cursor; import android.graphics.drawable.Drawable; +import android.support.v4.content.ContextCompat; import android.telephony.PhoneNumberUtils; import android.text.BidiFormatter; import android.text.TextDirectionHeuristics; @@ -177,33 +178,33 @@ public class DialerPhoneNumberListAdapter extends PhoneNumberListAdapter { resources, R.string.search_shortcut_call_number, mBidiFormatter.unicodeWrap(number, TextDirectionHeuristics.LTR)); - drawable = getContext().getResources().getDrawable(R.drawable.quantum_ic_call_vd_theme_24); + drawable = ContextCompat.getDrawable(getContext(), R.drawable.quantum_ic_call_vd_theme_24); break; case SHORTCUT_CREATE_NEW_CONTACT: text = resources.getString(R.string.search_shortcut_create_new_contact); drawable = - getContext().getResources().getDrawable(R.drawable.quantum_ic_person_add_vd_theme_24); + ContextCompat.getDrawable(getContext(), R.drawable.quantum_ic_person_add_vd_theme_24); drawable.setAutoMirrored(true); break; case SHORTCUT_ADD_TO_EXISTING_CONTACT: text = resources.getString(R.string.search_shortcut_add_to_contact); drawable = - getContext().getResources().getDrawable(R.drawable.quantum_ic_person_add_vd_theme_24); + ContextCompat.getDrawable(getContext(), R.drawable.quantum_ic_person_add_vd_theme_24); break; case SHORTCUT_SEND_SMS_MESSAGE: text = resources.getString(R.string.search_shortcut_send_sms_message); drawable = - getContext().getResources().getDrawable(R.drawable.quantum_ic_message_vd_theme_24); + ContextCompat.getDrawable(getContext(), R.drawable.quantum_ic_message_vd_theme_24); break; case SHORTCUT_MAKE_VIDEO_CALL: text = resources.getString(R.string.search_shortcut_make_video_call); drawable = - getContext().getResources().getDrawable(R.drawable.quantum_ic_videocam_vd_theme_24); + ContextCompat.getDrawable(getContext(), R.drawable.quantum_ic_videocam_vd_theme_24); break; case SHORTCUT_BLOCK_NUMBER: text = resources.getString(R.string.search_shortcut_block_number); drawable = - getContext().getResources().getDrawable(R.drawable.ic_not_interested_googblue_24dp); + ContextCompat.getDrawable(getContext(), R.drawable.ic_not_interested_googblue_24dp); break; default: throw new IllegalArgumentException("Invalid shortcut type"); diff --git a/java/com/android/dialer/app/list/DialtactsPagerAdapter.java b/java/com/android/dialer/app/list/DialtactsPagerAdapter.java index dba3d3a93..822aa789f 100644 --- a/java/com/android/dialer/app/list/DialtactsPagerAdapter.java +++ b/java/com/android/dialer/app/list/DialtactsPagerAdapter.java @@ -28,8 +28,8 @@ import com.android.dialer.calllog.CallLogComponent; import com.android.dialer.calllog.CallLogFramework; import com.android.dialer.calllog.ui.NewCallLogFragment; import com.android.dialer.common.Assert; -import com.android.dialer.common.ConfigProviderBindings; import com.android.dialer.common.LogUtil; +import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.dialer.contactsfragment.ContactsFragment; import com.android.dialer.database.CallLogQueryHandler; import com.android.dialer.speeddial.SpeedDialFragment; @@ -78,7 +78,7 @@ public class DialtactsPagerAdapter extends FragmentPagerAdapter { CallLogFramework callLogFramework = CallLogComponent.get(context).callLogFramework(); useNewCallLogTab = callLogFramework.isNewCallLogEnabled(context); useNewContactsTab = - ConfigProviderBindings.get(context).getBoolean("enable_new_contacts_tab", false); + ConfigProviderBindings.get(context).getBoolean("enable_new_contacts_tab", true); this.tabTitles = tabTitles; hasActiveVoicemailProvider = hasVoicemailProvider; fragments.addAll(Collections.nCopies(TAB_COUNT_WITH_VOICEMAIL, null)); diff --git a/java/com/android/dialer/app/list/ListsFragment.java b/java/com/android/dialer/app/list/ListsFragment.java index 32501d556..3f03db1e8 100644 --- a/java/com/android/dialer/app/list/ListsFragment.java +++ b/java/com/android/dialer/app/list/ListsFragment.java @@ -34,15 +34,11 @@ import android.provider.VoicemailContract; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnClickListener; import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; import com.android.contacts.common.list.ViewPagerTabs; import com.android.dialer.app.R; import com.android.dialer.app.calllog.CallLogFragment; import com.android.dialer.app.calllog.CallLogNotificationsService; -import com.android.dialer.app.calllog.VisualVoicemailCallLogFragment; import com.android.dialer.app.voicemail.error.VoicemailStatusCorruptionHandler; import com.android.dialer.app.voicemail.error.VoicemailStatusCorruptionHandler.Source; import com.android.dialer.common.LogUtil; @@ -51,6 +47,8 @@ import com.android.dialer.database.CallLogQueryHandler.Listener; import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; import com.android.dialer.logging.ScreenEvent; +import com.android.dialer.logging.UiAction; +import com.android.dialer.performancereport.PerformanceReport; import com.android.dialer.speeddial.SpeedDialFragment; import com.android.dialer.util.PermissionsUtil; import com.android.dialer.voicemailstatus.VisualVoicemailEnabledChecker; @@ -64,22 +62,18 @@ import java.util.ArrayList; * Contacts list. This will also eventually contain the logic that allows sliding the ViewPager * containing the lists up above the search bar and pin it against the top of the screen. */ -public class ListsFragment extends Fragment - implements OnPageChangeListener, Listener, OnClickListener { +public class ListsFragment extends Fragment implements OnPageChangeListener, Listener { private static final String TAG = "ListsFragment"; + private DialerViewPager mViewPager; private ViewPagerTabs mViewPagerTabs; private DialtactsPagerAdapter mAdapter; private RemoveView mRemoveView; private View mRemoveViewContent; - private View mMultiSelectSelectAllViewContent; - private TextView mSelectUnselectAllViewText; - private ImageView mSelectUnselectAllIcon; private Fragment mCurrentPage; private SharedPreferences mPrefs; private boolean mHasFetchedVoicemailStatus; - private boolean selectAllMode; private boolean mShowVoicemailTabAfterVoicemailStatusIsFetched; private VoicemailStatusHelper mVoicemailStatusHelper; private final ArrayList mOnPageChangeListeners = new ArrayList<>(); @@ -89,6 +83,8 @@ public class ListsFragment extends Fragment private boolean mPaused; private CallLogQueryHandler mCallLogQueryHandler; + private UiAction.Type[] actionTypeList; + private final ContentObserver mVoicemailStatusObserver = new ContentObserver(new Handler()) { @Override @@ -159,6 +155,12 @@ public class ListsFragment extends Fragment Trace.endSection(); Trace.beginSection(TAG + " setup views"); + actionTypeList = new UiAction.Type[TAB_COUNT_WITH_VOICEMAIL]; + actionTypeList[TAB_INDEX_SPEED_DIAL] = UiAction.Type.CHANGE_TAB_TO_FAVORITE; + actionTypeList[TAB_INDEX_HISTORY] = UiAction.Type.CHANGE_TAB_TO_CALL_LOG; + actionTypeList[TAB_INDEX_ALL_CONTACTS] = UiAction.Type.CHANGE_TAB_TO_CONTACTS; + actionTypeList[TAB_INDEX_VOICEMAIL] = UiAction.Type.CHANGE_TAB_TO_VOICEMAIL; + String[] tabTitles = new String[TAB_COUNT_WITH_VOICEMAIL]; tabTitles[TAB_INDEX_SPEED_DIAL] = getResources().getString(R.string.tab_speed_dial); tabTitles[TAB_INDEX_HISTORY] = getResources().getString(R.string.tab_history); @@ -190,13 +192,6 @@ public class ListsFragment extends Fragment addOnPageChangeListener(mViewPagerTabs); mRemoveView = (RemoveView) parentView.findViewById(R.id.remove_view); mRemoveViewContent = parentView.findViewById(R.id.remove_view_content); - mMultiSelectSelectAllViewContent = - parentView.findViewById(R.id.multi_select_select_all_view_content); - mSelectUnselectAllViewText = (TextView) parentView.findViewById(R.id.select_all_view_text); - mSelectUnselectAllIcon = (ImageView) parentView.findViewById(R.id.select_all_view_icon); - mMultiSelectSelectAllViewContent.setOnClickListener(null); - mSelectUnselectAllIcon.setOnClickListener(this); - mSelectUnselectAllViewText.setOnClickListener(this); if (PermissionsUtil.hasReadVoicemailPermissions(getContext()) && PermissionsUtil.hasAddVoicemailPermissions(getContext())) { @@ -227,8 +222,8 @@ public class ListsFragment extends Fragment /** * Shows the tab with the specified index. If the voicemail tab index is specified, but the - * voicemail status hasn't been fetched, it will try to show the tab after the voicemail status - * has been fetched. + * voicemail status hasn't been fetched, it will show the speed dial tab and try to show the + * voicemail tab after the voicemail status has been fetched. */ public void showTab(int index) { if (index == TAB_INDEX_VOICEMAIL) { @@ -255,6 +250,8 @@ public class ListsFragment extends Fragment @Override public void onPageSelected(int position) { + PerformanceReport.recordClick(actionTypeList[position]); + LogUtil.i("ListsFragment.onPageSelected", "position: %d", position); mTabIndex = mAdapter.getRtlPosition(position); @@ -389,7 +386,7 @@ public class ListsFragment extends Fragment public void markMissedCallsAsReadAndRemoveNotifications() { if (mCallLogQueryHandler != null) { mCallLogQueryHandler.markMissedCallsAsRead(); - CallLogNotificationsService.markNewMissedCallsAsOld(getContext(), null); + CallLogNotificationsService.cancelAllMissedCalls(getContext()); } } @@ -400,9 +397,7 @@ public class ListsFragment extends Fragment } public void showMultiSelectRemoveView(boolean show) { - mMultiSelectSelectAllViewContent.setVisibility(show ? View.VISIBLE : View.GONE); - mMultiSelectSelectAllViewContent.setAlpha(show ? 0 : 1); - mMultiSelectSelectAllViewContent.animate().alpha(show ? 1 : 0).start(); + mViewPagerTabs.setVisibility(show ? View.GONE : View.VISIBLE); mViewPager.setEnableSwipingPages(!show); } @@ -445,28 +440,4 @@ public class ListsFragment extends Fragment } Logger.get(getActivity()).logScreenView(screenType, getActivity()); } - - @Override - public void onClick(View v) { - updateSelectAllIcon(); - selectAllMode = !selectAllMode; - } - - public void setSelectAllModeToFalse() { - selectAllMode = false; - mSelectUnselectAllIcon.setImageDrawable( - getContext().getDrawable(R.drawable.ic_empty_check_mark_white_24dp)); - } - - private void updateSelectAllIcon() { - if (selectAllMode) { - mSelectUnselectAllIcon.setImageDrawable( - getContext().getDrawable(R.drawable.ic_empty_check_mark_white_24dp)); - ((VisualVoicemailCallLogFragment) mCurrentPage).getAdapter().onAllDeselected(); - } else { - mSelectUnselectAllIcon.setImageDrawable( - getContext().getDrawable(R.drawable.ic_check_mark_blue_24dp)); - ((VisualVoicemailCallLogFragment) mCurrentPage).getAdapter().onAllSelected(); - } - } } diff --git a/java/com/android/dialer/app/list/OldSpeedDialFragment.java b/java/com/android/dialer/app/list/OldSpeedDialFragment.java index 1ddc0f4e1..05d017b28 100644 --- a/java/com/android/dialer/app/list/OldSpeedDialFragment.java +++ b/java/com/android/dialer/app/list/OldSpeedDialFragment.java @@ -56,6 +56,7 @@ import com.android.dialer.util.PermissionsUtil; import com.android.dialer.util.ViewUtil; import com.android.dialer.widget.EmptyContentView; import java.util.ArrayList; +import java.util.Arrays; /** This fragment displays the user's favorite/frequent contacts in a grid. */ public class OldSpeedDialFragment extends Fragment @@ -403,9 +404,15 @@ public class OldSpeedDialFragment extends Fragment return; } - if (!PermissionsUtil.hasPermission(activity, READ_CONTACTS)) { + String[] deniedPermissions = + PermissionsUtil.getPermissionsCurrentlyDenied( + getContext(), PermissionsUtil.allContactsGroupPermissionsUsedInDialer); + if (deniedPermissions.length > 0) { + LogUtil.i( + "OldSpeedDialFragment.onEmptyViewActionButtonClicked", + "Requesting permissions: " + Arrays.toString(deniedPermissions)); FragmentCompat.requestPermissions( - this, new String[] {READ_CONTACTS}, READ_CONTACTS_PERMISSION_REQUEST_CODE); + this, deniedPermissions, READ_CONTACTS_PERMISSION_REQUEST_CODE); } else { // Switch tabs ((HostInterface) activity).showAllContactsTab(); diff --git a/java/com/android/dialer/app/list/PhoneFavoriteTileView.java b/java/com/android/dialer/app/list/PhoneFavoriteTileView.java index 835b448bd..eb4f8e967 100644 --- a/java/com/android/dialer/app/list/PhoneFavoriteTileView.java +++ b/java/com/android/dialer/app/list/PhoneFavoriteTileView.java @@ -138,6 +138,8 @@ public abstract class PhoneFavoriteTileView extends ContactTileView { } if (TextUtils.isEmpty(mPhoneNumberString)) { + // Don't set performance report now, since user may spend some time on picking a number + // Copy "superclass" implementation Logger.get(getContext()) .logInteraction(InteractionEvent.Type.SPEED_DIAL_CLICK_CONTACT_WITH_AMBIGUOUS_NUMBER); diff --git a/java/com/android/dialer/app/list/PhoneFavoritesTileAdapter.java b/java/com/android/dialer/app/list/PhoneFavoritesTileAdapter.java index ce8598261..876fbf146 100644 --- a/java/com/android/dialer/app/list/PhoneFavoritesTileAdapter.java +++ b/java/com/android/dialer/app/list/PhoneFavoritesTileAdapter.java @@ -200,7 +200,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements OnDragDrop int multipleNumbersContactsCount = 0; int contactsWithPhotoCount = 0; int contactsWithNameCount = 0; - int duoReachableContactsCount = 0; + int lightbringerReachableContactsCount = 0; // The cursor should not be closed since this is invoked from a CursorLoader. if (cursor.moveToFirst()) { @@ -308,7 +308,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements OnDragDrop if (contact.phoneNumber == null) { multipleNumbersContactsCount++; } else if (lightbringer.isReachable(mContext, contact.phoneNumber)) { - duoReachableContactsCount++; + lightbringerReachableContactsCount++; } } @@ -320,7 +320,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements OnDragDrop multipleNumbersContactsCount, contactsWithPhotoCount, contactsWithNameCount, - duoReachableContactsCount); + lightbringerReachableContactsCount); // Logs for manual testing LogUtil.v("PhoneFavoritesTileAdapter.saveCursorToCache", "counter: %d", counter); LogUtil.v( diff --git a/java/com/android/dialer/app/list/RegularSearchFragment.java b/java/com/android/dialer/app/list/RegularSearchFragment.java index 4f032032f..728948bfc 100644 --- a/java/com/android/dialer/app/list/RegularSearchFragment.java +++ b/java/com/android/dialer/app/list/RegularSearchFragment.java @@ -26,11 +26,13 @@ import com.android.contacts.common.list.ContactEntryListAdapter; import com.android.contacts.common.list.PinnedHeaderListView; import com.android.dialer.app.R; import com.android.dialer.callintent.CallInitiationType; +import com.android.dialer.common.LogUtil; import com.android.dialer.phonenumbercache.CachedNumberLookupService; import com.android.dialer.phonenumbercache.PhoneNumberCache; import com.android.dialer.util.PermissionsUtil; import com.android.dialer.widget.EmptyContentView; import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener; +import java.util.Arrays; public class RegularSearchFragment extends SearchFragment implements OnEmptyViewActionButtonClickedListener, @@ -114,8 +116,15 @@ public class RegularSearchFragment extends SearchFragment } if (READ_CONTACTS.equals(mPermissionToRequest)) { - FragmentCompat.requestPermissions( - this, new String[] {mPermissionToRequest}, PERMISSION_REQUEST_CODE); + String[] deniedPermissions = + PermissionsUtil.getPermissionsCurrentlyDenied( + getContext(), PermissionsUtil.allContactsGroupPermissionsUsedInDialer); + if (deniedPermissions.length > 0) { + LogUtil.i( + "RegularSearchFragment.onEmptyViewActionButtonClicked", + "Requesting permissions: " + Arrays.toString(deniedPermissions)); + FragmentCompat.requestPermissions(this, deniedPermissions, PERMISSION_REQUEST_CODE); + } } } diff --git a/java/com/android/dialer/app/list/SearchFragment.java b/java/com/android/dialer/app/list/SearchFragment.java index 7f2d17650..00a2708a1 100644 --- a/java/com/android/dialer/app/list/SearchFragment.java +++ b/java/com/android/dialer/app/list/SearchFragment.java @@ -42,6 +42,8 @@ import com.android.dialer.app.dialpad.DialpadFragment.ErrorDialogFragment; import com.android.dialer.app.widget.DialpadSearchEmptyContentView; import com.android.dialer.callintent.CallSpecificAppData; import com.android.dialer.common.LogUtil; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; import com.android.dialer.util.DialerUtils; import com.android.dialer.util.IntentUtil; import com.android.dialer.util.PermissionsUtil; @@ -96,9 +98,6 @@ public class SearchFragment extends PhoneNumberPickerFragment { public void onStart() { LogUtil.d("SearchFragment.onStart", ""); super.onStart(); - if (isSearchMode()) { - getAdapter().setHasHeader(0, false); - } mActivity = (HostInterface) getActivity(); @@ -170,16 +169,6 @@ public class SearchFragment extends PhoneNumberPickerFragment { return animator; } - @Override - protected void setSearchMode(boolean flag) { - super.setSearchMode(flag); - // This hides the "All contacts with phone numbers" header in the search fragment - final ContactEntryListAdapter adapter = getAdapter(); - if (adapter != null) { - adapter.setHasHeader(0, false); - } - } - public void setAddToContactNumber(String addToContactNumber) { mAddToContactNumber = addToContactNumber; } @@ -247,6 +236,10 @@ public class SearchFragment extends PhoneNumberPickerFragment { } break; case DialerPhoneNumberListAdapter.SHORTCUT_CREATE_NEW_CONTACT: + if (this instanceof SmartDialSearchFragment) { + Logger.get(getContext()) + .logImpression(DialerImpression.Type.CREATE_NEW_CONTACT_FROM_DIALPAD); + } number = TextUtils.isEmpty(mAddToContactNumber) ? adapter.getFormattedQueryString() @@ -255,6 +248,10 @@ public class SearchFragment extends PhoneNumberPickerFragment { DialerUtils.startActivityWithErrorToast(getActivity(), intent); break; case DialerPhoneNumberListAdapter.SHORTCUT_ADD_TO_EXISTING_CONTACT: + if (this instanceof SmartDialSearchFragment) { + Logger.get(getContext()) + .logImpression(DialerImpression.Type.ADD_TO_A_CONTACT_FROM_DIALPAD); + } number = TextUtils.isEmpty(mAddToContactNumber) ? adapter.getFormattedQueryString() diff --git a/java/com/android/dialer/app/list/SmartDialSearchFragment.java b/java/com/android/dialer/app/list/SmartDialSearchFragment.java index fc21c8bc3..2ebc06bc3 100644 --- a/java/com/android/dialer/app/list/SmartDialSearchFragment.java +++ b/java/com/android/dialer/app/list/SmartDialSearchFragment.java @@ -34,6 +34,7 @@ import com.android.dialer.common.LogUtil; import com.android.dialer.database.DialerDatabaseHelper; import com.android.dialer.util.PermissionsUtil; import com.android.dialer.widget.EmptyContentView; +import java.util.Arrays; /** Implements a fragment to load and display SmartDial search results. */ public class SmartDialSearchFragment extends SearchFragment @@ -79,6 +80,11 @@ public class SmartDialSearchFragment extends SearchFragment } } + @Override + public boolean getShowEmptyListForNullQuery() { + return true; + } + @Override protected void setupEmptyView() { if (mEmptyView != null && getActivity() != null) { @@ -123,8 +129,16 @@ public class SmartDialSearchFragment extends SearchFragment return; } - FragmentCompat.requestPermissions( - this, new String[] {CALL_PHONE}, CALL_PHONE_PERMISSION_REQUEST_CODE); + String[] deniedPermissions = + PermissionsUtil.getPermissionsCurrentlyDenied( + getContext(), PermissionsUtil.allPhoneGroupPermissionsUsedInDialer); + if (deniedPermissions.length > 0) { + LogUtil.i( + "SmartDialSearchFragment.onEmptyViewActionButtonClicked", + "Requesting permissions: " + Arrays.toString(deniedPermissions)); + FragmentCompat.requestPermissions( + this, deniedPermissions, CALL_PHONE_PERMISSION_REQUEST_CODE); + } } @Override diff --git a/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml b/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml index 7c6df9448..0729d7293 100644 --- a/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml +++ b/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml @@ -41,6 +41,7 @@ android:resizeableActivity="true" android:theme="@style/DialtactsActivityTheme" android:windowSoftInputMode="stateAlwaysHidden|adjustNothing"> + @@ -106,6 +107,7 @@ + + + + + + + - - - - - - - - - - - diff --git a/java/com/android/dialer/app/res/menu/dialtacts_options.xml b/java/com/android/dialer/app/res/menu/dialtacts_options.xml index 25a3e1811..b50e6ad5f 100644 --- a/java/com/android/dialer/app/res/menu/dialtacts_options.xml +++ b/java/com/android/dialer/app/res/menu/dialtacts_options.xml @@ -28,5 +28,8 @@ + diff --git a/java/com/android/dialer/app/res/values-af/strings.xml b/java/com/android/dialer/app/res/values-af/strings.xml index 4f4c65b8a..40e297386 100644 --- a/java/com/android/dialer/app/res/values-af/strings.xml +++ b/java/com/android/dialer/app/res/values-af/strings.xml @@ -80,6 +80,7 @@ "Voeg wagtyd by" "Instellings" "Nabootser" + "Skep nuwe UI-kortpad" "Alle kontakte" "Gebruik raak-nommerbord" "Keer terug na oproep wat besig is" @@ -104,12 +105,14 @@ "%s sek." "%s min. %s sek." "Kanselleer grootmaathandelingmodus" - "stemboodskap" - "stemboodskappe" - "Ja" - "Nee" + "Vee uit" + "Kanselleer" "Vee geselekteerde %1$s uit?" "%1$s gekies" + + ""Vee hierdie stemboodskappe uit? "" + ""Vee hierdie stemboodskap uit? "" + @string/call_log_header_today "%1$s om %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-am/strings.xml b/java/com/android/dialer/app/res/values-am/strings.xml index 7f4a622d7..08b52a6ee 100644 --- a/java/com/android/dialer/app/res/values-am/strings.xml +++ b/java/com/android/dialer/app/res/values-am/strings.xml @@ -80,6 +80,7 @@ "መጠበቅ አክል" "ቅንብሮች" "ማስመሰያ" + "አዲስ የዩአይ አቋራጭ ፍጠር" "ሁሉም እውቅያዎች" "የድምፅ ቁልፍ ሰሌዳን ንካ" "በመካሄድ ላይ ወዳለው ጥሪ ተመለስ" @@ -104,12 +105,14 @@ "%s ሰከንድ" "%s ደቂቃ %s ሴከ" "የጅምላ እርምጃ ሁነታ ይቅር" - "የድምፅ መልዕክት" - "የድምፅ መልዕክቶች" - "አዎ" - "አይ" + "ሰርዝ" + "ይቅር" "የተመረጠው %1$s ይሰረዝ?" "%1$s ተመርጠዋል" + + ""እነዚህ የድምፅ መልዕክቶች ይሰረዙ? "" + ""እነዚህ የድምፅ መልዕክቶች ይሰረዙ? "" + @string/call_log_header_today "%1$s %2$s ላይ" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ar/strings.xml b/java/com/android/dialer/app/res/values-ar/strings.xml index 3687d0bcb..fe84a66ab 100644 --- a/java/com/android/dialer/app/res/values-ar/strings.xml +++ b/java/com/android/dialer/app/res/values-ar/strings.xml @@ -84,6 +84,7 @@ "إضافة انتظار" "الإعدادات" "المحاكي" + "إنشاء اختصار للواجهة الجديدة" "جميع جهات الاتصال" "استخدام لوحة مفاتيح نغمات باللمس" "عودة إلى المكالمة الجارية" @@ -108,12 +109,18 @@ "%s ثانية" "%s دقيقة %s ثانية" "إلغاء وضع الإجراءات المجمَّع" - "البريد الصوتي" - "رسائل البريد الصوتي" - "نعم" - "لا" + "حذف" + "إلغاء" "حذف رسائل %1$s المحددة؟" "تم تحديد %1$s" + + ""حذف رسائل البريد الصوتي هذه؟ "" + ""حذف رسالتي البريد الصوتي هاتين؟ "" + ""حذف رسائل البريد الصوتي هذه؟ "" + ""حذف رسائل البريد الصوتي هذه؟ "" + ""حذف رسائل البريد الصوتي هذه؟ "" + ""حذف رسالة البريد الصوتي هذه؟ "" + @string/call_log_header_today "%1$s في %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-az/strings.xml b/java/com/android/dialer/app/res/values-az/strings.xml index b6681c9e2..f2b0cf35d 100644 --- a/java/com/android/dialer/app/res/values-az/strings.xml +++ b/java/com/android/dialer/app/res/values-az/strings.xml @@ -80,6 +80,7 @@ "Gözləmə əlavə edin" "Ayarlar" "Stimulyator" + "Yeni İİ Qısayolu yaradın" "Bütün kontaktlar" "Toxunma ton klaviaturasını istifadə edin" "Davam edən zəngə qayıdın" @@ -104,12 +105,14 @@ "%s san" "%s dəq %s san" "Qrup əməliyyatları rejimini ləğv edin" - "səsli e-məktub" - "səsli e-məktublar" - "Bəli" - "Xeyr" + "Silin" + "Ləğv edin" "Seçilmiş %1$s silinsin?" "%1$s seçilib" + + ""Bu səsli e-məktub silinsin? "" + ""Bu səsli e-məktub silinsin? "" + @string/call_log_header_today "%1$s tarixində %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-b+sr+Latn/strings.xml b/java/com/android/dialer/app/res/values-b+sr+Latn/strings.xml index 40c0886c8..b011f7866 100644 --- a/java/com/android/dialer/app/res/values-b+sr+Latn/strings.xml +++ b/java/com/android/dialer/app/res/values-b+sr+Latn/strings.xml @@ -81,6 +81,7 @@ "Dodaj čekanje" "Podešavanja" "Simulator" + "Napravite prečicu za novi UI" "Svi kontakti" "Upotrebite brojčanik za tonsko biranje" "Vrati se na poziv koji je u toku" @@ -105,12 +106,15 @@ "%s sek" "%s min %s sek" "Otkažite režim grupnih radnji" - "govornu poruku" - "govorne poruke" - "Da" - "Ne" + "Izbriši" + "Otkaži" "Želite li da izbrišete izabranu(e) %1$s?" "Izabranih: %1$s" + + ""Želite li da izbrišete ove govorne poruke? "" + ""Želite li da izbrišete ove govorne poruke? "" + ""Želite li da izbrišete ove govorne poruke? "" + @string/call_log_header_today "%1$s u %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-be/strings.xml b/java/com/android/dialer/app/res/values-be/strings.xml index f2ad3342b..f9b083747 100644 --- a/java/com/android/dialer/app/res/values-be/strings.xml +++ b/java/com/android/dialer/app/res/values-be/strings.xml @@ -82,6 +82,7 @@ "Дадаць чаканне" "Налады" "Сродак мадэліравання" + "Ярлык новага карыст. інтэрфейсу" "Усе кантакты" "Выкарыстанне тонавай клавіятуры" "Звярнуцца да бягучага выкліку" @@ -106,12 +107,16 @@ "%s с" "%s хв %s с" "Скасаваць рэжым пакетных дзеянняў" - "галасавая пошта" - "галасавая пошта" - "Так" - "Не" + "Выдаліць" + "Скасаваць" "Выдаліць вылучанае: %1$s?" "Выбрана: %1$s" + + ""Выдаліць гэтыя паведамленні галасавой пошты? "" + ""Выдаліць гэтыя паведамленні галасавой пошты? "" + ""Выдаліць гэтыя паведамленні галасавой пошты? "" + ""Выдаліць гэтыя паведамленні галасавой пошты? "" + @string/call_log_header_today "%1$s у %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-bg/strings.xml b/java/com/android/dialer/app/res/values-bg/strings.xml index 8083f4828..8b1105cb3 100644 --- a/java/com/android/dialer/app/res/values-bg/strings.xml +++ b/java/com/android/dialer/app/res/values-bg/strings.xml @@ -80,6 +80,7 @@ "Добавяне на изчакване" "Настройки" "Симулатор" + "Пряк път към новия ПИ" "Всички контакти" "Използване на тонова клавиатура" "Назад към текущото обаждане" @@ -104,12 +105,14 @@ "%s сек" "%s мин %s сек" "Анулиране на режима на групови действия" - "гласово съобщение" - "гласови съобщения" - "Да" - "Не" + "Изтриване" + "Отказ" "Избрахте %1$s – да се изтрие ли избраното?" "Избрахте %1$s" + + ""Да се изтрият ли тези гласови съобщения? "" + ""Да се изтрие ли това гласово съобщение? "" + @string/call_log_header_today "%1$s в %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-bn/strings.xml b/java/com/android/dialer/app/res/values-bn/strings.xml index 4d2d7cc1e..2ec362685 100644 --- a/java/com/android/dialer/app/res/values-bn/strings.xml +++ b/java/com/android/dialer/app/res/values-bn/strings.xml @@ -80,6 +80,7 @@ "অপেক্ষা যোগ করুন" "সেটিংস" "সিমুলেটার" + "নতুন UI শর্টকাট তৈরি করুন" "সকল পরিচিতি" "স্পর্শ স্বর কীপ্যাড ব্যবহার করুন" "প্রগতিতে থাকা কলে প্রত্যাবর্তন" @@ -104,12 +105,14 @@ "%s সেকেন্ড" "%s মিনিট %s সেকেন্ড" "ব্যাচ অ্যাকশন মোড বাতিল করুন" - "ভয়েসমেল" - "ভয়েসমেলগুলি" - "হ্যাঁ" - "না" + "মুছুন" + "বাতিল করুন" "নির্বাচিত %1$s মুছে ফেলতে চান?" "%1$sটি নির্বাচিত" + + ""এই ভয়েসমেলগুলি মুছবেন? "" + ""এই ভয়েসমেলগুলি মুছবেন? "" + @string/call_log_header_today "%1$s তারিখে %2$s\'টায়" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-bs/strings.xml b/java/com/android/dialer/app/res/values-bs/strings.xml index d8347723d..087db1274 100644 --- a/java/com/android/dialer/app/res/values-bs/strings.xml +++ b/java/com/android/dialer/app/res/values-bs/strings.xml @@ -81,6 +81,7 @@ "Dodaj čekanje" "Postavke" "Simulator" + "Kreiraj prečicu za novi UI" "Svi kontakti" "Koristi tastaturu za tonsko biranje" "Povratak na poziv u toku" @@ -105,12 +106,15 @@ "%s sek." "%s min. %s sek." "Otkaži način rada za grupnu radnju" - "poruka govorne pošte" - "poruke govorne pošte" - "Da" - "Ne" + "Izbriši" + "Otkaži" "Izbrisati izabranu/e %1$s?" "Odabrano %1$s" + + ""Izbrisati ove govorne poruke? "" + ""Izbrisati ove govorne poruke? "" + ""Izbrisati ove govorne poruke? "" + @string/call_log_header_today "%1$s u %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ca/strings.xml b/java/com/android/dialer/app/res/values-ca/strings.xml index 7b12e0dbd..71385805a 100644 --- a/java/com/android/dialer/app/res/values-ca/strings.xml +++ b/java/com/android/dialer/app/res/values-ca/strings.xml @@ -80,6 +80,7 @@ "Afegeix espera" "Configuració" "Simulador" + "Crea drecera per a la nova IU" "Tots els contactes" "Utilitza el teclat de tons" "Torna a la trucada en curs" @@ -104,18 +105,20 @@ "%s s" "%s min %s s" "Cancel·la el mode d\'accions en lot" - "missatge de veu" - "missatges de veu" - "Sí" - "No" + "Suprimeix" + "Cancel·la" "Vols suprimir l\'element o elements seleccionats (%1$s)?" "%1$s seleccionades" + + ""Vols suprimir aquests missatges de veu? "" + ""Vols suprimir aquest missatge de veu? "" + @string/call_log_header_today "%1$s a les %2$s" "%1$02d:%2$02d" "%1$s%2$s" "No es pot trucar a aquest número." - "Per configurar els missatges de veu, vés a Menú > Configuració." + "Per configurar els missatges de veu, ves a Menú > Configuració." "Per trucar a la bústia de veu, primer has de desactivar el mode d\'avió." "S\'està carregant…" "IMEI" @@ -229,7 +232,7 @@ "Bloqueja el número" "No és una trucada brossa" "Desbloqueja el número" - "Contingut brossa" + "Trucada brossa" "%1$s no té connexió i no s\'hi pot contactar" "Informació" diff --git a/java/com/android/dialer/app/res/values-cs/strings.xml b/java/com/android/dialer/app/res/values-cs/strings.xml index bbcb35847..dbff467c0 100644 --- a/java/com/android/dialer/app/res/values-cs/strings.xml +++ b/java/com/android/dialer/app/res/values-cs/strings.xml @@ -82,6 +82,7 @@ "Přidat čekání" "Nastavení" "Simulátor" + "Vytv. zkratku na nové rozhraní" "Všechny kontakty" "Použít dotykovou tónovou klávesnici" "Návrat k probíhajícímu hovoru" @@ -106,12 +107,16 @@ "%s s" "%s min %s s" "Zrušit režim hromadných akcí" - "vybranou hlasovou zprávu" - "vybrané hlasové zprávy" - "Ano" - "Ne" + "Smazat" + "Zrušit" "Smazat %1$s?" "Vybráno: %1$s" + + ""Smazat tyto hlasové zprávy? "" + ""Smazat tyto hlasové zprávy? "" + ""Smazat tyto hlasové zprávy? "" + ""Smazat tuto hlasovou zprávu? "" + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-da/strings.xml b/java/com/android/dialer/app/res/values-da/strings.xml index 31cf8e33d..72f5a2835 100644 --- a/java/com/android/dialer/app/res/values-da/strings.xml +++ b/java/com/android/dialer/app/res/values-da/strings.xml @@ -80,6 +80,7 @@ "Tilføj ventetid" "Indstillinger" "Simulator" + "Opret ny brugerfladegenvej" "Alle kontakter" "Brug numerisk tastatur" "Vend tilbage til igangværende opkald" @@ -88,7 +89,7 @@ "Massehandlingstilstanden startes" "Massehandlingstilstanden blev afsluttet" "Vælg %1$s" - "Fravælg %1$s" + "Fravalgt %1$s" "Afspil telefonsvarerbesked" "Vis kontaktpersonen %1$s" "Ring til %1$s" @@ -104,12 +105,14 @@ "%s sek." "%s min. %s sek." "Annuller massehandlingstilstand" - "talebesked" - "talebeskeder" - "Ja" - "Nej" + "Slet" + "Annuller" "Vil du slette de valgte %1$s?" "%1$s er valgt" + + ""Vil du slette denne talebesked? "" + ""Vil du slette disse talebeskeder? "" + @string/call_log_header_today "%1$s kl. %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-de/strings.xml b/java/com/android/dialer/app/res/values-de/strings.xml index c1f644119..a7efd53a3 100644 --- a/java/com/android/dialer/app/res/values-de/strings.xml +++ b/java/com/android/dialer/app/res/values-de/strings.xml @@ -80,6 +80,7 @@ "Warten hinzufügen" "Einstellungen" "Simulator" + "Verknüpfung für neue Benutzeroberfläche erstellen" "Alle Kontakte" "Telefontastatur verwenden" "Zurück zum aktuellen Anruf" @@ -104,12 +105,14 @@ "%s s" "%s min %s s" "Modus für Batch-Aktionen abbrechen" - "Mailboxnachricht" - "Mailboxnachrichten" - "Ja" - "Nein" + "Löschen" + "Abbrechen" "Ausgewählte %1$s löschen?" "%1$s ausgewählt" + + ""Diese Mailboxnachrichten löschen? "" + ""Diese Mailboxnachricht löschen? "" + @string/call_log_header_today "%1$s um %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-el/strings.xml b/java/com/android/dialer/app/res/values-el/strings.xml index c4ba02d0f..7080e5e50 100644 --- a/java/com/android/dialer/app/res/values-el/strings.xml +++ b/java/com/android/dialer/app/res/values-el/strings.xml @@ -80,6 +80,7 @@ "Προσθήκη αναμονής" "Ρυθμίσεις" "Προσομοιωτής" + "Δημ. νέας συντόμ. διεπαφής" "Όλες οι επαφές" "Χρησιμοποιήστε το πληκτρολόγιο αφής ηχητικών τόνων" "Επιστροφή στην κλήση που βρίσκεται σε εξέλιξη" @@ -104,12 +105,14 @@ "%s δευτερόλεπτα" "%s λεπτά %s δευτερόλεπτα" "Ακύρωση λειτουργίας μαζικών ενεργειών" - "φωνητικού μηνύματος αυτόματου τηλεφωνητή" - "φωνητικών μηνυμάτων αυτόματου τηλεφωνητή" - "Ναι" - "Όχι" + "Διαγραφή" + "Ακύρωση" "Διαγραφή επιλεγμ. %1$s;" "Έχουν επιλεγεί %1$s" + + ""Διαγραφή αυτών των μηνυμάτων αυτόματου τηλεφωνητή; "" + ""Διαγραφή αυτού του μηνύματος αυτόματου τηλεφωνητή; "" + @string/call_log_header_today "%1$s στις %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-en-rAU/strings.xml b/java/com/android/dialer/app/res/values-en-rAU/strings.xml index cb7e912c7..999f7dab0 100644 --- a/java/com/android/dialer/app/res/values-en-rAU/strings.xml +++ b/java/com/android/dialer/app/res/values-en-rAU/strings.xml @@ -80,6 +80,7 @@ "Add wait" "Settings" "Simulator" + "Create new UI shortcut" "All contacts" "Use touch tone keypad" "Return to call in progress" @@ -104,12 +105,14 @@ "%s sec" "%s min %s sec" "Cancel batch actions mode" - "voicemail" - "voicemails" - "Yes" - "No" + "Delete" + "Cancel" "Delete selected %1$s?" "%1$s selected" + + ""Delete these voicemails? "" + ""Delete this voicemail? "" + @string/call_log_header_today "%1$s at %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-en-rGB/strings.xml b/java/com/android/dialer/app/res/values-en-rGB/strings.xml index cb7e912c7..999f7dab0 100644 --- a/java/com/android/dialer/app/res/values-en-rGB/strings.xml +++ b/java/com/android/dialer/app/res/values-en-rGB/strings.xml @@ -80,6 +80,7 @@ "Add wait" "Settings" "Simulator" + "Create new UI shortcut" "All contacts" "Use touch tone keypad" "Return to call in progress" @@ -104,12 +105,14 @@ "%s sec" "%s min %s sec" "Cancel batch actions mode" - "voicemail" - "voicemails" - "Yes" - "No" + "Delete" + "Cancel" "Delete selected %1$s?" "%1$s selected" + + ""Delete these voicemails? "" + ""Delete this voicemail? "" + @string/call_log_header_today "%1$s at %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-en-rIN/strings.xml b/java/com/android/dialer/app/res/values-en-rIN/strings.xml index cb7e912c7..999f7dab0 100644 --- a/java/com/android/dialer/app/res/values-en-rIN/strings.xml +++ b/java/com/android/dialer/app/res/values-en-rIN/strings.xml @@ -80,6 +80,7 @@ "Add wait" "Settings" "Simulator" + "Create new UI shortcut" "All contacts" "Use touch tone keypad" "Return to call in progress" @@ -104,12 +105,14 @@ "%s sec" "%s min %s sec" "Cancel batch actions mode" - "voicemail" - "voicemails" - "Yes" - "No" + "Delete" + "Cancel" "Delete selected %1$s?" "%1$s selected" + + ""Delete these voicemails? "" + ""Delete this voicemail? "" + @string/call_log_header_today "%1$s at %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-es-rUS/strings.xml b/java/com/android/dialer/app/res/values-es-rUS/strings.xml index 79d607fc7..701d74ebc 100644 --- a/java/com/android/dialer/app/res/values-es-rUS/strings.xml +++ b/java/com/android/dialer/app/res/values-es-rUS/strings.xml @@ -80,6 +80,7 @@ "Agregar espera" "Configuración" "Simulador" + "Crear acceso a la nueva IU" "Todos los contactos" "Usar teclado numérico" "Regresar a la llamada en curso" @@ -104,12 +105,14 @@ "%s s" "%s min %s s" "Cancelar el modo de acción masiva" - "el mensaje de voz" - "los mensajes de voz" - "Sí" - "No" + "Borrar" + "Cancelar" "¿Deseas borrar %1$s que seleccionaste?" "%1$s seleccionada(s)" + + ""¿Deseas borrar estos mensajes de voz? "" + ""¿Deseas borrar este mensaje de voz? "" + @string/call_log_header_today "El %1$s a la hora %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-es/strings.xml b/java/com/android/dialer/app/res/values-es/strings.xml index 170edc8ca..8cf47f554 100644 --- a/java/com/android/dialer/app/res/values-es/strings.xml +++ b/java/com/android/dialer/app/res/values-es/strings.xml @@ -80,6 +80,7 @@ "Añadir espera" "Ajustes" "Simulador" + "Crear acceso a la interfaz" "Todos los contactos" "Usar teclado táctil" "Volver a la llamada" @@ -104,12 +105,14 @@ "%s s" "%s min y %s s" "Cancelar el modo de acciones en lote" - "mensaje de voz" - "mensajes de voz" - "Sí" - "No" + "Eliminar" + "Cancelar" "¿Eliminar la selección de %1$s?" "Se han seleccionado %1$s" + + ""¿Eliminar estos mensajes de voz? "" + ""¿Eliminar este mensaje de voz? "" + @string/call_log_header_today "%1$s a las %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-et/strings.xml b/java/com/android/dialer/app/res/values-et/strings.xml index e32b10403..da043bf3c 100644 --- a/java/com/android/dialer/app/res/values-et/strings.xml +++ b/java/com/android/dialer/app/res/values-et/strings.xml @@ -80,6 +80,7 @@ "Lisa ootamine" "Seaded" "Simulaator" + "Loo uue kasutajaliid. otsetee" "Kõik kontaktid" "Kasuta puutetooniga klahvistikku" "Tagasi käimasolevale kõnele" @@ -104,12 +105,14 @@ "%s s" "%s min %s s" "Mitme toimigu režiimi tühistamine" - "kõnepostisõnum" - "kõnepostisõnumid" - "Jah" - "Ei" + "Kustuta" + "Tühista" "Kas kustutada valitud kõnepostisõnumid %1$s?" "%1$s on valitud" + + ""Kas kustutada need kõnepostisõnumid? "" + ""Kas kustutada see kõnepostisõnum? "" + @string/call_log_header_today "%1$s kell %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-eu/strings.xml b/java/com/android/dialer/app/res/values-eu/strings.xml index 57ef67d88..071c6f3f0 100644 --- a/java/com/android/dialer/app/res/values-eu/strings.xml +++ b/java/com/android/dialer/app/res/values-eu/strings.xml @@ -80,6 +80,7 @@ "Gehitu itxaronaldia" "Ezarpenak" "Simulagailua" + "Sortu interfazerako esteka" "Kontaktu guztiak" "Erabili ukipen-tonuak dituen teklatua" "Itzuli abian den deira" @@ -104,12 +105,14 @@ "%s s" "%s min %s s" "Utzi bertan behera ekintzak multzoka gauzatzeko modua" - "ahots-mezua" - "ahots-mezuak" - "Bai" - "Ez" + "Ezabatu" + "Utzi" "Hautatutako %1$s ezabatu?" "%1$s hautatu dira" + + ""Ahots-mezu hauek ezabatu nahi dituzu? "" + ""Ahots-mezu hau ezabatu nahi duzu? "" + @string/call_log_header_today "%1$s (%2$s)" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-fa/strings.xml b/java/com/android/dialer/app/res/values-fa/strings.xml index eadb0dcb7..6c588747e 100644 --- a/java/com/android/dialer/app/res/values-fa/strings.xml +++ b/java/com/android/dialer/app/res/values-fa/strings.xml @@ -80,6 +80,7 @@ "افزودن انتظار" "تنظیمات" "شبیه‌ساز" + "ایجاد میان‌بر رابط کاربری جدید" "همه مخاطبین" "استفاده از صفحه‌کلید لمسی" "برگشت به تماس درحال انجام" @@ -104,12 +105,14 @@ "%s ثانیه" "%s دقیقه %s ثانیه" "لغو حالت اقدام‌ دسته‌ای" - "پست صوتی" - "پست‌های صوتی" - "بله" - "نه" + "حذف" + "لغو" "%1$s انتخاب‌شده حذف شود؟" "%1$s مورد انتخاب شد" + + ""این پست‌های صوتی حذف شوند؟ "" + ""این پست‌های صوتی حذف شوند؟ "" + @string/call_log_header_today "%1$s ساعت %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-fi/strings.xml b/java/com/android/dialer/app/res/values-fi/strings.xml index 951095908..55865d44a 100644 --- a/java/com/android/dialer/app/res/values-fi/strings.xml +++ b/java/com/android/dialer/app/res/values-fi/strings.xml @@ -80,6 +80,7 @@ "Lisää tauko" "Asetukset" "Simulaattori" + "Luo uusi UI-pikakuvake" "Kaikki yhteystiedot" "Käytä näppäimistöä" "Palaa käynnissä olevaan puheluun" @@ -104,12 +105,14 @@ "%s s" "%s min %s s" "Peruuta joukkotoimintotila." - "vastaajaviesti" - "vastaajaviestit" - "Kyllä" - "Ei" + "Poista" + "Peruuta" "Poistetaanko %1$s?" "%1$s valittu" + + ""Poistetaanko nämä vastaajaviestit? "" + ""Poistetaanko tämä vastaajaviesti? "" + @string/call_log_header_today "%1$s klo %2$s" "%1$02d.%2$02d" diff --git a/java/com/android/dialer/app/res/values-fr-rCA/strings.xml b/java/com/android/dialer/app/res/values-fr-rCA/strings.xml index 6aa285c50..f10b121d5 100644 --- a/java/com/android/dialer/app/res/values-fr-rCA/strings.xml +++ b/java/com/android/dialer/app/res/values-fr-rCA/strings.xml @@ -80,6 +80,7 @@ "Ajouter Attendre" "Paramètres" "Simulateur" + "Créer un raccourci vers l\'IU" "Tous les contacts" "Utiliser le clavier DTMF" "Reprendre l\'appel en cours" @@ -104,12 +105,14 @@ "%s s" "%s min et %s sec" "Annuler le mode d\'action par lots" - "message vocal" - "messages vocaux" - "Oui" - "Non" + "Supprimer" + "Annuler" "Supprimer la sélection (%1$s)?" "%1$s sélection(s)" + + ""Supprimer ce message vocal? "" + ""Supprimer ces messages vocaux? "" + @string/call_log_header_today "%1$s à %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-fr/strings.xml b/java/com/android/dialer/app/res/values-fr/strings.xml index f539d2e55..2ce930af5 100644 --- a/java/com/android/dialer/app/res/values-fr/strings.xml +++ b/java/com/android/dialer/app/res/values-fr/strings.xml @@ -80,6 +80,7 @@ "Ajouter une attente" "Paramètres" "Simulateur" + "Créer un raccourci vers la nouvelle interface" "Tous les contacts" "Utiliser le clavier DTMF" "Reprendre l\'appel en cours" @@ -104,12 +105,14 @@ "%s secondes" "%s min et %s s" "Annuler le mode d\'actions groupées" - "message vocal" - "messages vocaux" - "Oui" - "Non" + "Supprimer" + "Annuler" "Supprimer les messages vocaux sélectionnés (%1$s) ?" "%1$s sélectionnés" + + ""Supprimer ce message vocal ? "" + ""Supprimer ces message vocaux ? "" + @string/call_log_header_today "%1$s à %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-gl/strings.xml b/java/com/android/dialer/app/res/values-gl/strings.xml index ca31c5e47..b9e540750 100644 --- a/java/com/android/dialer/app/res/values-gl/strings.xml +++ b/java/com/android/dialer/app/res/values-gl/strings.xml @@ -80,6 +80,7 @@ "Engadir espera" "Configuración" "Simulador" + "Crear atallo para a nova IU" "Todos os contactos" "Usar teclado de tons táctiles" "Volver á chamada en curso" @@ -104,12 +105,14 @@ "%s s" "%s min %s s" "Cancela o modo de accións en lote" - "correo de voz" - "correos de voz" - "Si" - "Non" + "Eliminar" + "Cancelar" "Queres eliminar a selección (%1$s)?" "Cantidade seleccionada: %1$s" + + ""Queres eliminar estes correos de voz? "" + ""Queres eliminar este correo de voz? "" + @string/call_log_header_today "%1$s ás %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-gu/strings.xml b/java/com/android/dialer/app/res/values-gu/strings.xml index fbe4d0aaa..ca8749ad3 100644 --- a/java/com/android/dialer/app/res/values-gu/strings.xml +++ b/java/com/android/dialer/app/res/values-gu/strings.xml @@ -80,6 +80,7 @@ "પ્રતીક્ષા ઉમેરો" "સેટિંગ્સ" "સિમ્યુલેટર" + "નવું UI શૉર્ટકટ્સ બનાવો" "તમામ સંપર્કો" "ટચ ટોન કીપેડનો ઉપયોગ કરો" "કૉલ પર પાછા આવવું પ્રગતિ પર છે" @@ -104,12 +105,14 @@ "%s સેકંડ" "%s મિ %s સે" "બૅચ ક્રિયા મોડ રદ કરો" - "વૉઇસમેઇલ" - "વૉઇસમેઇલ" - "હા" - "નહીં" + "કાઢી નાખો" + "રદ કરો" "પસંદ કરેલ %1$sને કાઢી નાખીએ?" "%1$s પસંદ કરી" + + ""આ વૉઇસમેઇલ કાઢી નાખીએ? "" + ""આ વૉઇસમેઇલ કાઢી નાખીએ? "" + @string/call_log_header_today "%1$s નાં રોજ %2$s વાગ્યે" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-hi/strings.xml b/java/com/android/dialer/app/res/values-hi/strings.xml index c998e4402..3bc931921 100644 --- a/java/com/android/dialer/app/res/values-hi/strings.xml +++ b/java/com/android/dialer/app/res/values-hi/strings.xml @@ -80,6 +80,7 @@ "प्रतीक्षा का समय बढ़ाएं" "सेटिंग" "सिम्युलेटर" + "नया UI शॉर्टकट बनाएं" "सभी संपर्क" "टच टोन कीपैड का उपयोग करें" "कॉल पर लौटना प्रगति पर है" @@ -104,12 +105,14 @@ "%s सेकंड" "%s मि. %s से." "बैच कार्रवाई मोड रद्द करें" - "वॉयसमेल" - "वॉयसमेल" - "हां" - "नहीं" + "हटाएं" + "रद्द करें" "क्या चुने गए %1$s हटाना चाहते हैं?" "%1$s चयनित" + + ""ये वॉइसमेल हटाएं? "" + ""ये वॉइसमेल हटाएं? "" + @string/call_log_header_today "%1$s को %2$s बजे" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-hr/strings.xml b/java/com/android/dialer/app/res/values-hr/strings.xml index 5261cfb0d..0d2147008 100644 --- a/java/com/android/dialer/app/res/values-hr/strings.xml +++ b/java/com/android/dialer/app/res/values-hr/strings.xml @@ -81,6 +81,7 @@ "Dodaj čekanje" "Postavke" "Simulator" + "Izrada prečaca novog sučelja" "Svi kontakti" "Koristi dodirnu zvučnu tipkovnicu" "Natrag na poziv u tijeku" @@ -105,12 +106,15 @@ "%s s" "%s min %s s" "Otkaži način skupnih radnji" - "poruka govorne pošte" - "poruke govorne pošte" - "Da" - "Ne" + "Izbriši" + "Odustani" "Želite li izbrisati odabranu poruku/e govorne pošte %1$s?" "Odabrano: %1$s" + + ""Želite li izbrisati ove poruke govorne pošte? "" + ""Želite li izbrisati ove poruke govorne pošte? "" + ""Želite li izbrisati ove poruke govorne pošte? "" + @string/call_log_header_today "%1$s u %2$s" "%1$02d.%2$02d" diff --git a/java/com/android/dialer/app/res/values-hu/strings.xml b/java/com/android/dialer/app/res/values-hu/strings.xml index 452f0da47..9a373e6e8 100644 --- a/java/com/android/dialer/app/res/values-hu/strings.xml +++ b/java/com/android/dialer/app/res/values-hu/strings.xml @@ -80,6 +80,7 @@ "Várakozás hozzáadása" "Beállítások" "Szimulátor" + "Új felh. felület-parancsikon" "Összes névjegy" "Hangkódos telefonbillentyűzet használata" "Vissza a folyamatban lévő híváshoz" @@ -104,12 +105,14 @@ "%s másodperc" "%s perc %s másodperc" "Köteges művelet mód leállítva" - "hangpostaüzenetet" - "hangpostaüzeneteket" - "Igen" - "Nem" + "Törlés" + "Mégse" "Törli a kiválasztott %1$s?" "%1$s kiválasztva" + + ""Törli ezeket a hangpostaüzeneteket? "" + ""Törli ezt a hangpostaüzenetet? "" + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-hy/strings.xml b/java/com/android/dialer/app/res/values-hy/strings.xml index 97a84f2fe..2b2fbf61b 100644 --- a/java/com/android/dialer/app/res/values-hy/strings.xml +++ b/java/com/android/dialer/app/res/values-hy/strings.xml @@ -80,12 +80,13 @@ "Ավելացնել սպասում" "Կարգավորումներ" "Նմանակիչ" + "Ստեղծել միջերեսի նոր դյուրանցում" "Բոլոր կոնտակտները" "Օգտագործել հնչերանգներով ստեղնաշարը" "Վերադառնալ ընթացիկ զանգին" "Ավելացնել զանգ" "Մուտքային զանգեր" - "Մուտք զանգվածային գործողությունների ռեժին" + "Դուք մտել եք զանգվածային գործողության ռեժիմ" "Դուք դուրս եկաք զանգվածային գործողությունների ռեժիմից" "Ընտրվեց՝ %1$s" "Ապընտրվեց՝ %1$s" @@ -104,12 +105,14 @@ "%s վրկ" "%s րոպե %s վայրկյան" "Չեղարկել փաթեթային գործողությունների ռեժիմը" - "ձայնային հաղորդագրություն" - "ձայնային հաղորդագրություններ" - "Այո" - "Ոչ" + "Ջնջել" + "Չեղարկել" "Ջնջե՞լ նշված %1$sը" "Ընտրվել է՝ %1$s" + + ""Delete these voicemails? "" + ""Ջնջե՞լ այս ձայնային հաղորդագրությունները "" + @string/call_log_header_today "%1$s-ին, ժամը %2$s-ին" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-in/strings.xml b/java/com/android/dialer/app/res/values-in/strings.xml index f309f927b..e72fd6337 100644 --- a/java/com/android/dialer/app/res/values-in/strings.xml +++ b/java/com/android/dialer/app/res/values-in/strings.xml @@ -80,6 +80,7 @@ "Tambahkan tunggu" "Setelan" "Simulator" + "Buat Pintasan UI Baru" "Semua kontak" "Gunakan keypad nada sentuh" "Kembali ke panggilan sedang berlangsung" @@ -104,12 +105,14 @@ "%s dtk" "%s mnt %s dtk" "Membatalkan mode tindakan kelompok" - "pesan suara" - "pesan suara" - "Ya" - "Tidak" + "Hapus" + "Batal" "Hapus %1$s yang dipilih?" "%1$s dipilih" + + ""Hapus pesan suara ini? "" + ""Hapus pesan suara ini? "" + @string/call_log_header_today "%1$s pukul %2$s" "%1$02d.%2$02d" diff --git a/java/com/android/dialer/app/res/values-is/strings.xml b/java/com/android/dialer/app/res/values-is/strings.xml index b291eae84..bd329be9d 100644 --- a/java/com/android/dialer/app/res/values-is/strings.xml +++ b/java/com/android/dialer/app/res/values-is/strings.xml @@ -80,6 +80,7 @@ "Bæta töf við" "Stillingar" "Hermir" + "Stofna flýtileið í nýtt viðmót" "Allir tengiliðir" "Nota snertitónatakkaborð" "Fara aftur í símtal í gangi" @@ -104,12 +105,14 @@ "%s sek." "%s mín. og %s sek." "Hætta við runuaðgerðastillingu" - "talhólfsskilaboð" - "talhólfsskilaboð" - "Já" - "Nei" + "Eyða" + "Hætta við" "Eyða völdum %1$s?" "%1$s valin" + + ""Eyða þessum talhólfsskilaboðum? "" + ""Eyða þessum talhólfsskilaboðum? "" + @string/call_log_header_today "%1$s kl. %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-it/strings.xml b/java/com/android/dialer/app/res/values-it/strings.xml index 711ab26ee..356f5a603 100644 --- a/java/com/android/dialer/app/res/values-it/strings.xml +++ b/java/com/android/dialer/app/res/values-it/strings.xml @@ -80,6 +80,7 @@ "Aggiungi attesa" "Impostazioni" "Simulatore" + "Crea nuova scorciatoia UI" "Tutti i contatti" "Usa tastierino per selezione a toni" "Torna alla chiamata in corso" @@ -104,12 +105,14 @@ "%s secondi" "%s min %s s" "Annulla modalità di azione collettiva" - "messaggio vocale" - "messaggi vocali" - "Sì" - "No" + "Elimina" + "Annulla" "Eliminare i %1$s selezionati?" "%1$s selezionate" + + ""Eliminare questi messaggi vocali? "" + ""Eliminare questo messaggio vocale? "" + @string/call_log_header_today "%1$s alle ore %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-iw/strings.xml b/java/com/android/dialer/app/res/values-iw/strings.xml index bd2a05aec..230555a14 100644 --- a/java/com/android/dialer/app/res/values-iw/strings.xml +++ b/java/com/android/dialer/app/res/values-iw/strings.xml @@ -82,6 +82,7 @@ "הוסף המתנה" "הגדרות" "סימולטור" + "יצירת קיצור דרך לממשק החדש" "כל אנשי הקשר" "השתמש במקלדת עם חיוג צלילים" "חזור לשיחה פעילה" @@ -106,12 +107,16 @@ "%s שניות" "%s דק\' %s שנ\'" "ביטול המצב של ביצוע פעולות בכמות גדולה" - "ההודעה הקולית" - "ההודעות הקוליות" - "כן" - "לא" + "מחיקה" + "ביטול" "האם למחוק את %1$s שבחרת?" "%1$s נבחרו" + + ""האם למחוק את ההודעות הקוליות האלה? "" + ""האם למחוק את ההודעות הקוליות האלה? "" + ""האם למחוק את ההודעות הקוליות האלה? "" + ""האם למחוק את ההודעה הקולית הזו? "" + @string/call_log_header_today "%1$s ב-%2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ja/strings.xml b/java/com/android/dialer/app/res/values-ja/strings.xml index 9ba40fb8f..71fca83d5 100644 --- a/java/com/android/dialer/app/res/values-ja/strings.xml +++ b/java/com/android/dialer/app/res/values-ja/strings.xml @@ -80,6 +80,7 @@ "待機を追加" "設定" "シミュレーション" + "新しいUIのショートカットを作成" "すべての連絡先" "プッシュホン式キーパッドを使う" "通話に戻る" @@ -104,12 +105,14 @@ "%s秒" "%s%s秒" "一括操作モードをキャンセルします" - "ボイスメール" - "ボイスメール" - "はい" - "いいえ" + "削除" + "キャンセル" "選択した%1$sを削除しますか?" "%1$s 件選択済み" + + ""これらのボイスメールを削除しますか?"" + ""このボイスメールを削除しますか?"" + @string/call_log_header_today "%1$s%2$s" "%1$02d%2$02d 秒" diff --git a/java/com/android/dialer/app/res/values-ka/strings.xml b/java/com/android/dialer/app/res/values-ka/strings.xml index dbb48f4f5..fd9351f54 100644 --- a/java/com/android/dialer/app/res/values-ka/strings.xml +++ b/java/com/android/dialer/app/res/values-ka/strings.xml @@ -80,6 +80,7 @@ "ლოდინის დამატება" "პარამეტრები" "სიმულატორი" + "ახალი UI მალსახმობის შექმნა" "ყველა კონტაქტი" "ტონალური კლავიატურის გამოყენება" "მიმდინარე ზარზე დაბრუნება" @@ -104,12 +105,14 @@ "%s წმ" "%s მინ %s წამ" "ერთიანი ქმედების რეჟიმის გაუქმება" - "ხმოვანი ფოსტა" - "ხმოვანი ფოსტა" - "დიახ" - "არა" + "წაშლა" + "გაუქმება" "გსურთ, წაშალოთ არჩეული %1$s?" "არჩეულია %1$s" + + ""გსურთ ამ ხმოვანი შეტყობინებების წაშლა? "" + ""გსურთ ამ ხმოვანი შეტყობინების წაშლა? "" + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-kk/strings.xml b/java/com/android/dialer/app/res/values-kk/strings.xml index 8dfe531a1..f1763a21a 100644 --- a/java/com/android/dialer/app/res/values-kk/strings.xml +++ b/java/com/android/dialer/app/res/values-kk/strings.xml @@ -80,6 +80,7 @@ "Күтуді қосу" "Параметрлер" "Симулятор" + "Жаңа пайдаланушы интерфейсінің пернелер тіркесімін жасау" "Барлық контактілер" "Сенсорлы әуенді пернетақта" "Қосылып тұрған қоңырауға оралу" @@ -104,12 +105,14 @@ "%s сек." "%s мин %s сек" "Топтама әрекеттер режимін жабу" - "дауыстық хабар" - "дауыстық хабарлар" - "Иә" - "Жоқ" + "Жою" + "Жабу" "Таңдалған %1$s хабарларын жою қажет пе?" "%1$s таңдалды" + + ""Осы дауыстық хабарларды жою қажет пе? "" + ""Осы дауыстық хабарды жою қажет пе? "" + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-km/strings.xml b/java/com/android/dialer/app/res/values-km/strings.xml index ed0db05e2..54f1a126a 100644 --- a/java/com/android/dialer/app/res/values-km/strings.xml +++ b/java/com/android/dialer/app/res/values-km/strings.xml @@ -80,6 +80,7 @@ "បញ្ចូល​ការ​រង់ចាំ" "ការកំណត់" "កម្មវិធីធ្វើ​ដូច​មែនទែន" + "បង្កើត​ផ្លូវកាត់ UI ថ្មី" "ទំនាក់ទំនង​ទាំងអស់" "ប្រើ​សំឡេង​ប៉ះ​បន្ទះ​លេខ" "កំពុង​ត្រឡប់​ទៅកាន់​ការ​ហៅ" @@ -104,12 +105,14 @@ "%s វិនាទី" "%s នាទី %s វិនាទី" "បោះបង់​មុខងារ​សកម្មភាព​ជា​ក្រុម" - "សារ​ជា​សំឡេង" - "សារ​ជា​សំឡេង" - "បាទ/ចាស" - "ទេ" + "លុប" + "បោះបង់" "លុប %1$s ដែល​បាន​ជ្រើសរើស?" "បាន​ជ្រើសរើស %1$s" + + ""លុប​សារ​ជា​សំឡេង​ទាំងនេះ? "" + ""លុប​សារ​ជា​សំឡេង​នេះ? "" + @string/call_log_header_today "%1$s នៅម៉ោង %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-kn/strings.xml b/java/com/android/dialer/app/res/values-kn/strings.xml index 932bc4035..d7f3aabbc 100644 --- a/java/com/android/dialer/app/res/values-kn/strings.xml +++ b/java/com/android/dialer/app/res/values-kn/strings.xml @@ -80,6 +80,7 @@ "ನಿರೀಕ್ಷೆಯನ್ನು ಸೇರಿಸಿ" "ಸೆಟ್ಟಿಂಗ್‌ಗಳು" "ಸಿಮ್ಯುಲೇಟರ್" + "ಹೊಸ UI ಶಾರ್ಟ್‌ಕಟ್ ರಚಿಸಿ" "ಎಲ್ಲಾ ಸಂಪರ್ಕಗಳು" "ಸ್ಪರ್ಶ ಟೋನ್ ಕೀಪ್ಯಾಡ್ ಬಳಸಿ" "ಪ್ರತ್ಯತ್ತರ ಕರೆಯು ಪ್ರಗತಿಯಲ್ಲಿದೆ" @@ -104,12 +105,14 @@ "%s ಸೆಕೆಂ" "%s ನಿಮಿ %s ಸೆಕೆಂ" "ಬ್ಯಾಚ್ ಕ್ರಿಯೆಗಳ ಮೋಡ್ ಅನ್ನು ರದ್ದುಮಾಡಿ" - "ಧ್ವನಿಮೇಲ್" - "ಧ್ವನಿಮೇಲ್‌ಗಳು" - "ಹೌದು" - "ಇಲ್ಲ" + "ಅಳಿಸಿ" + "ರದ್ದುಮಾಡಿ" "ಆಯ್ಕೆ ಮಾಡಲಾದ %1$s ಅನ್ನು ಅಳಿಸುವುದೇ?" "%1$s ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ" + + ""ಈ ಧ್ವನಿಮೇಲ್‌ಗಳನ್ನು ಅಳಿಸುವುದೇ? "" + ""ಈ ಧ್ವನಿಮೇಲ್‌ಗಳನ್ನು ಅಳಿಸುವುದೇ? "" + @string/call_log_header_today "%1$s ರಂದು %2$s ಗಂಟೆಗೆ" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ko/strings.xml b/java/com/android/dialer/app/res/values-ko/strings.xml index de6b93c01..cb2e83c79 100644 --- a/java/com/android/dialer/app/res/values-ko/strings.xml +++ b/java/com/android/dialer/app/res/values-ko/strings.xml @@ -80,6 +80,7 @@ "대기 시간 추가" "설정" "시뮬레이터" + "새 UI 바로가기 만들기" "모든 연락처" "터치톤 키패드 사용" "진행 중인 통화로 돌아가기" @@ -104,12 +105,14 @@ "%s초" "%s%s초" "일괄 작업 모드 취소" - "음성사서함" - "음성사서함" - "예" - "아니요" + "삭제" + "취소" "선택한 %1$s을(를) 삭제하시겠습니까?" "%1$s개 선택됨" + + ""이 음성사서함을 삭제하시겠습니까? "" + ""이 음성사서함을 삭제하시겠습니까? "" + @string/call_log_header_today "%1$s %2$s" "%1$02d%2$02d초" diff --git a/java/com/android/dialer/app/res/values-ky/strings.xml b/java/com/android/dialer/app/res/values-ky/strings.xml index ac9a617ed..0a0b3e661 100644 --- a/java/com/android/dialer/app/res/values-ky/strings.xml +++ b/java/com/android/dialer/app/res/values-ky/strings.xml @@ -80,6 +80,7 @@ "Тыныгуу кошуу" "Жөндөөлөр" "Симулятор" + "Жаңы интерфейс үчүн кыска жол түзүү" "Бардык байланыштар" "Тоналдык терүү тактасын колдонуу" "Токтотулган чалууга кайтуу" @@ -104,12 +105,14 @@ "%s сек." "%s мүн. %s сек." "Жапырт аракет режимин жокко чыгаруу" - "үн почтасы" - "үн почталары" - "Ооба" - "Жок" + "Жок кылуу" + "Жокко чыгаруу" "Тандалган %1$s жок кылынсынбы?" "%1$s тандалды" + + ""Бул үн почталар жок кылынсынбы? "" + ""Бул үн почта жок кылынсынбы? "" + @string/call_log_header_today "%1$s саат %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-lo/strings.xml b/java/com/android/dialer/app/res/values-lo/strings.xml index 2a829730f..267d1c6be 100644 --- a/java/com/android/dialer/app/res/values-lo/strings.xml +++ b/java/com/android/dialer/app/res/values-lo/strings.xml @@ -80,6 +80,7 @@ "ເພີ່ມການລໍຖ້າ" "ການ​ຕັ້ງ​ຄ່າ" "ຕົວຈຳລອງ" + "ສ້າງປຸ່ມລັດສ່ວນຕິດຕໍ່ຜູ້ໃຊ້ໃໝ່" "ລາຍຊື່ຜູ່ຕິດຕໍ່ທັງໝົດ" "ໃຊ້ປຸ່ມກົດສັນຍານສຽງ" "ກັບໄປການໂທທີ່ກຳລັງດຳເນີນຢູ່" @@ -104,12 +105,14 @@ "%s ວິນາທີ" "%s ນ​ທ %s ວິ" "ຍົກເລີກໂໝດຄຳສັ່ງເປັນຊຸດ" - "ຂໍ້ຄວາມສຽງ" - "ຂໍ້ຄວາມສຽງ" - "ແມ່ນແລ້ວ" - "ບໍ່" + "ລຶບ" + "ຍົກເລີກ" "ລຶບ %1$s ທີ່ເລືອກອອກໄປບໍ?" "ເລືອກ %1$s ລາຍການແລ້ວ" + + ""ລຶບຂໍ້ຄວາມສຽງເຫຼົ່ານີ້ບໍ? "" + ""ລຶບຂໍ້ຄວາມສຽງນີ້ບໍ? "" + @string/call_log_header_today "%1$s ເວລາ %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-lt/strings.xml b/java/com/android/dialer/app/res/values-lt/strings.xml index 367c928f4..e26a90927 100644 --- a/java/com/android/dialer/app/res/values-lt/strings.xml +++ b/java/com/android/dialer/app/res/values-lt/strings.xml @@ -82,6 +82,7 @@ "Pridėti laukimą" "Nustatymai" "Simuliatorius" + "Sukurti naują NS spart. klav." "Visi kontaktai" "Naudoti jutiklinę klaviatūrą" "Grįžti prie vykdomo skambučio" @@ -106,12 +107,16 @@ "%s sek." "%s min. %s sek." "Atšaukti masinių veiksmų režimą" - "balso pašto praneš." - "balso pašto praneš." - "Taip" - "Ne" + "Ištrinti" + "Atšaukti" "Ištrinti pasir. %1$s?" "Pasirinkta: %1$s" + + ""Ištrinti šiuos balso pašto pranešimus? "" + ""Ištrinti šiuos balso pašto pranešimus? "" + ""Ištrinti šiuos balso pašto pranešimus? "" + ""Ištrinti šiuos balso pašto pranešimus? "" + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-lv/strings.xml b/java/com/android/dialer/app/res/values-lv/strings.xml index 2713b91b6..8df2813c4 100644 --- a/java/com/android/dialer/app/res/values-lv/strings.xml +++ b/java/com/android/dialer/app/res/values-lv/strings.xml @@ -81,6 +81,7 @@ "Pievienot gaidīšanu" "Iestatījumi" "Simulators" + "Jaunās liet. saskarnes saīsne" "Visas kontaktpersonas" "Izmantot skārientoņu tastatūru" "Atgriezties pie pašreizējā zvana" @@ -105,12 +106,15 @@ "%s s" "%s min %s s" "Iziet no grupas darbību režīma" - "balss pasta ziņojums" - "balss pasta ziņojumi" - "Jā" - "Nē" + "Dzēst" + "Atcelt" "Vai dzēst atlasi: %1$s?" "Atlasīti: %1$s" + + ""Vai dzēst šos balss pasta ziņojumus? "" + ""Vai dzēst šos balss pasta ziņojumus? "" + ""Vai dzēst šos balss pasta ziņojumus? "" + @string/call_log_header_today "%1$s plkst. %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-mk/strings.xml b/java/com/android/dialer/app/res/values-mk/strings.xml index 09725a642..953a05569 100644 --- a/java/com/android/dialer/app/res/values-mk/strings.xml +++ b/java/com/android/dialer/app/res/values-mk/strings.xml @@ -80,6 +80,7 @@ "Додај почекај" "Поставки" "Симулатор" + "Создај крат. за нов интерфејс" "Сите контакти" "Користи тастатура со звуци на допир" "Врати се на повик во тек" @@ -104,12 +105,14 @@ "%s сек." "%s мин. %s сек." "Откажи го режимот на групни дејства" - "говорна пошта" - "говорни пораки" - "Да" - "Не" + "Избриши" + "Откажи" "Да се избришат избраните %1$s?" "Избрани се %1$s" + + ""Да се избришат говорните пораки? "" + ""Да се избришат говорните пораки? "" + @string/call_log_header_today "%1$s во %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ml/strings.xml b/java/com/android/dialer/app/res/values-ml/strings.xml index 7655dbe23..0eef40748 100644 --- a/java/com/android/dialer/app/res/values-ml/strings.xml +++ b/java/com/android/dialer/app/res/values-ml/strings.xml @@ -80,6 +80,7 @@ "കാത്തിരിക്കൽ ചേർക്കുക" "ക്രമീകരണം" "സിമുലേറ്റർ" + "പുതിയ UI കുറുക്കുവഴി സൃഷ്‌ടിക്കുക" "എല്ലാ കോൺടാക്റ്റുകളും" "ടച്ച് ടോൺ കീപാഡ് ഉപയോഗിക്കുക" "വിളിച്ചുകൊണ്ടിരിക്കുന്ന കോളിലേക്ക് മടങ്ങുക" @@ -104,12 +105,14 @@ "%s സെക്കൻഡ്" "%s മി. %s സെ." "\'ബാച്ച് പ്രവർത്തനങ്ങൾ\' മോഡ് റദ്ദാക്കുക" - "വോയ്‌സ്‌മെയിൽ" - "വോയ്‌സ്മെയിലുകൾ" - "അതെ" - "ഇല്ല" + "ഇല്ലാതാക്കുക" + "റദ്ദാക്കൂ" "തിരഞ്ഞെടുത്ത %1$s ഇല്ലാതാക്കണോ?" "%1$s എണ്ണം തിരഞ്ഞെടുത്തു" + + ""ഈ വോയ്‌സ്‌മെയിലുകൾ ഇല്ലാതാക്കണോ? "" + ""ഈ വോയ്‌സ്‌മെയിൽ ഇല്ലാതാക്കണോ? "" + @string/call_log_header_today "%1$s, %2$s-ന്" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-mn/strings.xml b/java/com/android/dialer/app/res/values-mn/strings.xml index 29bd8af42..e0cd98710 100644 --- a/java/com/android/dialer/app/res/values-mn/strings.xml +++ b/java/com/android/dialer/app/res/values-mn/strings.xml @@ -80,6 +80,7 @@ "Хүлээлт нэмэх" "Тохиргоо" "Симулятор" + "Шинэ UI үүсгэх товчлол" "Бүх харилцагчид" "Хүрэлтээр дуугардаг гар ашиглах" "Үргэлжилж буй дуудлага руу буцах" @@ -104,12 +105,14 @@ "%s сек" "%s минут %s секунд" "Багц үйлдлийн горимыг цуцлах" - "дуут шуудан" - "дуут шуудан" - "Тийм" - "Үгүй" + "Устгах" + "Цуцлах" "Сонгосон %1$s-г устгах уу?" "%1$s сонгосон" + + ""Эдгээр дуут шууданг устгах уу? "" + ""Энэ дуут шууданг устгах уу? "" + @string/call_log_header_today "%1$s %2$s-д" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-mr/strings.xml b/java/com/android/dialer/app/res/values-mr/strings.xml index ee21291e8..70e6d410c 100644 --- a/java/com/android/dialer/app/res/values-mr/strings.xml +++ b/java/com/android/dialer/app/res/values-mr/strings.xml @@ -80,6 +80,7 @@ "प्रतीक्षा करा जोडा" "सेटिंग्ज" "सिम्युलेटर" + "नवीन UI शॉर्टकट तयार करा" "सर्व संपर्क" "स्‍पर्श टोन कीपॅडचा वापर करा" "चालू असलेल्या कॉलवर परत जा" @@ -104,12 +105,14 @@ "%s सेकंद" "%s मिनिट %s सेकंद" "बॅच क्रिया मोड रद्द करा" - "व्हॉइसमेल" - "व्हॉइसमेल" - "होय" - "नाही" + "हटवा" + "रद्द करा" "निवडलेले %1$s हटवायचेे?" "%1$s निवडले" + + ""हा व्हॉइसमेल हटवायचा? "" + ""हे व्हॉइसमेल हटवायचे? "" + @string/call_log_header_today "%1$s रोजी %2$s वाजता" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ms/strings.xml b/java/com/android/dialer/app/res/values-ms/strings.xml index dbb021359..f58f08f02 100644 --- a/java/com/android/dialer/app/res/values-ms/strings.xml +++ b/java/com/android/dialer/app/res/values-ms/strings.xml @@ -80,6 +80,7 @@ "Tambah penungguan" "Tetapan" "Simulator" + "Buat Pintasan UI Baharu" "Semua kenalan" "Gunakan pad kekunci nada sentuh" "Kembali ke panggilan yang sedang berlangsung" @@ -104,12 +105,14 @@ "%s saat" "%s min %s saat" "Batalkan mod tindakan kelompok" - "mel suara" - "mel suara" - "Ya" - "Tidak" + "Padam" + "Batal" "Padam %1$s yang dipilih?" "%1$s dipilih" + + ""Padamkan mel suara ini? "" + ""Padamkan mel suara ini? "" + @string/call_log_header_today "%1$s pada %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-my/strings.xml b/java/com/android/dialer/app/res/values-my/strings.xml index eecfeb234..60c3271a0 100644 --- a/java/com/android/dialer/app/res/values-my/strings.xml +++ b/java/com/android/dialer/app/res/values-my/strings.xml @@ -80,6 +80,7 @@ "စောင့်ဆိုင်းခြင်း ထည့်ပါ" "ဆက်တင်များ" "အသစ်ကဲ့သို့ တုပသည့်စနစ်" + "UI ဖြတ်လမ်းလင့်ခ်အသစ် လုပ်ရန်" "လိပ်စာများအားလုံး" "touch tone ကီးခလုတ် ကိုအသုံးပြုပါ" "ဖုန်းပြန်ခေါ်မှု ပြုလုပ်နေစဉ်" @@ -104,12 +105,14 @@ "%s စက္ကန့်" "%s မိနစ် %s စက္ကန့်" "တပြိုင်နက်တည်း စုပြုံလုပ်ဆောင်ချက်များမုဒ်ကိ ပယ်ဖျက်ရန်" - "အသံမေးလ်" - "အသံမေးလ်များ" - "Yes" - "No" + "ဖျက်ပါ" + "မလုပ်တော့" "ရွေးထားသော %1$s ကို ဖျက်လိုပါသလား။" "%1$s ကို ရွေးချယ်ထားသည်" + + ""ဤအသံမေးလ်များကို ဖျက်မလား။ "" + ""ဤအသံမေးလ်ကို ဖျက်မလား။ "" + @string/call_log_header_today "%1$s %2$s ၌" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-nb/strings.xml b/java/com/android/dialer/app/res/values-nb/strings.xml index bda4915b5..344a26a51 100644 --- a/java/com/android/dialer/app/res/values-nb/strings.xml +++ b/java/com/android/dialer/app/res/values-nb/strings.xml @@ -80,6 +80,7 @@ "Legg til Vent" "Innstillinger" "Simulator" + "Nytt grensesnitt – lag snarvei" "Alle kontakter" "Bruk tonetastatur" "Gå tilbake til aktiv samtale" @@ -104,12 +105,14 @@ "%s sek" "%s min %s sek" "Avbryt massehandlinsmodus" - "talepost" - "talepost" - "Ja" - "Nei" + "Slett" + "Avbryt" "Slett markert %1$s?" "%1$s er valgt" + + ""Vil du slette disse talemeldingene? "" + ""Vil du slette denne talemeldingen? "" + @string/call_log_header_today "%1$s kl. %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ne/strings.xml b/java/com/android/dialer/app/res/values-ne/strings.xml index 8262a316c..5e70c40b6 100644 --- a/java/com/android/dialer/app/res/values-ne/strings.xml +++ b/java/com/android/dialer/app/res/values-ne/strings.xml @@ -80,6 +80,7 @@ "पर्खाइ थप्नुहोस्" "सेटिङ्हरू" "सिम्युलेटर" + "नयाँ UI सर्टकट सिर्जना गर्ने" "सबै सम्पर्कहरू" "स्पर्श टोन किप्याडको प्रयोग गर्नुहोस्" "हुदै गरेको कलमा फर्कनुहोस्" @@ -104,12 +105,14 @@ "%s सेकेन्ड" "%s मिनेट %s सकेन्ड" "ब्याच सम्बन्धी कारबाहीको मोडलाई रद्द गर्नुहोस्" - "भ्वाइस मेल" - "भ्वाइस मेलहरू" - "हो" - "होइन" + "मेट्नुहोस्" + "रद्द गर्नुहोस्" "चयन गरिएका %1$s लाई मेटाउने हो?" "%1$s चयन गरियो" + + ""यी भ्वाइस मेलहरू मेट्ने हो? "" + ""यो भ्वाइस मेल मेट्ने हो? "" + @string/call_log_header_today "%1$s मा %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-nl/strings.xml b/java/com/android/dialer/app/res/values-nl/strings.xml index eed412d69..dbd29bc78 100644 --- a/java/com/android/dialer/app/res/values-nl/strings.xml +++ b/java/com/android/dialer/app/res/values-nl/strings.xml @@ -80,6 +80,7 @@ "Wachten toevoegen" "Instellingen" "Simulator" + "Snelkoppeling voor nieuwe UI" "Alle contacten" "Toetsen voor toonkiezen gebruiken" "Terug naar actief gesprek" @@ -104,12 +105,14 @@ "%s sec." "%s min. %s sec." "Modus voor batchacties annuleren" - "voicemail" - "voicemails" - "Ja" - "Nee" + "Verwijderen" + "Annuleren" "Geselecteerde %1$s verwijderen?" "%1$s geselecteerd" + + ""Deze voicemails verwijderen? "" + ""Deze voicemail verwijderen? "" + @string/call_log_header_today "%1$s om %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-no/strings.xml b/java/com/android/dialer/app/res/values-no/strings.xml index bda4915b5..344a26a51 100644 --- a/java/com/android/dialer/app/res/values-no/strings.xml +++ b/java/com/android/dialer/app/res/values-no/strings.xml @@ -80,6 +80,7 @@ "Legg til Vent" "Innstillinger" "Simulator" + "Nytt grensesnitt – lag snarvei" "Alle kontakter" "Bruk tonetastatur" "Gå tilbake til aktiv samtale" @@ -104,12 +105,14 @@ "%s sek" "%s min %s sek" "Avbryt massehandlinsmodus" - "talepost" - "talepost" - "Ja" - "Nei" + "Slett" + "Avbryt" "Slett markert %1$s?" "%1$s er valgt" + + ""Vil du slette disse talemeldingene? "" + ""Vil du slette denne talemeldingen? "" + @string/call_log_header_today "%1$s kl. %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-pa/strings.xml b/java/com/android/dialer/app/res/values-pa/strings.xml index 8e6540727..33afd5824 100644 --- a/java/com/android/dialer/app/res/values-pa/strings.xml +++ b/java/com/android/dialer/app/res/values-pa/strings.xml @@ -80,6 +80,7 @@ "ਉਡੀਕ ਜੋੜੋ" "ਸੈਟਿੰਗਾਂ" "ਸਿਮੁਲੇਟਰ" + "ਨਵਾਂ UI ਸ਼ਾਰਟਕੱਟ ਬਣਾਓ" "ਸਾਰੇ ਸੰਪਰਕ" "ਟਚ ਟੋਨ ਕੀਪੈਡ ਵਰਤੋ" "ਪ੍ਰਗਤੀ ਵਿੱਚ ਕਾਲ ਤੇ ਵਾਪਸ ਜਾਓ" @@ -104,12 +105,14 @@ "%s ਸਕਿੰਟ" "%s ਮਿੰਟ %s ਸਕਿੰਟ" "ਬੈਚ ਕਾਰਵਾਈਆਂ ਮੋਡ ਨੂੰ ਰੱਦ ਕਰੋ" - "ਵੌਇਸਮੇਲ" - "ਵੌਇਸਮੇਲਾਂ" - "ਹਾਂ" - "ਨਹੀਂ" + "ਮਿਟਾਓ" + "ਰੱਦ ਕਰੋ" "ਕੀ ਚੁਣੀ(ਆਂ) ਹੋਈ(ਆਂ) %1$s ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?" "%1$s ਨੂੰ ਚੁਣਿਆ ਗਿਆ" + + ""ਕੀ ਇਸ ਵੌਇਸਮੇਲ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ? "" + ""ਕੀ ਇਹਨਾਂ ਵੌਇਸਮੇਲਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ? "" + @string/call_log_header_today "%1$s ਨੂੰ %2$s ਵਜੇ" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-pl/strings.xml b/java/com/android/dialer/app/res/values-pl/strings.xml index 8f57a82b4..7f6027c51 100644 --- a/java/com/android/dialer/app/res/values-pl/strings.xml +++ b/java/com/android/dialer/app/res/values-pl/strings.xml @@ -82,6 +82,7 @@ "Dodaj oczekiwanie" "Ustawienia" "Symulator" + "Utwórz skrót do nowego interfejsu" "Wszystkie kontakty" "Użyj klawiatury tonowej" "Wróć do aktywnego połączenia" @@ -106,12 +107,16 @@ "%s s" "%s min %s s" "Anuluj tryb działań zbiorczych" - "wiadomości głosowe" - "wiadomości głosowe" - "Tak" - "Nie" + "Usuń" + "Anuluj" "Usunąć wybrane %1$s?" "Wybrane: %1$s" + + ""Usunąć te wiadomości głosowe? "" + ""Usunąć te wiadomości głosowe? "" + ""Usunąć te wiadomości głosowe? "" + ""Usunąć tę wiadomość głosową? "" + @string/call_log_header_today "%1$s o %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-pt-rBR/strings.xml b/java/com/android/dialer/app/res/values-pt-rBR/strings.xml index eb61923e9..768ce57d4 100644 --- a/java/com/android/dialer/app/res/values-pt-rBR/strings.xml +++ b/java/com/android/dialer/app/res/values-pt-rBR/strings.xml @@ -80,6 +80,7 @@ "Adicionar espera" "Configurações" "Simulador" + "Criar atalho para a nova IU" "Todos os contatos" "Usar teclado multifrequencial" "Retornar para a chamada em espera" @@ -104,12 +105,14 @@ "%s seg" "%s m %s s" "Cancelar modo de ações em lote" - "correio de voz" - "correios de voz" - "Sim" - "Não" + "Excluir" + "Cancelar" "Excluir a seleção de %1$s?" "Itens selecionados: %1$s" + + ""Excluir este correio de voz? "" + ""Excluir estes correios de voz? "" + @string/call_log_header_today "%1$s às %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-pt-rPT/strings.xml b/java/com/android/dialer/app/res/values-pt-rPT/strings.xml index 493f846c4..3c636e1d6 100644 --- a/java/com/android/dialer/app/res/values-pt-rPT/strings.xml +++ b/java/com/android/dialer/app/res/values-pt-rPT/strings.xml @@ -80,6 +80,7 @@ "Adicionar espera" "Definições" "Simulador" + "Criar novo atalho de IU" "Todos os contactos" "Utilizar teclado numérico com tons de toque" "Voltar à chamada em curso" @@ -104,12 +105,14 @@ "%s seg" "%s min. %s seg." "Cancelar modo de ações em lote" - "mensagem de correio de voz" - "mensagens de correio de voz" - "Sim" - "Não" + "Eliminar" + "Cancelar" "Pretende eliminar a(s) %1$s selecionada(s)?" "%1$s selecionada(s)" + + ""Pretende eliminar esta(s) mensagem(ns) de correio de voz? "" + ""Pretende eliminar estas mensagens de correio de voz? "" + @string/call_log_header_today "%1$s às %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-pt/strings.xml b/java/com/android/dialer/app/res/values-pt/strings.xml index eb61923e9..768ce57d4 100644 --- a/java/com/android/dialer/app/res/values-pt/strings.xml +++ b/java/com/android/dialer/app/res/values-pt/strings.xml @@ -80,6 +80,7 @@ "Adicionar espera" "Configurações" "Simulador" + "Criar atalho para a nova IU" "Todos os contatos" "Usar teclado multifrequencial" "Retornar para a chamada em espera" @@ -104,12 +105,14 @@ "%s seg" "%s m %s s" "Cancelar modo de ações em lote" - "correio de voz" - "correios de voz" - "Sim" - "Não" + "Excluir" + "Cancelar" "Excluir a seleção de %1$s?" "Itens selecionados: %1$s" + + ""Excluir este correio de voz? "" + ""Excluir estes correios de voz? "" + @string/call_log_header_today "%1$s às %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ro/strings.xml b/java/com/android/dialer/app/res/values-ro/strings.xml index 93d01888a..b85f84987 100644 --- a/java/com/android/dialer/app/res/values-ro/strings.xml +++ b/java/com/android/dialer/app/res/values-ro/strings.xml @@ -81,6 +81,7 @@ "Adăugați interval de așteptare" "Setări" "Simulator" + "Creați comandă rapidă IU nouă" "Toată agenda" "Tastatura tactilă cu sunet" "Reveniți la apelul în curs" @@ -105,12 +106,15 @@ "%s secunde" "%s min. %s sec." "Anulați modul de acțiuni în lot" - "mesagerie vocală" - "mesaje vocale" - "Da" - "Nu" + "Ștergeți" + "Anulați" "Ștergeți cele %1$s selectate?" "%1$s selectate" + + ""Ștergeți aceste mesaje vocale? "" + ""Ștergeți aceste mesaje vocale? "" + ""Ștergeți acest mesaj vocal? "" + @string/call_log_header_today "%1$s la %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ru/strings.xml b/java/com/android/dialer/app/res/values-ru/strings.xml index 54278c40b..91441cc56 100644 --- a/java/com/android/dialer/app/res/values-ru/strings.xml +++ b/java/com/android/dialer/app/res/values-ru/strings.xml @@ -82,6 +82,7 @@ "Добавить паузу" "Настройки" "Симулятор" + "Создать ярлык для нового интерфейса" "Все контакты" "Панель тонального набора" "Вернуться к текущему вызову" @@ -106,12 +107,16 @@ "%s сек." "%s мин. %s сек." "Отмена режима массового действия" - "голосовое сообщение" - "голосовые сообщения" - "Да" - "Нет" + "Удалить" + "Отмена" "Удалить %1$s?" "Выбрано: %1$s" + + ""Удалить эти голосовые сообщения? "" + ""Удалить эти голосовые сообщения? "" + ""Удалить эти голосовые сообщения? "" + ""Удалить эти голосовые сообщения? "" + @string/call_log_header_today "%1$s в %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-si/strings.xml b/java/com/android/dialer/app/res/values-si/strings.xml index 63634577f..8a748d53c 100644 --- a/java/com/android/dialer/app/res/values-si/strings.xml +++ b/java/com/android/dialer/app/res/values-si/strings.xml @@ -80,6 +80,7 @@ "රැඳී සිටීම එක් කරන්න" "සැකසීම්" "සමාකෘතිය" + "නව UI කෙටිමග තනන්න" "සියලුම සම්බන්ධතා" "ස්පර්ශ නාද යතුරුපෑඩය භාවිතා කරන්න" "පවතින ඇමතුමට නැවත යන්න" @@ -104,12 +105,14 @@ "තත් %s" "මිනි %s තත් %s" "කාණ්ඩ ක්‍රියා ප්‍රකාරය අවලංගු කරන්න" - "හඬ තැපෑල" - "හඬ තැපැල්" - "ඔව්" - "නැත" + "මකන්න" + "අවලංගු කරන්න" "තෝරා ගත් %1$s මකන්නද?" "%1$s තෝරා ගන්නා ලදි" + + ""මෙම හඬ තැපැල් මකන්නද? "" + ""මෙම හඬ තැපැල් මකන්නද? "" + @string/call_log_header_today "%1$s දින %2$sට" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-sk/strings.xml b/java/com/android/dialer/app/res/values-sk/strings.xml index f7bf4237c..e84febb17 100644 --- a/java/com/android/dialer/app/res/values-sk/strings.xml +++ b/java/com/android/dialer/app/res/values-sk/strings.xml @@ -82,6 +82,7 @@ "Pridať čakanie" "Nastavenia" "Simulátor" + "Vyt. skratku na nové rozhranie" "Všetky kontakty" "Použiť dotykovú tónovú klávesnicu" "Návrat k prebiehajúcemu hovoru" @@ -106,12 +107,16 @@ "%s s" "%s min. %s s" "Zrušiť režim hromadných akcií" - "hlasová správa" - "hlasové správy" - "Áno" - "Nie" + "Odstrániť" + "Zrušiť" "Chcete odstrániť vybraté položky (%1$s)?" "Vybraté: %1$s" + + ""Chcete odstrániť tieto hlasové správy? "" + ""Chcete odstrániť tieto hlasové správy? "" + ""Chcete odstrániť tieto hlasové správy? "" + ""Chcete odstrániť túto hlasovú správu? "" + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-sl/strings.xml b/java/com/android/dialer/app/res/values-sl/strings.xml index d3c57dd92..495b6e802 100644 --- a/java/com/android/dialer/app/res/values-sl/strings.xml +++ b/java/com/android/dialer/app/res/values-sl/strings.xml @@ -82,6 +82,7 @@ "Dodaj premor" "Nastavitve" "Simulator" + "Ustvari bliž. za novi up. vm." "Vsi stiki" "Uporabi številčnico za tonsko klicanje" "Nazaj na klic, ki poteka" @@ -106,12 +107,16 @@ "%s s" "%s min %s s" "Prekliči način množičnega dejanja" - "sporočilo v odzivniku" - "sporočila v odzivniku" - "Da" - "Ne" + "Izbriši" + "Prekliči" "Želite izbrisati %1$s?" "Št. izbranih: %1$s" + + ""Želite izbrisati ta sporočila v odzivniku? "" + ""Želite izbrisati ta sporočila v odzivniku? "" + ""Želite izbrisati ta sporočila v odzivniku? "" + ""Želite izbrisati ta sporočila v odzivniku? "" + @string/call_log_header_today "%1$s ob %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-sq/strings.xml b/java/com/android/dialer/app/res/values-sq/strings.xml index 84704459c..809fd8a22 100644 --- a/java/com/android/dialer/app/res/values-sq/strings.xml +++ b/java/com/android/dialer/app/res/values-sq/strings.xml @@ -80,6 +80,7 @@ "Shto një pritje" "Cilësimet" "Simuluesi" + "Krijo një shkurtore për ndërfaqen e re të përdoruesit" "Të gjitha kontaktet" "Përdor bllokun e tasteve" "Kthehu te telefonata" @@ -104,12 +105,14 @@ "%s sekonda" "%s min. e %s sek." "Anulo modalitetin e veprimeve në grup" - "posta zanore" - "postat zanore" - "Po" - "Jo" + "Fshi" + "Anulo" "Të fshihen %1$s të zgjedhura?" "%1$s të zgjedhura" + + ""Të fshihen këto posta zanore? "" + ""Të fshihet kjo postë zanore? "" + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-sr/strings.xml b/java/com/android/dialer/app/res/values-sr/strings.xml index 6cf7a7c85..6f85c0ba8 100644 --- a/java/com/android/dialer/app/res/values-sr/strings.xml +++ b/java/com/android/dialer/app/res/values-sr/strings.xml @@ -81,6 +81,7 @@ "Додај чекање" "Подешавања" "Симулатор" + "Направите пречицу за нови UI" "Сви контакти" "Употребите бројчаник за тонско бирање" "Врати се на позив који је у току" @@ -105,12 +106,15 @@ "%s сек" "%s мин %s сек" "Откажите режим групних радњи" - "говорну поруку" - "говорне поруке" - "Да" - "Не" + "Избриши" + "Откажи" "Желите ли да избришете изабрану(е) %1$s?" "Изабраних: %1$s" + + ""Желите ли да избришете ове говорне поруке? "" + ""Желите ли да избришете ове говорне поруке? "" + ""Желите ли да избришете ове говорне поруке? "" + @string/call_log_header_today "%1$s у %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-sv/strings.xml b/java/com/android/dialer/app/res/values-sv/strings.xml index 71ef3e55b..e8446cab1 100644 --- a/java/com/android/dialer/app/res/values-sv/strings.xml +++ b/java/com/android/dialer/app/res/values-sv/strings.xml @@ -80,6 +80,7 @@ "Lägg till väntetid" "Inställningar" "Simulator" + "Skapa genväg till anv.gränssn." "Alla kontakter" "Använd tonvalstelefon" "Återvänd till pågående samtal" @@ -104,12 +105,14 @@ "%s sekund" "%s min %s sek" "Avbryt läget för massåtgärd" - "röstbrevlåda" - "röstmeddelanden" - "Ja" - "Nej" + "Radera" + "Avbryt" "Vill du radera markerade %1$s?" "%1$s har markerats" + + ""Vill du ta bort dessa röstmeddelanden? "" + ""Vill du ta bort det här röstmeddelandet? "" + @string/call_log_header_today "%1$s kl. %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-sw/strings.xml b/java/com/android/dialer/app/res/values-sw/strings.xml index 9cbdd3e8e..142aaf0de 100644 --- a/java/com/android/dialer/app/res/values-sw/strings.xml +++ b/java/com/android/dialer/app/res/values-sw/strings.xml @@ -80,6 +80,7 @@ "Ongeza kusubiri" "Mipangilio" "Kielelezo" + "Unda Mkato Mpya wa Kiolesura" "Anwani zote" "Tumia kibao cha kuchapa cha sauti na kugusa" "Rudi kwa simu inayoendelea" @@ -104,12 +105,14 @@ "Sekunde %s" "Dak %s sek %s" "Ghairi hali ya kutekeleza vitendo vingi" - "ujumbe wa sauti" - "ujumbe wa sauti" - "Ndiyo" - "Hapana" + "Futa" + "Ghairi" "Je, ungependa kufuta %1$s uliochagua?" "%1$s zimechaguliwa" + + ""Je, unataka kufuta kila ujumbe wa sauti ulioonyeshwa? "" + ""Je, unataka kufuta ujumbe huu wa sauti? "" + @string/call_log_header_today "%1$s saa %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ta/strings.xml b/java/com/android/dialer/app/res/values-ta/strings.xml index a91088c4f..e270a3cee 100644 --- a/java/com/android/dialer/app/res/values-ta/strings.xml +++ b/java/com/android/dialer/app/res/values-ta/strings.xml @@ -80,6 +80,7 @@ "காத்திருப்பைச் சேர்" "அமைப்பு" "சிமுலேட்டர்" + "புதிய UI குறுக்குவழியை உருவாக்கு" "எல்லா தொடர்புகளும்" "டச் டோன் விசைப்பலகையைப் பயன்படுத்தவும்" "செயலிலுள்ள அழைப்பிற்குத் திரும்பு" @@ -104,12 +105,14 @@ "%s வி" "%s நிமிடம் %s வினாடி" "தொகுப்புச் செயல்கள் பயன்முறையை ரத்துசெய்யும்" - "குரலஞ்சல்" - "குரலஞ்சல்கள்" - "ஆம்" - "வேண்டாம்" + "நீக்கு" + "ரத்துசெய்" "தேர்ந்தெடுத்த %1$sஐ நீக்கவா?" "%1$s தேர்ந்தெடுக்கப்பட்டன" + + ""இந்தக் குரலஞ்சல்களை நீக்கவா? "" + ""இந்தக் குரலஞ்சலை நீக்கவா? "" + @string/call_log_header_today "%1$s அன்று %2$s மணிக்கு" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-te/strings.xml b/java/com/android/dialer/app/res/values-te/strings.xml index aecc1c4b9..8d2c66784 100644 --- a/java/com/android/dialer/app/res/values-te/strings.xml +++ b/java/com/android/dialer/app/res/values-te/strings.xml @@ -80,6 +80,7 @@ "నిరీక్షణ సమయాన్ని జోడించు" "సెట్టింగ్‌లు" "సిములేటర్" + "కొత్త UI సత్వరమార్గం సృష్టించు" "అన్ని పరిచయాలు" "టచ్ టోన్ కీప్యాడ్‌ను ఉపయోగించండి" "ప్రోగ్రెస్‌లో ఉన్న కాల్‌కు వెళ్లు" @@ -104,12 +105,14 @@ "%s సెక" "%s నిమి %s సెక" "సమూహ చర్యల మోడ్‌ను రద్దు చేస్తుంది" - "వాయిస్ మెయిల్" - "వాయిస్ మెయిల్‌లు" - "అవును" - "వద్దు" + "తొలగించు" + "రద్దు చేయి" "ఎంచుకున్న %1$sను తొలగించాలా?" "%1$s ఎంచుకోబడ్డాయి" + + ""ఈ వాయిస్ మెయిల్‌లను తొలగించాలా? "" + ""ఈ వాయిస్ మెయిల్‌ను తొలగించాలా? "" + @string/call_log_header_today "%1$s %2$sకి" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-th/strings.xml b/java/com/android/dialer/app/res/values-th/strings.xml index 58507b49e..76a66e20e 100644 --- a/java/com/android/dialer/app/res/values-th/strings.xml +++ b/java/com/android/dialer/app/res/values-th/strings.xml @@ -80,6 +80,7 @@ "เพิ่มการรอ" "การตั้งค่า" "เครื่องมือจำลอง" + "สร้างทางลัด UI ใหม่" "รายชื่อติดต่อทั้งหมด" "ใช้ปุ่มกดสัญญาณเสียง" "กลับไปคุยสายต่อ" @@ -104,12 +105,14 @@ "%s วินาที" "%s นาที %s วินาที" "ยกเลิกโหมดการทำงานแบบกลุ่ม" - "ข้อความเสียง" - "ข้อความเสียง" - "ใช่" - "ไม่" + "ลบ" + "ยกเลิก" "ลบ%1$sที่เลือกหรือไม่" "เลือกไว้ %1$s รายการ" + + ""ลบข้อความเสียงเหล่านี้ไหม "" + ""ลบข้อความเสียงนี้ไหม "" + @string/call_log_header_today "วันที่ %1$s เวลา %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-tl/strings.xml b/java/com/android/dialer/app/res/values-tl/strings.xml index 9a8157fea..51e7a6659 100644 --- a/java/com/android/dialer/app/res/values-tl/strings.xml +++ b/java/com/android/dialer/app/res/values-tl/strings.xml @@ -80,6 +80,7 @@ "Magdagdag ng paghihintay" "Mga Setting" "Simulator" + "Gawa ng Shortcut ng Bagong UI" "Lahat ng mga contact" "Gumamit ng touch tone na keypad" "Bumalik sa kasalukuyang tawag" @@ -104,12 +105,14 @@ "%s sec" "%s min %s sec" "Kanselahin ang batch actions mode" - "voicemail" - "mga voicemail" - "Oo" - "Hindi" + "I-delete" + "Kanselahin" "I-delete ang napiling %1$s?" "%1$s ang napili" + + ""I-delete ang mga voicemail na ito? "" + ""I-delete ang mga voicemail na ito? "" + @string/call_log_header_today "%1$s ng %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-tr/strings.xml b/java/com/android/dialer/app/res/values-tr/strings.xml index 17bd6645c..1ff0128d4 100644 --- a/java/com/android/dialer/app/res/values-tr/strings.xml +++ b/java/com/android/dialer/app/res/values-tr/strings.xml @@ -80,6 +80,7 @@ "Bekleme ekle" "Ayarlar" "Simülatör" + "Kull. Arayüzü Kısayolu Oluştur" "Tüm kişiler" "Telefon tuş takımını kullan" "Çağrıya dön" @@ -104,12 +105,14 @@ "%s sn." "%s dk. %s sn." "Toplu işlemler modu iptal edilir" - "sesli mesaj" - "sesli mesajlar" - "Evet" - "Hayır" + "Sil" + "İptal" "Seçili %1$s silinsin mi?" "%1$s öğe seçildi" + + ""Bu sesli mesajlar silinsin mi? "" + ""Bu sesli mesaj silinsin mi? "" + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-uk/strings.xml b/java/com/android/dialer/app/res/values-uk/strings.xml index a020a1f1b..b92970daa 100644 --- a/java/com/android/dialer/app/res/values-uk/strings.xml +++ b/java/com/android/dialer/app/res/values-uk/strings.xml @@ -82,6 +82,7 @@ "Додати паузу" "Налаштування" "Симулятор" + "Створити ярлик для нової дії" "Усі контакти" "Використовувати тональний набір" "Повернутися до поточного виклику" @@ -106,12 +107,16 @@ "%s с" "%s хв %s с" "Скасувати режим масових дій" - "голосова пошта" - "голосова пошта" - "Так" - "Ні" + "Видалити" + "Скасувати" "Видалити вибране (%1$s)?" "Вибрано %1$s" + + ""Видалити ці повідомлення голосової пошти? "" + ""Видалити ці повідомлення голосової пошти? "" + ""Видалити ці повідомлення голосової пошти? "" + ""Видалити ці повідомлення голосової пошти? "" + @string/call_log_header_today "%1$s о %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-ur/strings.xml b/java/com/android/dialer/app/res/values-ur/strings.xml index d696bd54c..cb2eb9e33 100644 --- a/java/com/android/dialer/app/res/values-ur/strings.xml +++ b/java/com/android/dialer/app/res/values-ur/strings.xml @@ -80,6 +80,7 @@ "انتظار شامل کریں" "ترتیبات" "Simulator" + "‏نیا UI شارٹ کٹ تخلیق کریں" "سبھی رابطے" "ٹچ ٹون کی پیڈ کا استعمال کریں" "جاری کال پر واپس لوٹیں" @@ -104,12 +105,14 @@ "%s سیکنڈ" "%s منٹ %s سیکنڈ" "بیچ کاروائی موڈ منسوخ کریں" - "صوتی میل" - "صوتی میلز" - "ہاں" - "نہیں" + "حذف کریں" + "منسوخ کریں" "منتخب کردہ %1$s حذف کریں؟" "%1$s منتخب کردہ" + + ""ان صوتی میلز کو حذف کریں؟ "" + ""اس صوتی میل کو حذف کریں؟ "" + @string/call_log_header_today "%1$s بوقت %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-uz/strings.xml b/java/com/android/dialer/app/res/values-uz/strings.xml index aa645bf88..c7d08f3bf 100644 --- a/java/com/android/dialer/app/res/values-uz/strings.xml +++ b/java/com/android/dialer/app/res/values-uz/strings.xml @@ -80,6 +80,7 @@ "Kutishni qo‘shish" "Sozlamalar" "Simulyator" + "Yangi interfeys uchun yorliq" "Barcha kontaktlar" "Tovushli raqam tergich" "Amaldagi chaqiruvga qaytish" @@ -104,12 +105,14 @@ "%s soniya" "%s daq %s son" "Yoppasiga bajariladigan amallar rejimini bekor qilish" - "ovozli xabar" - "ovozli xabarlar" - "Ha" - "Yo‘q" + "O‘chirish" + "Bekor qilish" "Tanlangan %1$s o‘chirib tashlansinmi?" "Tanlandi: %1$s" + + ""Bu ovozli xabarlar o‘chirib tashlansinmi? "" + ""Bu ovozli xabar o‘chirib tashlansinmi? "" + @string/call_log_header_today "%1$s, %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-vi/strings.xml b/java/com/android/dialer/app/res/values-vi/strings.xml index dda7c1523..c79e1ed20 100644 --- a/java/com/android/dialer/app/res/values-vi/strings.xml +++ b/java/com/android/dialer/app/res/values-vi/strings.xml @@ -80,6 +80,7 @@ "Thêm chờ" "Cài đặt" "Trình mô phỏng" + "Tạo phím tắt giao diện người dùng mới" "Tất cả liên hệ" "Sử dụng bàn phím số cảm ứng có âm" "Quay lại cuộc gọi đang thực hiện" @@ -104,12 +105,14 @@ "%s giây" "%s phút %s giây" "Hủy chế độ tác vụ hàng loạt" - "thư thoại" - "thư thoại" - "Có" - "Không" + "Xóa" + "Hủy" "Xóa %1$s đã chọn?" "Đã chọn %1$s" + + ""Xóa các thư thoại này? "" + ""Xóa thư thoại này? "" + @string/call_log_header_today "%1$s lúc %2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-zh-rCN/strings.xml b/java/com/android/dialer/app/res/values-zh-rCN/strings.xml index 672614e48..3262c1a02 100644 --- a/java/com/android/dialer/app/res/values-zh-rCN/strings.xml +++ b/java/com/android/dialer/app/res/values-zh-rCN/strings.xml @@ -80,6 +80,7 @@ "延长等待时间" "设置" "模拟器" + "创建可在新界面中使用的快捷键" "所有联系人" "使用按键式键盘" "返回正在进行的通话" @@ -104,12 +105,14 @@ "%s 秒" "%s 分钟 %s 秒" "取消批量操作模式" - "语音邮件" - "语音邮件" - "是" - "否" + "删除" + "取消" "要删除所选的%1$s吗?" "已选择 %1$s 封" + + ""要删除这些语音邮件吗?"" + ""要删除这封语音邮件吗?"" + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-zh-rHK/strings.xml b/java/com/android/dialer/app/res/values-zh-rHK/strings.xml index f3dc44baf..71e62eddc 100644 --- a/java/com/android/dialer/app/res/values-zh-rHK/strings.xml +++ b/java/com/android/dialer/app/res/values-zh-rHK/strings.xml @@ -80,6 +80,7 @@ "新增插播功能" "設定" "模擬器" + "建立新使用者介面捷徑" "所有聯絡人" "使用觸控音頻按鍵" "返回進行中的通話" @@ -104,12 +105,14 @@ "%s 秒" "%s%s 秒" "取消批量操作模式" - "留言" - "留言" - "是" - "否" + "刪除" + "取消" "要刪除所選的%1$s嗎?" "已選取 %1$s 個" + + ""要刪除這些留言嗎?"" + ""要刪除此留言嗎?"" + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-zh-rTW/strings.xml b/java/com/android/dialer/app/res/values-zh-rTW/strings.xml index 473955c5d..9178dcf67 100644 --- a/java/com/android/dialer/app/res/values-zh-rTW/strings.xml +++ b/java/com/android/dialer/app/res/values-zh-rTW/strings.xml @@ -80,6 +80,7 @@ "延長等待時間" "設定" "模擬工具" + "建立新版 UI 捷徑" "所有聯絡人" "使用觸控音按鍵" "返回進行中的通話" @@ -104,12 +105,14 @@ "%s 秒" "%s%s 秒" "取消批次操作模式" - "語音留言" - "語音留言" - "是" - "否" + "刪除" + "取消" "要刪除選取的%1$s嗎?" "已選取 %1$s 個" + + ""要刪除這些語音留言嗎?"" + ""要刪除這則語音留言嗎?"" + @string/call_log_header_today "%1$s%2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values-zu/strings.xml b/java/com/android/dialer/app/res/values-zu/strings.xml index 93843aa2c..f52f597c8 100644 --- a/java/com/android/dialer/app/res/values-zu/strings.xml +++ b/java/com/android/dialer/app/res/values-zu/strings.xml @@ -80,6 +80,7 @@ "Yengeza ukulinda" "Izilungiselelo" "Isilingisi" + "Dala isinqamuleli esisha se-UI" "Bonke othintana nabo" "Sebenzisa ikhiphedi yethoni yokuthinta" "Buyela kukholi eqhubekayo" @@ -104,12 +105,14 @@ "%s isekhondi" "%s amaminithi %s amasekhondi" "Khansela imodi lezenzo zeqoqo" - "ivoyisimeyili" - "ama-meyli ezwi" - "Yebo" - "Cha" + "Susa" + "Khansela" "Susa okukhethiwe %1$s?" "Engu-%1$s ekhethiwe" + + ""Sula lawa mavoyisimeyili? "" + ""Sula lawa mavoyisimeyili? "" + @string/call_log_header_today "%1$s ngo-%2$s" "%1$02d:%2$02d" diff --git a/java/com/android/dialer/app/res/values/dimens.xml b/java/com/android/dialer/app/res/values/dimens.xml index 57c43ebbd..90a8bb879 100644 --- a/java/com/android/dialer/app/res/values/dimens.xml +++ b/java/com/android/dialer/app/res/values/dimens.xml @@ -24,6 +24,11 @@ --> 16dp + + 14sp + 16dp + 18dp + 8dp 32dp diff --git a/java/com/android/dialer/app/res/values/strings.xml b/java/com/android/dialer/app/res/values/strings.xml index 6110601d8..e02c6fb30 100644 --- a/java/com/android/dialer/app/res/values/strings.xml +++ b/java/com/android/dialer/app/res/values/strings.xml @@ -114,7 +114,7 @@ Voicemail - + %1$d Voicemails @@ -131,12 +131,12 @@ [CHAR LIMIT=10] --> - %1$s, + %1$s, %2$s - New voicemail from + New voicemail from %1$s @@ -165,7 +165,7 @@ Missed calls only - (%1$d) + (%1$d) %2$s @@ -258,6 +258,9 @@ and testing. [CHAR LIMIT=30]--> Simulator + + Create New UI Shortcut + All contacts @@ -395,14 +398,18 @@ [CHAR LIMIT=NONE] --> Cancel batch actions mode - voicemail - voicemails - Yes - No + Delete + Cancel Delete selected %1$s? %1$s selected + + + Delete this voicemail? + Delete these voicemails? + + @@ -516,7 +523,7 @@ Undo - Call + Call %s @@ -579,13 +586,13 @@ - + Call ^1 - + Missed call from ^1, ^2, ^3, ^4. - + Call ^1 @@ -629,7 +636,7 @@ action triggers a return video call to the named person/number. Note: AccessibilityServices uses this attribute to announce the purpose of the button. [CHAR LIMIT=NONE] --> - + Video call ^1. @@ -638,21 +645,21 @@ triggers playing back the voicemail. Note: AccessibilityServices uses this attribute to announce the purpose of the button. [CHAR LIMIT=NONE] --> - + Listen to voicemail from ^1 - + Play voicemail from ^1 - + Pause voicemail from ^1 @@ -660,7 +667,7 @@ - + Delete voicemail from ^1 @@ -674,14 +681,14 @@ - + Create contact for ^1 - + Add ^1 to existing contact @@ -689,7 +696,7 @@ displays the call details screen for an entry in the call log. This shows the calls to and from the specified number associated with the call log entry. [CHAR LIMIT=NONE] --> - + Call details for ^1 @@ -798,14 +805,14 @@ - + Call blocking temporarily off - + Call blocking has been disabled because you contacted emergency services from this phone within the last 48 hours. It will be automatically reenabled once the 48 hour period expires. @@ -818,7 +825,7 @@ - + You previously marked some callers to be automatically sent to voicemail via other apps. @@ -840,13 +847,13 @@ - + Calls from these numbers will be blocked and voicemails will be automatically deleted. - + Calls from these numbers will be blocked, but they may still be able to leave you voicemails. @@ -855,7 +862,7 @@ - %1$s + %1$s is already blocked. diff --git a/java/com/android/dialer/app/res/values/styles.xml b/java/com/android/dialer/app/res/values/styles.xml index 592f06d29..e0122e81c 100644 --- a/java/com/android/dialer/app/res/values/styles.xml +++ b/java/com/android/dialer/app/res/values/styles.xml @@ -16,6 +16,11 @@ --> + +