From 2827dd135647dab6f414f06b38f80537bff9a58a Mon Sep 17 00:00:00 2001 From: Eric Erfanian Date: Thu, 26 Oct 2017 09:37:50 -0700 Subject: Display CDMA voice privacy icon on notification bar. The locked phone icon will be shown for voice privacy call on CDMA for non-hold status(dialing, ongoing etc.) The onhold icon is same as usual. This change also update on hold icon to quantum vector drawable resources. WANT_LGTM=all Bug: 37529280 Test: StatusBarNotifierTest PiperOrigin-RevId: 173451922 Change-Id: I71d4c03b6953ca72def339c9c0a77bacbaf145f8 --- .../res/drawable/quantum_ic_phone_locked_vd_theme_24.xml | 10 ++++++++++ .../res/drawable/quantum_ic_phone_paused_vd_theme_24.xml | 10 ++++++++++ java/com/android/incallui/StatusBarNotifier.java | 7 +++++-- .../res/drawable-hdpi/ic_phone_paused_white_24dp.png | Bin 458 -> 0 bytes .../res/drawable-mdpi/ic_phone_paused_white_24dp.png | Bin 346 -> 0 bytes .../res/drawable-xhdpi/ic_phone_paused_white_24dp.png | Bin 584 -> 0 bytes .../res/drawable-xxhdpi/ic_phone_paused_white_24dp.png | Bin 842 -> 0 bytes 7 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 assets/quantum/res/drawable/quantum_ic_phone_locked_vd_theme_24.xml create mode 100644 assets/quantum/res/drawable/quantum_ic_phone_paused_vd_theme_24.xml delete mode 100644 java/com/android/incallui/res/drawable-hdpi/ic_phone_paused_white_24dp.png delete mode 100644 java/com/android/incallui/res/drawable-mdpi/ic_phone_paused_white_24dp.png delete mode 100644 java/com/android/incallui/res/drawable-xhdpi/ic_phone_paused_white_24dp.png delete mode 100644 java/com/android/incallui/res/drawable-xxhdpi/ic_phone_paused_white_24dp.png diff --git a/assets/quantum/res/drawable/quantum_ic_phone_locked_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_phone_locked_vd_theme_24.xml new file mode 100644 index 000000000..a249774b2 --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_phone_locked_vd_theme_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/assets/quantum/res/drawable/quantum_ic_phone_paused_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_phone_paused_vd_theme_24.xml new file mode 100644 index 000000000..99d25c10d --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_phone_paused_vd_theme_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/java/com/android/incallui/StatusBarNotifier.java b/java/com/android/incallui/StatusBarNotifier.java index 4ce43935e..bb3ef4333 100644 --- a/java/com/android/incallui/StatusBarNotifier.java +++ b/java/com/android/incallui/StatusBarNotifier.java @@ -624,7 +624,8 @@ public class StatusBarNotifier * Returns the appropriate icon res Id to display based on the call for which we want to display * information. */ - private int getIconToDisplay(DialerCall call) { + @VisibleForTesting + public int getIconToDisplay(DialerCall call) { // Even if both lines are in use, we only show a single item in // the expanded Notifications UI. It's labeled "Ongoing call" // (or "On hold" if there's only one call, and it's on hold.) @@ -633,7 +634,7 @@ public class StatusBarNotifier // from the foreground call. And if there's a ringing call, // display that regardless of the state of the other calls. if (call.getState() == DialerCall.State.ONHOLD) { - return R.drawable.ic_phone_paused_white_24dp; + return R.drawable.quantum_ic_phone_paused_vd_theme_24; } else if (call.getVideoTech().getSessionModificationState() == SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST || call.isVideoCall()) { @@ -644,6 +645,8 @@ public class StatusBarNotifier // helpful hint for users so they know how to get back to the call. For Sprint HD calls, we // replace this icon with an icon of a phone with a HD badge. This is a carrier requirement. return R.drawable.ic_hd_call; + } else if (call.hasProperty(Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY)) { + return R.drawable.quantum_ic_phone_locked_vd_theme_24; } // If ReturnToCall is enabled, use the static icon. The animated one will show in the bubble. if (ReturnToCallController.isEnabled(mContext) diff --git a/java/com/android/incallui/res/drawable-hdpi/ic_phone_paused_white_24dp.png b/java/com/android/incallui/res/drawable-hdpi/ic_phone_paused_white_24dp.png deleted file mode 100644 index a2177f58a..000000000 Binary files a/java/com/android/incallui/res/drawable-hdpi/ic_phone_paused_white_24dp.png and /dev/null differ diff --git a/java/com/android/incallui/res/drawable-mdpi/ic_phone_paused_white_24dp.png b/java/com/android/incallui/res/drawable-mdpi/ic_phone_paused_white_24dp.png deleted file mode 100644 index 7dc920b2b..000000000 Binary files a/java/com/android/incallui/res/drawable-mdpi/ic_phone_paused_white_24dp.png and /dev/null differ diff --git a/java/com/android/incallui/res/drawable-xhdpi/ic_phone_paused_white_24dp.png b/java/com/android/incallui/res/drawable-xhdpi/ic_phone_paused_white_24dp.png deleted file mode 100644 index a8becf485..000000000 Binary files a/java/com/android/incallui/res/drawable-xhdpi/ic_phone_paused_white_24dp.png and /dev/null differ diff --git a/java/com/android/incallui/res/drawable-xxhdpi/ic_phone_paused_white_24dp.png b/java/com/android/incallui/res/drawable-xxhdpi/ic_phone_paused_white_24dp.png deleted file mode 100644 index baf0cf27f..000000000 Binary files a/java/com/android/incallui/res/drawable-xxhdpi/ic_phone_paused_white_24dp.png and /dev/null differ -- cgit v1.2.3 From 32257fdc92016ed2f76e62af8425937284e0d61b Mon Sep 17 00:00:00 2001 From: calderwoodra Date: Wed, 25 Oct 2017 15:01:37 -0700 Subject: Search fragment now closes after placing a call. Moved SearchContactViewHolder listener logic from SearchAdapter to SearchFragment to make it easier to close search after placing a call. Bug: 68201142 Test: existing + DialtactsActivityTest PiperOrigin-RevId: 173454972 Change-Id: Ib5715d0f427d62344641b4bf841d34145fc3f65e --- java/com/android/dialer/app/DialtactsActivity.java | 12 ++- .../searchfragment/list/NewSearchFragment.java | 75 ++++++++++++++++-- .../dialer/searchfragment/list/SearchAdapter.java | 90 ++++------------------ 3 files changed, 93 insertions(+), 84 deletions(-) diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java index b9ca67f62..b5ec20246 100644 --- a/java/com/android/dialer/app/DialtactsActivity.java +++ b/java/com/android/dialer/app/DialtactsActivity.java @@ -124,7 +124,7 @@ import com.android.dialer.performancereport.PerformanceReport; import com.android.dialer.postcall.PostCall; import com.android.dialer.proguard.UsedByReflection; import com.android.dialer.searchfragment.list.NewSearchFragment; -import com.android.dialer.searchfragment.list.NewSearchFragment.SearchFragmentListTouchListener; +import com.android.dialer.searchfragment.list.NewSearchFragment.SearchFragmentListener; import com.android.dialer.simulator.Simulator; import com.android.dialer.simulator.SimulatorComponent; import com.android.dialer.smartdial.SmartDialNameMatcher; @@ -164,7 +164,7 @@ public class DialtactsActivity extends TransactionSafeActivity PhoneNumberInteraction.DisambigDialogDismissedListener, ActivityCompat.OnRequestPermissionsResultCallback, DialpadListener, - SearchFragmentListTouchListener { + SearchFragmentListener { public static final boolean DEBUG = false; @VisibleForTesting public static final String TAG_DIALPAD_FRAGMENT = "dialpad"; @@ -1664,6 +1664,14 @@ public class DialtactsActivity extends TransactionSafeActivity return false; } + @Override + public void onCallPlaced() { + if (mIsDialpadShown) { + hideDialpadFragment(false, true); + } + exitSearchUi(); + } + /** Popup menu accessible from the search bar */ protected class OptionsPopupMenu extends PopupMenu { diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java index ef1b4fc19..c200b946c 100644 --- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java +++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.ACCESS_FINE_LOCATION; import android.app.Fragment; import android.app.LoaderManager.LoaderCallbacks; +import android.content.Intent; import android.content.Loader; import android.content.pm.PackageManager; import android.database.Cursor; @@ -31,6 +32,7 @@ import android.support.annotation.VisibleForTesting; import android.support.v13.app.FragmentCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -42,13 +44,23 @@ import android.widget.FrameLayout; import android.widget.FrameLayout.LayoutParams; import com.android.contacts.common.extensions.PhoneDirectoryExtenderAccessor; import com.android.dialer.animation.AnimUtils; +import com.android.dialer.assisteddialing.ConcreteCreator; +import com.android.dialer.callcomposer.CallComposerActivity; import com.android.dialer.callintent.CallInitiationType; +import com.android.dialer.callintent.CallIntentBuilder; +import com.android.dialer.callintent.CallSpecificAppData; import com.android.dialer.common.Assert; import com.android.dialer.common.FragmentUtils; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.ThreadUtil; +import com.android.dialer.constants.ActivityRequestCodes; +import com.android.dialer.dialercontact.DialerContact; +import com.android.dialer.duo.DuoComponent; import com.android.dialer.enrichedcall.EnrichedCallComponent; import com.android.dialer.enrichedcall.EnrichedCallManager.CapabilitiesListener; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; +import com.android.dialer.searchfragment.common.RowClickListener; import com.android.dialer.searchfragment.common.SearchCursor; import com.android.dialer.searchfragment.cp2.SearchContactsCursorLoader; import com.android.dialer.searchfragment.list.SearchActionViewHolder.Action; @@ -72,7 +84,8 @@ public final class NewSearchFragment extends Fragment implements LoaderCallbacks, OnEmptyViewActionButtonClickedListener, CapabilitiesListener, - OnTouchListener { + OnTouchListener, + RowClickListener { // Since some of our queries can generate network requests, we should delay them until the user // stops typing to prevent generating too much network traffic. @@ -124,9 +137,8 @@ public final class NewSearchFragment extends Fragment public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup parent, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_search, parent, false); - adapter = new SearchAdapter(getActivity(), new SearchCursorManager()); + adapter = new SearchAdapter(getContext(), new SearchCursorManager(), this); adapter.setQuery(query); - adapter.setCallInitiationType(callInitiationType); adapter.setSearchActions(getActions()); adapter.setZeroSuggestVisible(getArguments().getBoolean(KEY_SHOW_ZERO_SUGGEST)); emptyContentView = view.findViewById(R.id.empty_view); @@ -241,7 +253,6 @@ public final class NewSearchFragment extends Fragment this.callInitiationType = callInitiationType; if (adapter != null) { adapter.setQuery(query); - adapter.setCallInitiationType(callInitiationType); adapter.setSearchActions(getActions()); adapter.setZeroSuggestVisible(isRegularSearch()); loadNearbyPlacesCursor(); @@ -449,12 +460,59 @@ public final class NewSearchFragment extends Fragment if (event.getAction() == MotionEvent.ACTION_UP) { v.performClick(); } - return FragmentUtils.getParentUnsafe(this, SearchFragmentListTouchListener.class) + return FragmentUtils.getParentUnsafe(this, SearchFragmentListener.class) .onSearchListTouch(event); } - /** Callback to {@link NewSearchFragment}'s parent to notify when the list is touched. */ - public interface SearchFragmentListTouchListener { + @Override + public void placeVoiceCall(String phoneNumber, int ranking) { + placeCall(phoneNumber, ranking, false, true); + } + + @Override + public void placeVideoCall(String phoneNumber, int ranking) { + placeCall(phoneNumber, ranking, true, false); + } + + private void placeCall( + String phoneNumber, int position, boolean isVideoCall, boolean allowAssistedDial) { + CallSpecificAppData callSpecificAppData = + CallSpecificAppData.newBuilder() + .setCallInitiationType(callInitiationType) + .setPositionOfSelectedSearchResult(position) + .setCharactersInSearchString(query == null ? 0 : query.length()) + .setAllowAssistedDialing(allowAssistedDial) + .build(); + Intent intent = + new CallIntentBuilder(phoneNumber, callSpecificAppData) + .setIsVideoCall(isVideoCall) + .setAllowAssistedDial( + allowAssistedDial, + ConcreteCreator.createNewAssistedDialingMediator( + getContext().getSystemService(TelephonyManager.class), + getContext().getApplicationContext())) + .build(); + DialerUtils.startActivityWithErrorToast(getActivity(), intent); + FragmentUtils.getParentUnsafe(this, SearchFragmentListener.class).onCallPlaced(); + } + + @Override + public void placeDuoCall(String phoneNumber) { + Logger.get(getContext()) + .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FROM_SEARCH); + Intent intent = DuoComponent.get(getContext()).getDuo().getIntent(getContext(), phoneNumber); + getActivity().startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO); + FragmentUtils.getParentUnsafe(this, SearchFragmentListener.class).onCallPlaced(); + } + + @Override + public void openCallAndShare(DialerContact contact) { + Intent intent = CallComposerActivity.newIntent(getContext(), contact); + DialerUtils.startActivityWithErrorToast(getContext(), intent); + } + + /** Callback to {@link NewSearchFragment}'s parent to be notified of important events. */ + public interface SearchFragmentListener { /** * Called when the list view in {@link NewSearchFragment} is touched. @@ -462,5 +520,8 @@ public final class NewSearchFragment extends Fragment * @see OnTouchListener#onTouch(View, MotionEvent) */ boolean onSearchListTouch(MotionEvent event); + + /** Called when a call is placed from the search fragment. */ + void onCallPlaced(); } } diff --git a/java/com/android/dialer/searchfragment/list/SearchAdapter.java b/java/com/android/dialer/searchfragment/list/SearchAdapter.java index 949c2a2c5..dc78953b5 100644 --- a/java/com/android/dialer/searchfragment/list/SearchAdapter.java +++ b/java/com/android/dialer/searchfragment/list/SearchAdapter.java @@ -16,55 +16,43 @@ package com.android.dialer.searchfragment.list; -import android.app.Activity; -import android.content.Intent; +import android.content.Context; import android.support.annotation.VisibleForTesting; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; -import android.telephony.TelephonyManager; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; -import com.android.dialer.assisteddialing.ConcreteCreator; -import com.android.dialer.callcomposer.CallComposerActivity; -import com.android.dialer.callintent.CallInitiationType; -import com.android.dialer.callintent.CallIntentBuilder; -import com.android.dialer.callintent.CallSpecificAppData; import com.android.dialer.common.Assert; -import com.android.dialer.constants.ActivityRequestCodes; -import com.android.dialer.dialercontact.DialerContact; -import com.android.dialer.duo.DuoComponent; -import com.android.dialer.logging.DialerImpression; -import com.android.dialer.logging.Logger; import com.android.dialer.searchfragment.common.RowClickListener; import com.android.dialer.searchfragment.common.SearchCursor; import com.android.dialer.searchfragment.cp2.SearchContactViewHolder; import com.android.dialer.searchfragment.list.SearchCursorManager.RowType; import com.android.dialer.searchfragment.nearbyplaces.NearbyPlaceViewHolder; import com.android.dialer.searchfragment.remote.RemoteContactViewHolder; -import com.android.dialer.util.DialerUtils; import java.util.List; /** RecyclerView adapter for {@link NewSearchFragment}. */ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) -public final class SearchAdapter extends RecyclerView.Adapter - implements RowClickListener { +public final class SearchAdapter extends RecyclerView.Adapter { private final SearchCursorManager searchCursorManager; - private final Activity activity; + private final Context context; private boolean showZeroSuggest; private String query; - private CallInitiationType.Type callInitiationType = CallInitiationType.Type.UNKNOWN_INITIATION; private OnClickListener allowClickListener; private OnClickListener dismissClickListener; + private RowClickListener rowClickListener; @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) - public SearchAdapter(Activity activity, SearchCursorManager searchCursorManager) { - this.activity = activity; + public SearchAdapter( + Context context, SearchCursorManager searchCursorManager, RowClickListener rowClickListener) { + this.context = context; this.searchCursorManager = searchCursorManager; + this.rowClickListener = rowClickListener; } @Override @@ -72,24 +60,25 @@ public final class SearchAdapter extends RecyclerView.Adapter switch (rowType) { case RowType.CONTACT_ROW: return new SearchContactViewHolder( - LayoutInflater.from(activity).inflate(R.layout.search_contact_row, root, false), this); + LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false), + rowClickListener); case RowType.NEARBY_PLACES_ROW: return new NearbyPlaceViewHolder( - LayoutInflater.from(activity).inflate(R.layout.search_contact_row, root, false)); + LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false)); case RowType.CONTACT_HEADER: case RowType.DIRECTORY_HEADER: case RowType.NEARBY_PLACES_HEADER: return new HeaderViewHolder( - LayoutInflater.from(activity).inflate(R.layout.header_layout, root, false)); + LayoutInflater.from(context).inflate(R.layout.header_layout, root, false)); case RowType.DIRECTORY_ROW: return new RemoteContactViewHolder( - LayoutInflater.from(activity).inflate(R.layout.search_contact_row, root, false)); + LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false)); case RowType.SEARCH_ACTION: return new SearchActionViewHolder( - LayoutInflater.from(activity).inflate(R.layout.search_action_layout, root, false)); + LayoutInflater.from(context).inflate(R.layout.search_action_layout, root, false)); case RowType.LOCATION_REQUEST: return new LocationPermissionViewHolder( - LayoutInflater.from(activity).inflate(R.layout.location_permission_row, root, false), + LayoutInflater.from(context).inflate(R.layout.location_permission_row, root, false), allowClickListener, dismissClickListener); case RowType.INVALID: @@ -168,10 +157,6 @@ public final class SearchAdapter extends RecyclerView.Adapter } } - void setCallInitiationType(CallInitiationType.Type callInitiationType) { - this.callInitiationType = callInitiationType; - } - public void setNearbyPlacesCursor(SearchCursor nearbyPlacesCursor) { if (searchCursorManager.setNearbyPlacesCursor(nearbyPlacesCursor)) { notifyDataSetChanged(); @@ -209,51 +194,6 @@ public final class SearchAdapter extends RecyclerView.Adapter } } - @Override - public void placeVoiceCall(String phoneNumber, int ranking) { - placeCall(phoneNumber, ranking, false, true); - } - - @Override - public void placeVideoCall(String phoneNumber, int ranking) { - placeCall(phoneNumber, ranking, true, false); - } - - private void placeCall( - String phoneNumber, int position, boolean isVideoCall, boolean allowAssistedDial) { - CallSpecificAppData callSpecificAppData = - CallSpecificAppData.newBuilder() - .setCallInitiationType(callInitiationType) - .setPositionOfSelectedSearchResult(position) - .setCharactersInSearchString(query == null ? 0 : query.length()) - .setAllowAssistedDialing(allowAssistedDial) - .build(); - Intent intent = - new CallIntentBuilder(phoneNumber, callSpecificAppData) - .setIsVideoCall(isVideoCall) - .setAllowAssistedDial( - allowAssistedDial, - ConcreteCreator.createNewAssistedDialingMediator( - activity.getSystemService(TelephonyManager.class), - activity.getApplicationContext())) - .build(); - DialerUtils.startActivityWithErrorToast(activity, intent); - } - - @Override - public void placeDuoCall(String phoneNumber) { - Logger.get(activity) - .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FROM_SEARCH); - Intent intent = DuoComponent.get(activity).getDuo().getIntent(activity, phoneNumber); - activity.startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_DUO); - } - - @Override - public void openCallAndShare(DialerContact contact) { - Intent intent = CallComposerActivity.newIntent(activity, contact); - DialerUtils.startActivityWithErrorToast(activity, intent); - } - /** Viewholder for R.layout.location_permission_row that requests the location permission. */ private static class LocationPermissionViewHolder extends RecyclerView.ViewHolder { -- cgit v1.2.3 From 94df7203674f12ff90d768467a307ed01601565d Mon Sep 17 00:00:00 2001 From: weijiaxu Date: Wed, 25 Oct 2017 18:21:41 -0700 Subject: App latency test migration. Migrate the existing app latency test to a new solution from Project Fi team. The main change on this new solution is that the data collection part is done by Primes now. Also, a few changes has been made on DialerPrimes class and a new Dialer variant dialer_release_test has been created. The benefits of using primes to collect data are: 1. latency tests dont need to insert lines of code to track latency in dialer codebase 2. be able to collect data on any variants with or without Proguard 3. latency tests now only contain ui interaction to trigger scenarios on which we want add measurements 4. share the same logic with primes on production so that data from testbeds and normal users are comparable. 5. easier for anyone to add interesting data entries. ----------Mobile Harness Below----------------------------------- RELNOTES[INC]:Add entries for dialer to use mobileharness plugin. Test: No PiperOrigin-RevId: 173481741 Change-Id: Ia6812794141382898bea4b34bca90278c5663464 --- java/com/android/dialer/logging/LoggingBindings.java | 13 +++++++++++++ java/com/android/dialer/logging/LoggingBindingsStub.java | 6 ++++++ java/com/android/incallui/InCallActivity.java | 10 ++++++++++ java/com/android/incallui/call/CallList.java | 13 +++++++++++++ 4 files changed, 42 insertions(+) diff --git a/java/com/android/dialer/logging/LoggingBindings.java b/java/com/android/dialer/logging/LoggingBindings.java index ca9a0533e..7682c767d 100644 --- a/java/com/android/dialer/logging/LoggingBindings.java +++ b/java/com/android/dialer/logging/LoggingBindings.java @@ -20,6 +20,13 @@ import android.widget.QuickContactBadge; /** Allows the container application to gather analytics. */ public interface LoggingBindings { + String ON_CREATE_PRIMES_EVENT_NAME = "Application.onCreate"; + String ON_CREATE_TO_ACTIVITY_ON_CREATE_PRIMES_EVENT_NAME = + "Application.onCreate_To_GoogleDialtactsActivity.onCreate"; + String ON_CALL_ADDED_TO_ON_INCALL_UI_SHOWN_INCOMING = + "CallList.onCallAdded_To_InCallActivity.onCreate_Incoming"; + String ON_CALL_ADDED_TO_ON_INCALL_UI_SHOWN_OUTGOING = + "CallList.onCallAdded_To_InCallActivity.onCreate_Outgoing"; /** * Logs an DialerImpression event that's not associated with a specific call. * @@ -87,4 +94,10 @@ public interface LoggingBindings { /** Logs successful People Api lookup result */ void logSuccessfulPeopleApiLookupReport(long latency, int httpResponseCode); + + /** Log start a latency timer */ + void logStartLatencyTimer(String timerEventName); + + /** Log end a latency timer */ + void logStopLatencyTimer(String timerEventName); } diff --git a/java/com/android/dialer/logging/LoggingBindingsStub.java b/java/com/android/dialer/logging/LoggingBindingsStub.java index 2dbcc3ffb..ab6872cf4 100644 --- a/java/com/android/dialer/logging/LoggingBindingsStub.java +++ b/java/com/android/dialer/logging/LoggingBindingsStub.java @@ -61,4 +61,10 @@ public class LoggingBindingsStub implements LoggingBindings { @Override public void logSuccessfulPeopleApiLookupReport(long latency, int httpResponseCode) {} + + @Override + public void logStartLatencyTimer(String timerEventName) {} + + @Override + public void logStopLatencyTimer(String timerEventName) {} } diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java index c3a68c021..c509e4890 100644 --- a/java/com/android/incallui/InCallActivity.java +++ b/java/com/android/incallui/InCallActivity.java @@ -40,6 +40,8 @@ import com.android.dialer.compat.ActivityCompat; import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; +import com.android.dialer.logging.LoggingBindings; +import com.android.dialer.logging.LoggingBindingsFactory; import com.android.dialer.logging.ScreenEvent; import com.android.incallui.answer.bindings.AnswerBindings; import com.android.incallui.answer.protocol.AnswerScreen; @@ -145,6 +147,14 @@ public class InCallActivity extends TransactionSafeFragmentActivity pseudoBlackScreenOverlay = findViewById(R.id.psuedo_black_screen_overlay); sendBroadcast(CallPendingActivity.getFinishBroadcast()); Trace.endSection(); + if (getApplicationContext() instanceof LoggingBindingsFactory) { + LoggingBindings loggingBindings = + ((LoggingBindingsFactory) getApplicationContext()).newLoggingBindings(); + loggingBindings.logStopLatencyTimer( + LoggingBindings.ON_CALL_ADDED_TO_ON_INCALL_UI_SHOWN_INCOMING); + loggingBindings.logStopLatencyTimer( + LoggingBindings.ON_CALL_ADDED_TO_ON_INCALL_UI_SHOWN_OUTGOING); + } } @Override diff --git a/java/com/android/incallui/call/CallList.java b/java/com/android/incallui/call/CallList.java index 59f38349a..4f1dfd43f 100644 --- a/java/com/android/incallui/call/CallList.java +++ b/java/com/android/incallui/call/CallList.java @@ -36,6 +36,8 @@ import com.android.dialer.enrichedcall.EnrichedCallComponent; import com.android.dialer.enrichedcall.EnrichedCallManager; import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; +import com.android.dialer.logging.LoggingBindings; +import com.android.dialer.logging.LoggingBindingsFactory; import com.android.dialer.shortcuts.ShortcutUsageReporter; import com.android.dialer.spam.Spam; import com.android.dialer.spam.SpamBindings; @@ -117,6 +119,17 @@ public class CallList implements DialerCallDelegate { public void onCallAdded( final Context context, final android.telecom.Call telecomCall, LatencyReport latencyReport) { Trace.beginSection("CallList.onCallAdded"); + if (context.getApplicationContext() instanceof LoggingBindingsFactory) { + if (telecomCall.getState() == Call.STATE_CONNECTING) { + ((LoggingBindingsFactory) context.getApplicationContext()) + .newLoggingBindings() + .logStartLatencyTimer(LoggingBindings.ON_CALL_ADDED_TO_ON_INCALL_UI_SHOWN_OUTGOING); + } else if (telecomCall.getState() == Call.STATE_RINGING) { + ((LoggingBindingsFactory) context.getApplicationContext()) + .newLoggingBindings() + .logStartLatencyTimer(LoggingBindings.ON_CALL_ADDED_TO_ON_INCALL_UI_SHOWN_INCOMING); + } + } if (mUiListeners != null) { mUiListeners.onCallAdded(); } -- cgit v1.2.3 From 65c21801bf47cf24e2755445545bedabc0f393bf Mon Sep 17 00:00:00 2001 From: calderwoodra Date: Wed, 25 Oct 2017 23:16:35 -0700 Subject: Cp2 Phonelookup isDirty implementation. Checks if a cp2 contact has been modified or deleted. Bug: 67605130,64099602 Test: Cp2PhoneLookupTest PiperOrigin-RevId: 173499443 Change-Id: I1fa267c05732fba09f00113232d4370b159aa735 --- .../dialer/phonelookup/cp2/Cp2PhoneLookup.java | 125 ++++++++++++++++++++- 1 file changed, 121 insertions(+), 4 deletions(-) diff --git a/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java b/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java index 323ec7c65..a3d97c64e 100644 --- a/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java +++ b/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java @@ -16,21 +16,138 @@ package com.android.dialer.phonelookup.cp2; +import android.content.Context; +import android.database.Cursor; +import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.Contacts; +import android.provider.ContactsContract.DeletedContacts; +import android.support.v4.util.ArraySet; import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.common.concurrent.DialerExecutors; import com.android.dialer.phonelookup.PhoneLookup; import com.android.dialer.phonelookup.PhoneLookupInfo; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; +import java.util.Set; -/** TODO(calderwoodra) */ -final class Cp2PhoneLookup implements PhoneLookup { +/** PhoneLookup implementation for local contacts. */ +public final class Cp2PhoneLookup implements PhoneLookup { + + private final Context context; + + Cp2PhoneLookup(Context context) { + this.context = context; + } @Override public ListenableFuture isDirty( ImmutableSet phoneNumbers, long lastModified) { - // TODO(calderwoodra) - return null; + // TODO(calderwoodra): consider a different thread pool + return MoreExecutors.listeningDecorator(DialerExecutors.getLowPriorityThreadPool(context)) + .submit(() -> isDirtyInternal(phoneNumbers, lastModified)); + } + + private boolean isDirtyInternal(ImmutableSet phoneNumbers, long lastModified) { + return contactsUpdated(getContactIdsFromPhoneNumbers(phoneNumbers), lastModified) + || contactsDeleted(lastModified); + } + + /** Returns set of contact ids that correspond to {@code phoneNumbers} if the contact exists. */ + private Set getContactIdsFromPhoneNumbers(ImmutableSet phoneNumbers) { + Set contactIds = new ArraySet<>(); + try (Cursor cursor = + context + .getContentResolver() + .query( + Phone.CONTENT_URI, + new String[] {Phone.CONTACT_ID}, + columnInSetWhereStatement(Phone.NORMALIZED_NUMBER, phoneNumbers.size()), + contactIdsSelectionArgs(phoneNumbers), + null)) { + cursor.moveToPosition(-1); + while (cursor.moveToNext()) { + contactIds.add(cursor.getLong(0 /* columnIndex */)); + } + } + return contactIds; + } + + private static String[] contactIdsSelectionArgs(ImmutableSet phoneNumbers) { + String[] args = new String[phoneNumbers.size()]; + int i = 0; + for (DialerPhoneNumber phoneNumber : phoneNumbers) { + args[i++] = getNormalizedNumber(phoneNumber); + } + return args; + } + + private static String getNormalizedNumber(DialerPhoneNumber phoneNumber) { + // TODO(calderwoodra): implement normalization logic that matches contacts. + return phoneNumber.getRawInput().getNumber(); + } + + /** Returns true if any contacts were modified after {@code lastModified}. */ + private boolean contactsUpdated(Set contactIds, long lastModified) { + try (Cursor cursor = + context + .getContentResolver() + .query( + Contacts.CONTENT_URI, + new String[] {Contacts._ID}, + contactsIsDirtyWhereStatement(contactIds.size()), + contactsIsDirtySelectionArgs(lastModified, contactIds), + null)) { + return cursor.getCount() > 0; + } + } + + private static String contactsIsDirtyWhereStatement(int numberOfContactIds) { + StringBuilder where = new StringBuilder(); + // Filter to after last modified time + where.append(Contacts.CONTACT_LAST_UPDATED_TIMESTAMP).append(" > ?"); + + // Filter based only on contacts we care about + where.append(" AND ").append(columnInSetWhereStatement(Contacts._ID, numberOfContactIds)); + return where.toString(); + } + + private String[] contactsIsDirtySelectionArgs(long lastModified, Set contactIds) { + String[] args = new String[contactIds.size() + 1]; + args[0] = Long.toString(lastModified); + int i = 1; + for (Long contactId : contactIds) { + args[i++] = Long.toString(contactId); + } + return args; + } + + /** Returns true if any contacts were deleted after {@code lastModified}. */ + private boolean contactsDeleted(long lastModified) { + try (Cursor cursor = + context + .getContentResolver() + .query( + DeletedContacts.CONTENT_URI, + new String[] {DeletedContacts.CONTACT_DELETED_TIMESTAMP}, + DeletedContacts.CONTACT_DELETED_TIMESTAMP + " > ?", + new String[] {Long.toString(lastModified)}, + null)) { + return cursor.getCount() > 0; + } + } + + private static String columnInSetWhereStatement(String columnName, int setSize) { + StringBuilder where = new StringBuilder(); + where.append(columnName).append(" IN ("); + for (int i = 0; i < setSize; i++) { + if (i != 0) { + where.append(", "); + } + where.append("?"); + } + return where.append(")").toString(); } @Override -- cgit v1.2.3