summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortwyen <twyen@google.com>2017-11-29 20:49:06 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-11-29 20:49:06 +0000
commit002c66cda2a66ffdcde73442efb212e8341cb445 (patch)
tree1749d2cbf1a8636a2b5f79b88ff888e6700970f5
parent52dadec2337ec34791e1666921d70e2c2eb33834 (diff)
parent38db0c78bfc3330ac72e75a2b88397cf4b35145b (diff)
Merge changes Ic61819b8,I4149abe1,Ic738a6dd,I297faa26,Ib6a929ef, ...
am: 38db0c78bf Change-Id: I3857acc52182d915bef2ec6ab5e2e1479008da8d
-rw-r--r--java/com/android/dialer/assisteddialing/AssistedDialingMediator.java5
-rw-r--r--java/com/android/dialer/assisteddialing/AssistedDialingMediatorImpl.java8
-rw-r--r--java/com/android/dialer/assisteddialing/AssistedDialingMediatorStub.java8
-rw-r--r--java/com/android/dialer/assisteddialing/ui/res/values/strings.xml4
-rw-r--r--java/com/android/dialer/contactsfragment/ContactsAdapter.java17
-rw-r--r--java/com/android/dialer/contactsfragment/ContactsFragment.java67
-rw-r--r--java/com/android/dialer/logging/dialer_impression.proto19
-rw-r--r--java/com/android/dialer/precall/externalreceiver/LaunchPreCallActivity.java3
-rw-r--r--java/com/android/dialer/precall/impl/CallingAccountSelector.java45
-rw-r--r--java/com/android/dialer/precall/impl/PreCallActivity.java5
-rw-r--r--java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java3
-rw-r--r--java/com/android/dialer/precall/impl/PreCallImpl.java3
-rw-r--r--java/com/android/dialer/precall/impl/res/values/strings.xml6
-rw-r--r--java/com/android/incallui/CallButtonPresenter.java3
-rw-r--r--java/com/android/incallui/DialpadFragment.java178
-rw-r--r--java/com/android/incallui/DtmfKeyListener.java156
16 files changed, 329 insertions, 201 deletions
diff --git a/java/com/android/dialer/assisteddialing/AssistedDialingMediator.java b/java/com/android/dialer/assisteddialing/AssistedDialingMediator.java
index 004d2f7da..756fd6125 100644
--- a/java/com/android/dialer/assisteddialing/AssistedDialingMediator.java
+++ b/java/com/android/dialer/assisteddialing/AssistedDialingMediator.java
@@ -27,6 +27,11 @@ public interface AssistedDialingMediator {
/** Returns {@code true} if the current client platform supports Assisted Dialing. */
public boolean isPlatformEligible();
+ /** Returns the country code in which the library thinks the user typically resides. */
+ @SuppressWarnings("AndroidApiChecker") // Use of optional
+ @TargetApi(VERSION_CODES.N)
+ public Optional<String> userHomeCountryCode();
+
@SuppressWarnings("AndroidApiChecker") // Use of optional
@TargetApi(VERSION_CODES.N)
public Optional<TransformationInfo> attemptAssistedDial(@NonNull String numberToTransform);
diff --git a/java/com/android/dialer/assisteddialing/AssistedDialingMediatorImpl.java b/java/com/android/dialer/assisteddialing/AssistedDialingMediatorImpl.java
index 1cc9732bb..7214437ab 100644
--- a/java/com/android/dialer/assisteddialing/AssistedDialingMediatorImpl.java
+++ b/java/com/android/dialer/assisteddialing/AssistedDialingMediatorImpl.java
@@ -56,6 +56,14 @@ final class AssistedDialingMediatorImpl implements AssistedDialingMediator {
return true;
}
+ /** Returns the country code in which the library thinks the user typically resides. */
+ @Override
+ @SuppressWarnings("AndroidApiChecker") // Use of optional
+ @TargetApi(VERSION_CODES.N)
+ public Optional<String> userHomeCountryCode() {
+ return locationDetector.getUpperCaseUserHomeCountry();
+ }
+
/**
* Returns an Optional of type String containing the transformed number that was provided. The
* transformed number should be capable of dialing out of the User's current country and
diff --git a/java/com/android/dialer/assisteddialing/AssistedDialingMediatorStub.java b/java/com/android/dialer/assisteddialing/AssistedDialingMediatorStub.java
index fe32e2c9a..9a40e0576 100644
--- a/java/com/android/dialer/assisteddialing/AssistedDialingMediatorStub.java
+++ b/java/com/android/dialer/assisteddialing/AssistedDialingMediatorStub.java
@@ -32,6 +32,14 @@ public final class AssistedDialingMediatorStub implements AssistedDialingMediato
return Optional.empty();
}
+ /** Always returns an empty Optional. */
+ @Override
+ @SuppressWarnings("AndroidApiChecker") // Use of optional
+ @TargetApi(VERSION_CODES.N)
+ public Optional<String> userHomeCountryCode() {
+ return Optional.empty();
+ }
+
@Override
public boolean isPlatformEligible() {
return false;
diff --git a/java/com/android/dialer/assisteddialing/ui/res/values/strings.xml b/java/com/android/dialer/assisteddialing/ui/res/values/strings.xml
index 3b40817ed..1dc778f59 100644
--- a/java/com/android/dialer/assisteddialing/ui/res/values/strings.xml
+++ b/java/com/android/dialer/assisteddialing/ui/res/values/strings.xml
@@ -20,7 +20,7 @@
<string name="assisted_dialing_setting_title">Assisted dialing</string>
<!-- Label for a setting enabling assisted dialing switch preference-->
- <string name="assisted_dialing_setting_summary">Automatically correct the phone number prefix when traveling and calling international numbers</string>
+ <string name="assisted_dialing_setting_summary">Predict and add a country code when you call while traveling abroad</string>
<!-- Key for the assisted dialing setting toggle-->
<string name="assisted_dialing_setting_toggle_key" translatable="false">assisted_dialing_setting_toggle_key</string>
@@ -531,4 +531,4 @@
<item>ZM</item>
<item>ZW</item>
</string-array>
-</resources> \ No newline at end of file
+</resources>
diff --git a/java/com/android/dialer/contactsfragment/ContactsAdapter.java b/java/com/android/dialer/contactsfragment/ContactsAdapter.java
index 481574e0c..8f2120cd7 100644
--- a/java/com/android/dialer/contactsfragment/ContactsAdapter.java
+++ b/java/com/android/dialer/contactsfragment/ContactsAdapter.java
@@ -49,22 +49,24 @@ final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
private final ArrayMap<ContactViewHolder, Integer> holderMap = new ArrayMap<>();
private final Context context;
- private final Cursor cursor;
private final @Header int header;
private final @ClickAction int clickAction;
// List of contact sublist headers
- private final String[] headers;
-
+ private String[] headers = new String[0];
// Number of contacts that correspond to each header in {@code headers}.
- private final int[] counts;
+ private int[] counts = new int[0];
+ // Cursor with list of contacts
+ private Cursor cursor;
- ContactsAdapter(
- Context context, Cursor cursor, @Header int header, @ClickAction int clickAction) {
+ ContactsAdapter(Context context, @Header int header, @ClickAction int clickAction) {
this.context = context;
- this.cursor = cursor;
this.header = header;
this.clickAction = clickAction;
+ }
+
+ void updateCursor(Cursor cursor) {
+ this.cursor = cursor;
headers = cursor.getExtras().getStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES);
counts = cursor.getExtras().getIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS);
if (counts != null) {
@@ -78,6 +80,7 @@ final class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
"ContactsAdapter", "Count sum (%d) != cursor count (%d).", sum, cursor.getCount());
}
}
+ notifyDataSetChanged();
}
@Override
diff --git a/java/com/android/dialer/contactsfragment/ContactsFragment.java b/java/com/android/dialer/contactsfragment/ContactsFragment.java
index a8daa546a..82b68b8ee 100644
--- a/java/com/android/dialer/contactsfragment/ContactsFragment.java
+++ b/java/com/android/dialer/contactsfragment/ContactsFragment.java
@@ -16,8 +16,13 @@
package com.android.dialer.contactsfragment;
+import static android.Manifest.permission.READ_CONTACTS;
+
import android.app.Fragment;
import android.app.LoaderManager.LoaderCallbacks;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
import android.content.Loader;
import android.content.pm.PackageManager;
import android.database.Cursor;
@@ -80,6 +85,18 @@ public class ContactsFragment extends Fragment
private static final String EXTRA_HEADER = "extra_header";
private static final String EXTRA_CLICK_ACTION = "extra_click_action";
+ /**
+ * Listen to broadcast events about permissions in order to be notified if the READ_CONTACTS
+ * permission is granted via the UI in another fragment.
+ */
+ private final BroadcastReceiver readContactsPermissionGrantedReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ getLoaderManager().initLoader(0, null, ContactsFragment.this);
+ }
+ };
+
private FastScroller fastScroller;
private TextView anchoredHeader;
private RecyclerView recyclerView;
@@ -146,6 +163,23 @@ public class ContactsFragment extends Fragment
fastScroller = view.findViewById(R.id.fast_scroller);
anchoredHeader = view.findViewById(R.id.header);
recyclerView = view.findViewById(R.id.recycler_view);
+ adapter = new ContactsAdapter(getContext(), header, clickAction);
+ recyclerView.setAdapter(adapter);
+ manager =
+ new LinearLayoutManager(getContext()) {
+ @Override
+ public void onLayoutChildren(Recycler recycler, State state) {
+ super.onLayoutChildren(recycler, state);
+ int itemsShown = findLastVisibleItemPosition() - findFirstVisibleItemPosition() + 1;
+ if (adapter.getItemCount() > itemsShown) {
+ fastScroller.setVisibility(View.VISIBLE);
+ recyclerView.setOnScrollChangeListener(ContactsFragment.this);
+ } else {
+ fastScroller.setVisibility(View.GONE);
+ }
+ }
+ };
+ recyclerView.setLayoutManager(manager);
emptyContentView = view.findViewById(R.id.empty_list_view);
emptyContentView.setImage(R.drawable.empty_contacts);
@@ -187,6 +221,7 @@ public class ContactsFragment extends Fragment
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+ LogUtil.enterBlock("ContactsFragment.onLoadFinished");
if (cursor == null || cursor.getCount() == 0) {
emptyContentView.setDescription(R.string.all_contacts_empty);
emptyContentView.setActionLabel(R.string.all_contacts_empty_add_contact_action);
@@ -195,24 +230,8 @@ public class ContactsFragment extends Fragment
} else {
emptyContentView.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
- adapter = new ContactsAdapter(getContext(), cursor, header, clickAction);
- manager =
- new LinearLayoutManager(getContext()) {
- @Override
- public void onLayoutChildren(Recycler recycler, State state) {
- super.onLayoutChildren(recycler, state);
- int itemsShown = findLastVisibleItemPosition() - findFirstVisibleItemPosition() + 1;
- if (adapter.getItemCount() > itemsShown) {
- fastScroller.setVisibility(View.VISIBLE);
- recyclerView.setOnScrollChangeListener(ContactsFragment.this);
- } else {
- fastScroller.setVisibility(View.GONE);
- }
- }
- };
+ adapter.updateCursor(cursor);
- recyclerView.setLayoutManager(manager);
- recyclerView.setAdapter(adapter);
PerformanceReport.logOnScrollStateChange(recyclerView);
fastScroller.setup(adapter, manager);
}
@@ -311,4 +330,18 @@ public class ContactsFragment extends Fragment
}
}
}
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ PermissionsUtil.registerPermissionReceiver(
+ getActivity(), readContactsPermissionGrantedReceiver, READ_CONTACTS);
+ }
+
+ @Override
+ public void onStop() {
+ PermissionsUtil.unregisterPermissionReceiver(
+ getActivity(), readContactsPermissionGrantedReceiver);
+ super.onStop();
+ }
}
diff --git a/java/com/android/dialer/logging/dialer_impression.proto b/java/com/android/dialer/logging/dialer_impression.proto
index c2456d8ac..2bbce0d25 100644
--- a/java/com/android/dialer/logging/dialer_impression.proto
+++ b/java/com/android/dialer/logging/dialer_impression.proto
@@ -12,7 +12,7 @@ message DialerImpression {
// Event enums to be used for Impression Logging in Dialer.
// It's perfectly acceptable for this enum to be large
// Values should be from 1000 to 100000.
- // Next Tag: 1293
+ // Next Tag: 1308
enum Type {
UNKNOWN_AOSP_EVENT_TYPE = 1000;
@@ -604,5 +604,22 @@ message DialerImpression {
1291
;
+
+ PRECALL_INITIATED = 1293;
+ PRECALL_INITIATED_EXTERNAL = 1294;
+ PRECALL_CANCELED = 1295;
+
+ DUAL_SIM_CHANGE_SIM_PRESSED = 1296;
+ DUAL_SIM_SELECTION_SHOWN = 1297;
+ DUAL_SIM_SELECTION_VOICEMAIL = 1298;
+ DUAL_SIM_SELECTION_IN_CONTACTS = 1299;
+ DUAL_SIM_SELECTION_SUGGESTION_AVAILABLE = 1300;
+ DUAL_SIM_SELECTION_SUGGESTED_CARRIER = 1301;
+ DUAL_SIM_SELECTION_SUGGESTED_FREQUENCY = 1302;
+ DUAL_SIM_SELECTION_SUGGESTED_SIM_SELECTED = 1303;
+ DUAL_SIM_SELECTION_NON_SUGGESTED_SIM_SELECTED = 1304;
+ DUAL_SIM_SELECTION_PREFERRED_SET = 1305;
+ DUAL_SIM_SELECTION_PREFERRED_USED = 1306;
+ DUAL_SIM_SELECTION_GLOBAL_USED = 1307;
}
}
diff --git a/java/com/android/dialer/precall/externalreceiver/LaunchPreCallActivity.java b/java/com/android/dialer/precall/externalreceiver/LaunchPreCallActivity.java
index 121e6a6c9..a7811fe6a 100644
--- a/java/com/android/dialer/precall/externalreceiver/LaunchPreCallActivity.java
+++ b/java/com/android/dialer/precall/externalreceiver/LaunchPreCallActivity.java
@@ -23,6 +23,8 @@ import android.os.Bundle;
import android.support.annotation.Nullable;
import com.android.dialer.callintent.CallInitiationType.Type;
import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.logging.DialerImpression;
+import com.android.dialer.logging.Logger;
import com.android.dialer.precall.PreCall;
/**
@@ -47,6 +49,7 @@ public class LaunchPreCallActivity extends Activity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ Logger.get(this).logImpression(DialerImpression.Type.PRECALL_INITIATED_EXTERNAL);
Intent intent = getIntent();
CallIntentBuilder builder = new CallIntentBuilder(intent.getData(), Type.EXTERNAL_INITIATION);
builder
diff --git a/java/com/android/dialer/precall/impl/CallingAccountSelector.java b/java/com/android/dialer/precall/impl/CallingAccountSelector.java
index 5d928b4fb..a61a3b1c6 100644
--- a/java/com/android/dialer/precall/impl/CallingAccountSelector.java
+++ b/java/com/android/dialer/precall/impl/CallingAccountSelector.java
@@ -47,6 +47,9 @@ import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.configprovider.ConfigProviderBindings;
+import com.android.dialer.logging.DialerImpression;
+import com.android.dialer.logging.DialerImpression.Type;
+import com.android.dialer.logging.Logger;
import com.android.dialer.precall.PreCallAction;
import com.android.dialer.precall.PreCallCoordinator;
import com.android.dialer.precall.PreCallCoordinator.PendingAction;
@@ -116,6 +119,7 @@ public class CallingAccountSelector implements PreCallAction {
switch (builder.getUri().getScheme()) {
case PhoneAccount.SCHEME_VOICEMAIL:
showDialog(coordinator, coordinator.startPendingAction(), null, null, null);
+ Logger.get(coordinator.getActivity()).logImpression(Type.DUAL_SIM_SELECTION_VOICEMAIL);
break;
case PhoneAccount.SCHEME_TEL:
processPreferredAccount(coordinator);
@@ -146,6 +150,8 @@ public class CallingAccountSelector implements PreCallAction {
return;
}
if (result.phoneAccountHandle.isPresent()) {
+ Logger.get(coordinator.getActivity())
+ .logImpression(DialerImpression.Type.DUAL_SIM_SELECTION_PREFERRED_USED);
coordinator.getBuilder().setPhoneAccountHandle(result.phoneAccountHandle.get());
pendingAction.finish();
return;
@@ -155,6 +161,8 @@ public class CallingAccountSelector implements PreCallAction {
.getSystemService(TelecomManager.class)
.getDefaultOutgoingPhoneAccount(builder.getUri().getScheme());
if (defaultPhoneAccount != null) {
+ Logger.get(coordinator.getActivity())
+ .logImpression(DialerImpression.Type.DUAL_SIM_SELECTION_GLOBAL_USED);
builder.setPhoneAccountHandle(defaultPhoneAccount);
pendingAction.finish();
return;
@@ -183,6 +191,25 @@ public class CallingAccountSelector implements PreCallAction {
@Nullable String number,
@Nullable Suggestion suggestion) {
Assert.isMainThread();
+ Logger.get(coordinator.getActivity()).logImpression(Type.DUAL_SIM_SELECTION_SHOWN);
+ if (dataId != null) {
+ Logger.get(coordinator.getActivity()).logImpression(Type.DUAL_SIM_SELECTION_IN_CONTACTS);
+ }
+ if (suggestion != null) {
+ Logger.get(coordinator.getActivity())
+ .logImpression(Type.DUAL_SIM_SELECTION_SUGGESTION_AVAILABLE);
+ switch (suggestion.reason) {
+ case INTRA_CARRIER:
+ Logger.get(coordinator.getActivity())
+ .logImpression(Type.DUAL_SIM_SELECTION_SUGGESTED_CARRIER);
+ break;
+ case FREQUENT:
+ Logger.get(coordinator.getActivity())
+ .logImpression(Type.DUAL_SIM_SELECTION_SUGGESTED_FREQUENCY);
+ break;
+ default:
+ }
+ }
List<PhoneAccountHandle> phoneAccountHandles =
coordinator
.getActivity()
@@ -194,7 +221,7 @@ public class CallingAccountSelector implements PreCallAction {
dataId != null /* canSetDefault */,
R.string.pre_call_select_phone_account_remember,
phoneAccountHandles,
- new SelectedListener(coordinator, pendingAction, dataId, number),
+ new SelectedListener(coordinator, pendingAction, dataId, number, suggestion),
null /* call ID */,
buildHint(coordinator.getActivity(), phoneAccountHandles, suggestion));
selectPhoneAccountDialogFragment.show(
@@ -351,25 +378,39 @@ public class CallingAccountSelector implements PreCallAction {
private final PreCallCoordinator.PendingAction listener;
private final String dataId;
private final String number;
+ private final Suggestion suggestion;
public SelectedListener(
@NonNull PreCallCoordinator builder,
@NonNull PreCallCoordinator.PendingAction listener,
@Nullable String dataId,
- @Nullable String number) {
+ @Nullable String number,
+ @Nullable Suggestion suggestion) {
this.coordinator = Assert.isNotNull(builder);
this.listener = Assert.isNotNull(listener);
this.dataId = dataId;
this.number = number;
+ this.suggestion = suggestion;
}
@MainThread
@Override
public void onPhoneAccountSelected(
PhoneAccountHandle selectedAccountHandle, boolean setDefault, @Nullable String callId) {
+ if (suggestion != null) {
+ if (suggestion.phoneAccountHandle.equals(selectedAccountHandle)) {
+ Logger.get(coordinator.getActivity())
+ .logImpression(DialerImpression.Type.DUAL_SIM_SELECTION_SUGGESTED_SIM_SELECTED);
+ } else {
+ Logger.get(coordinator.getActivity())
+ .logImpression(DialerImpression.Type.DUAL_SIM_SELECTION_NON_SUGGESTED_SIM_SELECTED);
+ }
+ }
coordinator.getBuilder().setPhoneAccountHandle(selectedAccountHandle);
if (dataId != null && setDefault) {
+ Logger.get(coordinator.getActivity())
+ .logImpression(DialerImpression.Type.DUAL_SIM_SELECTION_PREFERRED_SET);
DialerExecutorComponent.get(coordinator.getActivity())
.dialerExecutorFactory()
.createNonUiTaskBuilder(new WritePreferredAccountWorker())
diff --git a/java/com/android/dialer/precall/impl/PreCallActivity.java b/java/com/android/dialer/precall/impl/PreCallActivity.java
index 48c2fbfc3..ee417b968 100644
--- a/java/com/android/dialer/precall/impl/PreCallActivity.java
+++ b/java/com/android/dialer/precall/impl/PreCallActivity.java
@@ -18,6 +18,7 @@ package com.android.dialer.precall.impl;
import android.annotation.TargetApi;
import android.app.Activity;
+import android.app.KeyguardManager;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
@@ -34,8 +35,10 @@ public class PreCallActivity extends Activity {
super.onCreate(savedInstanceState);
preCallCoordinator = new PreCallCoordinatorImpl(this);
preCallCoordinator.onCreate(getIntent(), savedInstanceState);
- getWindow().addFlags(LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ if (getSystemService(KeyguardManager.class).isKeyguardLocked()) {
+ getWindow().addFlags(LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ }
}
@Override
diff --git a/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java b/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java
index 94ba90d75..36af62245 100644
--- a/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java
+++ b/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java
@@ -24,6 +24,8 @@ import android.support.annotation.Nullable;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.logging.DialerImpression.Type;
+import com.android.dialer.logging.Logger;
import com.android.dialer.precall.PreCallAction;
import com.android.dialer.precall.PreCallComponent;
import com.android.dialer.precall.PreCallCoordinator;
@@ -116,6 +118,7 @@ public class PreCallCoordinatorImpl implements PreCallCoordinator {
public void abortCall() {
Assert.checkState(currentAction != null);
aborted = true;
+ Logger.get(getActivity()).logImpression(Type.PRECALL_CANCELED);
}
@NonNull
diff --git a/java/com/android/dialer/precall/impl/PreCallImpl.java b/java/com/android/dialer/precall/impl/PreCallImpl.java
index 1c78bb8b0..b9c9d8873 100644
--- a/java/com/android/dialer/precall/impl/PreCallImpl.java
+++ b/java/com/android/dialer/precall/impl/PreCallImpl.java
@@ -21,6 +21,8 @@ import android.content.Intent;
import android.support.annotation.NonNull;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.logging.DialerImpression;
+import com.android.dialer.logging.Logger;
import com.android.dialer.precall.PreCall;
import com.android.dialer.precall.PreCallAction;
import com.android.dialer.precall.PreCallComponent;
@@ -42,6 +44,7 @@ public class PreCallImpl implements PreCall {
@NonNull
@Override
public Intent buildIntent(Context context, CallIntentBuilder builder) {
+ Logger.get(context).logImpression(DialerImpression.Type.PRECALL_INITIATED);
if (!requiresUi(context, builder)) {
LogUtil.i("PreCallImpl.buildIntent", "No UI requested, running pre-call directly");
for (PreCallAction action : PreCallComponent.get(context).getPreCall().getActions()) {
diff --git a/java/com/android/dialer/precall/impl/res/values/strings.xml b/java/com/android/dialer/precall/impl/res/values/strings.xml
index 0d30ac9e5..db7df947b 100644
--- a/java/com/android/dialer/precall/impl/res/values/strings.xml
+++ b/java/com/android/dialer/precall/impl/res/values/strings.xml
@@ -17,7 +17,7 @@
<resources>
<!-- Title of the dialog to select which SIM to call with before making a call, if the device has
multiple SIMs [CHAR LIMIT=40]-->
- <string name="pre_call_select_phone_account">Call with</string>
+ <string name="pre_call_select_phone_account">Choose SIM for this call</string>
<!-- Checkbox label when selecting a SIM when calling a contact, to use the selected SIM for the
same contact and never ask again [CHAR LIMIT=40]-->
@@ -25,10 +25,10 @@
<!-- Hint text under a SIM when selecting SIM to call, indicating the SIM is on the same carrier
as the outgoing call.[CHAR LIMIT=40]-->
- <string name="pre_call_select_phone_account_hint_intra_carrier">Same carrier</string>
+ <string name="pre_call_select_phone_account_hint_intra_carrier">Uses your carrier</string>
<!-- Hint text under a SIM when selecting SIM to call, indicating user often use the SIM to call
the contact.[CHAR LIMIT=40]-->
- <string name="pre_call_select_phone_account_hint_frequent">You use often</string>
+ <string name="pre_call_select_phone_account_hint_frequent">Recently used</string>
</resources> \ No newline at end of file
diff --git a/java/com/android/incallui/CallButtonPresenter.java b/java/com/android/incallui/CallButtonPresenter.java
index bd3ba6dc6..c20642b59 100644
--- a/java/com/android/incallui/CallButtonPresenter.java
+++ b/java/com/android/incallui/CallButtonPresenter.java
@@ -28,6 +28,7 @@ import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.logging.DialerImpression;
+import com.android.dialer.logging.DialerImpression.Type;
import com.android.dialer.logging.Logger;
import com.android.dialer.telecom.TelecomUtil;
import com.android.incallui.InCallCameraManager.Listener;
@@ -318,6 +319,7 @@ public class CallButtonPresenter
@Override
public void swapSimClicked() {
LogUtil.enterBlock("CallButtonPresenter.swapSimClicked");
+ Logger.get(getContext()).logImpression(Type.DUAL_SIM_CHANGE_SIM_PRESSED);
SwapSimWorker worker =
new SwapSimWorker(
getContext(),
@@ -466,6 +468,7 @@ public class CallButtonPresenter
mOtherAccount = TelecomUtil.getOtherAccount(getContext(), call.getAccountHandle());
boolean showSwapSim =
mOtherAccount != null
+ && !call.isVoiceMailNumber()
&& DialerCall.State.isDialing(call.getState())
// Most devices cannot make calls on 2 SIMs at the same time.
&& InCallPresenter.getInstance().getCallList().getAllCalls().size() == 1;
diff --git a/java/com/android/incallui/DialpadFragment.java b/java/com/android/incallui/DialpadFragment.java
index fbcd4078e..2f3a68cda 100644
--- a/java/com/android/incallui/DialpadFragment.java
+++ b/java/com/android/incallui/DialpadFragment.java
@@ -18,8 +18,6 @@ package com.android.incallui;
import android.content.Context;
import android.os.Bundle;
-import android.text.Editable;
-import android.text.method.DialerKeyListener;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.view.KeyEvent;
@@ -32,6 +30,7 @@ import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.contacts.common.compat.PhoneNumberUtilsCompat;
+import com.android.dialer.common.LogUtil;
import com.android.dialer.dialpadview.DialpadKeyButton;
import com.android.dialer.dialpadview.DialpadKeyButton.OnPressedListener;
import com.android.dialer.dialpadview.DialpadView;
@@ -82,7 +81,7 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
};
private EditText mDtmfDialerField;
// KeyListener used with the "dialpad digits" EditText widget.
- private DTMFKeyListener mDialerKeyListener;
+ private DtmfKeyListener mDtmfKeyListener;
private DialpadView mDialpadView;
private int mCurrentTextColor;
@@ -141,8 +140,9 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
mDialpadView.setBackgroundResource(R.color.incall_dialpad_background);
mDtmfDialerField = (EditText) parent.findViewById(R.id.digits);
if (mDtmfDialerField != null) {
- mDialerKeyListener = new DTMFKeyListener();
- mDtmfDialerField.setKeyListener(mDialerKeyListener);
+ LogUtil.i("DialpadFragment.onCreateView", "creating dtmfKeyListener");
+ mDtmfKeyListener = new DtmfKeyListener(getPresenter());
+ mDtmfDialerField.setKeyListener(mDtmfKeyListener);
// remove the long-press context menus that support
// the edit (copy / paste / select) functions.
mDtmfDialerField.setLongClickable(false);
@@ -180,7 +180,7 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
@Override
public void onDestroyView() {
- mDialerKeyListener = null;
+ mDtmfKeyListener = null;
super.onDestroyView();
}
@@ -236,8 +236,8 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
/** Called externally (from InCallScreen) to play a DTMF Tone. */
/* package */ boolean onDialerKeyDown(KeyEvent event) {
Log.d(this, "Notifying dtmf key down.");
- if (mDialerKeyListener != null) {
- return mDialerKeyListener.onKeyDown(event);
+ if (mDtmfKeyListener != null) {
+ return mDtmfKeyListener.onKeyDown(event);
} else {
return false;
}
@@ -246,8 +246,8 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
/** Called externally (from InCallScreen) to cancel the last DTMF Tone played. */
public boolean onDialerKeyUp(KeyEvent event) {
Log.d(this, "Notifying dtmf key up.");
- if (mDialerKeyListener != null) {
- return mDialerKeyListener.onKeyUp(event);
+ if (mDtmfKeyListener != null) {
+ return mDtmfKeyListener.onKeyUp(event);
} else {
return false;
}
@@ -307,162 +307,4 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
setTranslationY(yFraction * getHeight());
}
}
-
- /**
- * Our own key listener, specialized for dealing with DTMF codes. 1. Ignore the backspace since it
- * is irrelevant. 2. Allow ONLY valid DTMF characters to generate a tone and be sent as a DTMF
- * code. 3. All other remaining characters are handled by the superclass.
- *
- * <p>This code is purely here to handle events from the hardware keyboard while the DTMF dialpad
- * is up.
- */
- private class DTMFKeyListener extends DialerKeyListener {
-
- /**
- * Overrides the characters used in {@link DialerKeyListener#CHARACTERS} These are the valid
- * dtmf characters.
- */
- public final char[] dtmfCharacters =
- new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*'};
-
- private DTMFKeyListener() {
- super();
- }
-
- /** Overriden to return correct DTMF-dialable characters. */
- @Override
- protected char[] getAcceptedChars() {
- return dtmfCharacters;
- }
-
- /** special key listener ignores backspace. */
- @Override
- public boolean backspace(View view, Editable content, int keyCode, KeyEvent event) {
- return false;
- }
-
- /**
- * Overriden so that with each valid button press, we start sending a dtmf code and play a local
- * dtmf tone.
- */
- @Override
- public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) {
- // if (DBG) log("DTMFKeyListener.onKeyDown, keyCode " + keyCode + ", view " + view);
-
- // find the character
- char c = (char) lookup(event, content);
-
- // if not a long press, and parent onKeyDown accepts the input
- if (event.getRepeatCount() == 0 && super.onKeyDown(view, content, keyCode, event)) {
-
- boolean keyOK = ok(getAcceptedChars(), c);
-
- // if the character is a valid dtmf code, start playing the tone and send the
- // code.
- if (keyOK) {
- Log.d(this, "DTMFKeyListener reading '" + c + "' from input.");
- getPresenter().processDtmf(c);
- } else {
- Log.d(this, "DTMFKeyListener rejecting '" + c + "' from input.");
- }
- return true;
- }
- return false;
- }
-
- /**
- * Overriden so that with each valid button up, we stop sending a dtmf code and the dtmf tone.
- */
- @Override
- public boolean onKeyUp(View view, Editable content, int keyCode, KeyEvent event) {
- // if (DBG) log("DTMFKeyListener.onKeyUp, keyCode " + keyCode + ", view " + view);
-
- super.onKeyUp(view, content, keyCode, event);
-
- // find the character
- char c = (char) lookup(event, content);
-
- boolean keyOK = ok(getAcceptedChars(), c);
-
- if (keyOK) {
- Log.d(this, "Stopping the tone for '" + c + "'");
- getPresenter().stopDtmf();
- return true;
- }
-
- return false;
- }
-
- /** Handle individual keydown events when we DO NOT have an Editable handy. */
- public boolean onKeyDown(KeyEvent event) {
- char c = lookup(event);
- Log.d(this, "DTMFKeyListener.onKeyDown: event '" + c + "'");
-
- // if not a long press, and parent onKeyDown accepts the input
- if (event.getRepeatCount() == 0 && c != 0) {
- // if the character is a valid dtmf code, start playing the tone and send the
- // code.
- if (ok(getAcceptedChars(), c)) {
- Log.d(this, "DTMFKeyListener reading '" + c + "' from input.");
- getPresenter().processDtmf(c);
- return true;
- } else {
- Log.d(this, "DTMFKeyListener rejecting '" + c + "' from input.");
- }
- }
- return false;
- }
-
- /**
- * Handle individual keyup events.
- *
- * @param event is the event we are trying to stop. If this is null, then we just force-stop the
- * last tone without checking if the event is an acceptable dialer event.
- */
- public boolean onKeyUp(KeyEvent event) {
- if (event == null) {
- //the below piece of code sends stopDTMF event unnecessarily even when a null event
- //is received, hence commenting it.
- /*if (DBG) log("Stopping the last played tone.");
- stopTone();*/
- return true;
- }
-
- char c = lookup(event);
- Log.d(this, "DTMFKeyListener.onKeyUp: event '" + c + "'");
-
- // TODO: stopTone does not take in character input, we may want to
- // consider checking for this ourselves.
- if (ok(getAcceptedChars(), c)) {
- Log.d(this, "Stopping the tone for '" + c + "'");
- getPresenter().stopDtmf();
- return true;
- }
-
- return false;
- }
-
- /**
- * Find the Dialer Key mapped to this event.
- *
- * @return The char value of the input event, otherwise 0 if no matching character was found.
- */
- private char lookup(KeyEvent event) {
- // This code is similar to {@link DialerKeyListener#lookup(KeyEvent, Spannable) lookup}
- int meta = event.getMetaState();
- int number = event.getNumber();
-
- if (!((meta & (KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON)) == 0) || (number == 0)) {
- int match = event.getMatch(getAcceptedChars(), meta);
- number = (match != 0) ? match : number;
- }
-
- return (char) number;
- }
-
- /** Check to see if the keyEvent is dialable. */
- boolean isKeyEventAcceptable(KeyEvent event) {
- return (ok(getAcceptedChars(), lookup(event)));
- }
- }
}
diff --git a/java/com/android/incallui/DtmfKeyListener.java b/java/com/android/incallui/DtmfKeyListener.java
new file mode 100644
index 000000000..a2a0de09e
--- /dev/null
+++ b/java/com/android/incallui/DtmfKeyListener.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.incallui;
+
+import android.support.annotation.NonNull;
+import android.text.Editable;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.method.DialerKeyListener;
+import android.view.KeyEvent;
+import android.view.View;
+import com.android.dialer.common.LogUtil;
+
+/**
+ * Key listener specialized to deal with Dtmf codes.
+ *
+ * <p>This listener will listen for valid Dtmf characters, and in response will inform the
+ * associated presenter of the character. As an implementation of {@link DialerKeyListener}, this
+ * class will listen for <b>hardware keyboard</b> events.
+ *
+ * <p>From legacy documentation:
+ *
+ * <ul>
+ * <li>Ignores the backspace since it is irrelevant.
+ * <li>Allow ONLY valid DTMF characters to generate a tone and be sent as a DTMF code.
+ * <li>All other remaining characters are handled by the superclass.
+ * <li>This code is purely here to handle events from the hardware keyboard while the DTMF dialpad
+ * is up.
+ * </ul>
+ */
+final class DtmfKeyListener extends DialerKeyListener {
+ /**
+ * Overrides the characters used in {@link DialerKeyListener#CHARACTERS} These are the valid dtmf
+ * characters.
+ */
+ private static final char[] VALID_DTMF_CHARACTERS =
+ new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*'};
+
+ /**
+ * Spannable used to call {@link DialerKeyListener#lookup(KeyEvent, Spannable)}, so it's not
+ * necessary to copy the implementation.
+ *
+ * <p>The Spannable is only used to determine which meta keys are pressed, e.g. shift, alt, see
+ * {@link android.text.method.MetaKeyKeyListener#getMetaState(CharSequence)}, so using a dummy
+ * value is fine here.
+ */
+ private static final Spannable EMPTY_SPANNABLE = new SpannableString("");
+
+ private final DialpadPresenter presenter;
+
+ DtmfKeyListener(@NonNull DialpadPresenter presenter) {
+ this.presenter = presenter;
+ }
+
+ @Override
+ protected char[] getAcceptedChars() {
+ return VALID_DTMF_CHARACTERS;
+ }
+
+ @Override
+ public boolean backspace(View view, Editable content, int keyCode, KeyEvent event) {
+ return false;
+ }
+
+ /**
+ * Responds to keyDown events by firing a Dtmf tone, if the given event corresponds is a {@link
+ * #VALID_DTMF_CHARACTERS}.
+ *
+ * @return {@code true} if the event was handled.
+ */
+ @Override
+ public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) {
+ LogUtil.i("DtmfKeyListener.onKeyDown", "overload");
+ if (!super.onKeyDown(view, content, keyCode, event)) {
+ LogUtil.i("DtmfKeyListener.onKeyDown", "parent type didn't support event");
+ return false;
+ }
+
+ return onKeyDown(event);
+ }
+
+ /**
+ * Version of {@link #onKeyDown(View, Editable, int, KeyEvent)} used when a View/Editable isn't
+ * available.
+ */
+ boolean onKeyDown(KeyEvent event) {
+ LogUtil.enterBlock("DtmfKeyListener.onKeyDown");
+ if (event.getRepeatCount() != 0) {
+ LogUtil.i("DtmfKeyListener.onKeyDown", "long press, ignoring");
+ return false;
+ }
+
+ char c = (char) lookup(event, EMPTY_SPANNABLE);
+
+ if (!ok(getAcceptedChars(), c)) {
+ LogUtil.i("DtmfKeyListener.onKeyDown", "not an accepted character");
+ return false;
+ }
+
+ presenter.processDtmf(c);
+ return true;
+ }
+
+ /**
+ * Responds to keyUp events by stopping any playing Dtmf tone if the given event corresponds is a
+ * {@link #VALID_DTMF_CHARACTERS}.
+ *
+ * <p>Null events also stop the Dtmf tone.
+ *
+ * @return {@code true} if the event was handled
+ */
+ @Override
+ public boolean onKeyUp(View view, Editable content, int keyCode, KeyEvent event) {
+ LogUtil.i("DtmfKeyListener.onKeyUp", "overload");
+ super.onKeyUp(view, content, keyCode, event);
+
+ return onKeyUp(event);
+ }
+
+ /**
+ * Handle individual keyup events.
+ *
+ * @param event is the event we are trying to stop. If this is null, then we just force-stop the
+ * last tone without checking if the event is an acceptable dialer event.
+ */
+ boolean onKeyUp(KeyEvent event) {
+ LogUtil.enterBlock("DtmfKeyListener.onKeyUp");
+ if (event == null) {
+ return true;
+ }
+
+ char c = (char) lookup(event, EMPTY_SPANNABLE);
+
+ if (!ok(getAcceptedChars(), c)) {
+ LogUtil.i("DtmfKeyListener.onKeyUp", "not an accepted character");
+ return false;
+ }
+
+ presenter.stopDtmf();
+ return true;
+ }
+}