diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2018-05-15 19:31:05 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2018-05-15 19:31:05 +0000 |
commit | 47636a2531e2a1d6c51b1cd3fb6e242f457b2f71 (patch) | |
tree | 2de3818a7fa2c123be648ee01d9e551596f09ae2 /java | |
parent | 21f2f3e1d5eba2cc436b0f1c78d9e354f209287d (diff) | |
parent | 3e2c6b8c22b238c3f3b1d9786a045f0a20615fa0 (diff) |
Merge changes Id53c298a,I7df0ece7,I9f41b1a7,Iffbfa408,I2aac0df1, ...
* changes:
Don't use LoaderManager.getInstance() in dialer.
Implement PhoneNumberCacheLookup
Fix add call button behavior.
Use component for iconography
Move SpamStub to separate package.
Initialize dialpadFragment and searchFragment with FragmentManager when MainSearchController is created
Compress all of dialer's png files.
Delete unused check__SpamStatus methods
Refactor simulator menu and add portal package for adding simulator service later.
Add simulator component in generated root component.
Update DialerCall to use SpamStatus instead of booleans
Added contacts permission screen to speed dial fragment.
Don't crash when cp2 returns a null label.
Register system call log content observer if user enables Phone permission.
Exit multiselect mode when opening the dialpad.
Support missing phone permission in new call log.
Diffstat (limited to 'java')
134 files changed, 823 insertions, 539 deletions
diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java index c819fecba..06f094d5e 100644 --- a/java/com/android/dialer/app/DialtactsActivity.java +++ b/java/com/android/dialer/app/DialtactsActivity.java @@ -46,6 +46,7 @@ import android.telecom.PhoneAccount; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; +import android.view.ActionMode; import android.view.DragEvent; import android.view.Gravity; import android.view.Menu; @@ -1532,7 +1533,7 @@ public class DialtactsActivity extends TransactionSafeActivity } @Override - public void onActionModeStateChanged(boolean isEnabled) { + public void onActionModeStateChanged(ActionMode mode, boolean isEnabled) { isMultiSelectModeEnabled = isEnabled; } diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java index c2c753e43..450e5eaa7 100644 --- a/java/com/android/dialer/app/calllog/CallLogAdapter.java +++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java @@ -178,7 +178,7 @@ public class CallLogAdapter extends GroupingListAdapter MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.actionbar_delete, menu); multiSelectRemoveView.showMultiSelectRemoveView(true); - actionModeStateChangedListener.onActionModeStateChanged(true); + actionModeStateChangedListener.onActionModeStateChanged(mode, true); return true; } @@ -216,7 +216,7 @@ public class CallLogAdapter extends GroupingListAdapter selectAllMode = false; deselectAllMode = false; multiSelectRemoveView.showMultiSelectRemoveView(false); - actionModeStateChangedListener.onActionModeStateChanged(false); + actionModeStateChangedListener.onActionModeStateChanged(null, false); notifyDataSetChanged(); } }; @@ -1511,7 +1511,7 @@ public class CallLogAdapter extends GroupingListAdapter /** Interface used to allow single tap multi select for contact photos. */ public interface OnActionModeStateChangedListener { - void onActionModeStateChanged(boolean isEnabled); + void onActionModeStateChanged(ActionMode mode, boolean isEnabled); boolean isActionModeStateEnabled(); } diff --git a/java/com/android/dialer/app/res/drawable-hdpi/empty_call_log.png b/java/com/android/dialer/app/res/drawable-hdpi/empty_call_log.png Binary files differindex d6f6daaab..b51b7b8d9 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/empty_call_log.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/empty_call_log.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/empty_speed_dial.png b/java/com/android/dialer/app/res/drawable-hdpi/empty_speed_dial.png Binary files differdeleted file mode 100644 index 3e9232fc9..000000000 --- a/java/com/android/dialer/app/res/drawable-hdpi/empty_speed_dial.png +++ /dev/null diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_menu_history_lt.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_menu_history_lt.png Binary files differindex a36323ca9..1c0c65458 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/ic_menu_history_lt.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/ic_menu_history_lt.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_mic_grey600.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_mic_grey600.png Binary files differindex 4b67cf71a..a392ff66b 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/ic_mic_grey600.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/ic_mic_grey600.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_not_interested_googblue_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_not_interested_googblue_24dp.png Binary files differindex 26a26f911..393a0c882 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/ic_not_interested_googblue_24dp.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/ic_not_interested_googblue_24dp.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_not_spam.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_not_spam.png Binary files differindex bf413f912..37caf38f4 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/ic_not_spam.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/ic_not_spam.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_phone_24dp.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_phone_24dp.png Binary files differindex b27dfba06..9d4148248 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/ic_phone_24dp.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/ic_phone_24dp.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_remove.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_remove.png Binary files differindex 1ee6adf8d..0af1e39fd 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/ic_remove.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/ic_remove.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_star.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_star.png Binary files differindex 62e1f8a6d..91c08cfe4 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/ic_star.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/ic_star.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/ic_unblock.png b/java/com/android/dialer/app/res/drawable-hdpi/ic_unblock.png Binary files differindex 03643b20d..177761068 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/ic_unblock.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/ic_unblock.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/old_ic_handle.png b/java/com/android/dialer/app/res/drawable-hdpi/old_ic_handle.png Binary files differindex 34310aa49..a1c248ce4 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/old_ic_handle.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/old_ic_handle.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/search_shadow.9.png b/java/com/android/dialer/app/res/drawable-hdpi/search_shadow.9.png Binary files differindex 3dc1c17f6..7e7c7c137 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/search_shadow.9.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/search_shadow.9.png diff --git a/java/com/android/dialer/app/res/drawable-hdpi/shadow_contact_photo.png b/java/com/android/dialer/app/res/drawable-hdpi/shadow_contact_photo.png Binary files differindex 44b06f261..1fa6c4aeb 100644 --- a/java/com/android/dialer/app/res/drawable-hdpi/shadow_contact_photo.png +++ b/java/com/android/dialer/app/res/drawable-hdpi/shadow_contact_photo.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/empty_call_log.png b/java/com/android/dialer/app/res/drawable-mdpi/empty_call_log.png Binary files differindex 3cd59b35b..a8d5a0c3c 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/empty_call_log.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/empty_call_log.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/empty_speed_dial.png b/java/com/android/dialer/app/res/drawable-mdpi/empty_speed_dial.png Binary files differdeleted file mode 100644 index 98152e0d3..000000000 --- a/java/com/android/dialer/app/res/drawable-mdpi/empty_speed_dial.png +++ /dev/null diff --git a/java/com/android/dialer/app/res/drawable-mdpi/ic_menu_history_lt.png b/java/com/android/dialer/app/res/drawable-mdpi/ic_menu_history_lt.png Binary files differindex 3597a5e82..4a87c9410 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/ic_menu_history_lt.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/ic_menu_history_lt.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/ic_mic_grey600.png b/java/com/android/dialer/app/res/drawable-mdpi/ic_mic_grey600.png Binary files differindex 2310c734a..f058bff88 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/ic_mic_grey600.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/ic_mic_grey600.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/ic_not_spam.png b/java/com/android/dialer/app/res/drawable-mdpi/ic_not_spam.png Binary files differindex b1f1c7efe..211baa90a 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/ic_not_spam.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/ic_not_spam.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/ic_phone_24dp.png b/java/com/android/dialer/app/res/drawable-mdpi/ic_phone_24dp.png Binary files differindex c1766b854..6539c3437 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/ic_phone_24dp.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/ic_phone_24dp.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/ic_remove.png b/java/com/android/dialer/app/res/drawable-mdpi/ic_remove.png Binary files differindex 2c134ea10..241a6a678 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/ic_remove.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/ic_remove.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/ic_star.png b/java/com/android/dialer/app/res/drawable-mdpi/ic_star.png Binary files differindex d2af0ba20..1f6366302 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/ic_star.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/ic_star.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/ic_unblock.png b/java/com/android/dialer/app/res/drawable-mdpi/ic_unblock.png Binary files differindex d80fb2f5c..9f303d9a0 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/ic_unblock.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/ic_unblock.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/old_ic_handle.png b/java/com/android/dialer/app/res/drawable-mdpi/old_ic_handle.png Binary files differindex 81a67ba6f..3671e9394 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/old_ic_handle.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/old_ic_handle.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/search_shadow.9.png b/java/com/android/dialer/app/res/drawable-mdpi/search_shadow.9.png Binary files differindex 0c33905cd..758ce8279 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/search_shadow.9.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/search_shadow.9.png diff --git a/java/com/android/dialer/app/res/drawable-mdpi/shadow_contact_photo.png b/java/com/android/dialer/app/res/drawable-mdpi/shadow_contact_photo.png Binary files differindex 8665d8303..5c802f946 100644 --- a/java/com/android/dialer/app/res/drawable-mdpi/shadow_contact_photo.png +++ b/java/com/android/dialer/app/res/drawable-mdpi/shadow_contact_photo.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/empty_call_log.png b/java/com/android/dialer/app/res/drawable-xhdpi/empty_call_log.png Binary files differindex 14ec04ba1..eabc83819 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/empty_call_log.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/empty_call_log.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/empty_speed_dial.png b/java/com/android/dialer/app/res/drawable-xhdpi/empty_speed_dial.png Binary files differdeleted file mode 100644 index a3a76751b..000000000 --- a/java/com/android/dialer/app/res/drawable-xhdpi/empty_speed_dial.png +++ /dev/null diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/ic_menu_history_lt.png b/java/com/android/dialer/app/res/drawable-xhdpi/ic_menu_history_lt.png Binary files differindex 6b411cbc3..27dbebff3 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/ic_menu_history_lt.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/ic_menu_history_lt.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/ic_mic_grey600.png b/java/com/android/dialer/app/res/drawable-xhdpi/ic_mic_grey600.png Binary files differindex a9a83b329..e1d6a5c17 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/ic_mic_grey600.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/ic_mic_grey600.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/ic_not_spam.png b/java/com/android/dialer/app/res/drawable-xhdpi/ic_not_spam.png Binary files differindex 138f27cdb..8fdd43fdf 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/ic_not_spam.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/ic_not_spam.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/ic_phone_24dp.png b/java/com/android/dialer/app/res/drawable-xhdpi/ic_phone_24dp.png Binary files differindex 83167f4cd..8d250c8ad 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/ic_phone_24dp.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/ic_phone_24dp.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/ic_remove.png b/java/com/android/dialer/app/res/drawable-xhdpi/ic_remove.png Binary files differindex be81592ef..ac81f84f0 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/ic_remove.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/ic_remove.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/ic_star.png b/java/com/android/dialer/app/res/drawable-xhdpi/ic_star.png Binary files differindex 2071f42f2..19518848a 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/ic_star.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/ic_star.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/ic_unblock.png b/java/com/android/dialer/app/res/drawable-xhdpi/ic_unblock.png Binary files differindex f7dfa21ac..c6e6595ce 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/ic_unblock.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/ic_unblock.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/old_ic_handle.png b/java/com/android/dialer/app/res/drawable-xhdpi/old_ic_handle.png Binary files differindex 0ad839286..36f3466a6 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/old_ic_handle.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/old_ic_handle.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/search_shadow.9.png b/java/com/android/dialer/app/res/drawable-xhdpi/search_shadow.9.png Binary files differindex 5667ab368..ad4528698 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/search_shadow.9.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/search_shadow.9.png diff --git a/java/com/android/dialer/app/res/drawable-xhdpi/shadow_contact_photo.png b/java/com/android/dialer/app/res/drawable-xhdpi/shadow_contact_photo.png Binary files differindex 8359a50e9..4e09fd712 100644 --- a/java/com/android/dialer/app/res/drawable-xhdpi/shadow_contact_photo.png +++ b/java/com/android/dialer/app/res/drawable-xhdpi/shadow_contact_photo.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/empty_call_log.png b/java/com/android/dialer/app/res/drawable-xxhdpi/empty_call_log.png Binary files differindex 501d7f1e2..ddb88237a 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/empty_call_log.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/empty_call_log.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/empty_speed_dial.png b/java/com/android/dialer/app/res/drawable-xxhdpi/empty_speed_dial.png Binary files differdeleted file mode 100644 index fb2ea5f15..000000000 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/empty_speed_dial.png +++ /dev/null diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_menu_history_lt.png b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_menu_history_lt.png Binary files differindex 779bc0620..75a633ce5 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_menu_history_lt.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_menu_history_lt.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_mic_grey600.png b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_mic_grey600.png Binary files differindex 07128dd82..726fc11ba 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_mic_grey600.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_mic_grey600.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_not_spam.png b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_not_spam.png Binary files differindex f699959cb..941ce8dea 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_not_spam.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_not_spam.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_phone_24dp.png b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_phone_24dp.png Binary files differindex 8fff728bb..9b366f702 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_phone_24dp.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_phone_24dp.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_remove.png b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_remove.png Binary files differindex 2722f23aa..9281ab914 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_remove.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_remove.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_star.png b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_star.png Binary files differindex f3c830435..94fd394f7 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_star.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_star.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_unblock.png b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_unblock.png Binary files differindex 828a4879f..52fce33fc 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/ic_unblock.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/ic_unblock.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/old_ic_handle.png b/java/com/android/dialer/app/res/drawable-xxhdpi/old_ic_handle.png Binary files differindex d07a1d057..269cb3810 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/old_ic_handle.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/old_ic_handle.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/search_shadow.9.png b/java/com/android/dialer/app/res/drawable-xxhdpi/search_shadow.9.png Binary files differindex ff55620d0..fc6f3bf5d 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/search_shadow.9.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/search_shadow.9.png diff --git a/java/com/android/dialer/app/res/drawable-xxhdpi/shadow_contact_photo.png b/java/com/android/dialer/app/res/drawable-xxhdpi/shadow_contact_photo.png Binary files differindex bfeb0ff53..f7b8d2d9a 100644 --- a/java/com/android/dialer/app/res/drawable-xxhdpi/shadow_contact_photo.png +++ b/java/com/android/dialer/app/res/drawable-xxhdpi/shadow_contact_photo.png diff --git a/java/com/android/dialer/app/res/drawable-xxxhdpi/empty_call_log.png b/java/com/android/dialer/app/res/drawable-xxxhdpi/empty_call_log.png Binary files differindex fbac1e40f..5704d753f 100644 --- a/java/com/android/dialer/app/res/drawable-xxxhdpi/empty_call_log.png +++ b/java/com/android/dialer/app/res/drawable-xxxhdpi/empty_call_log.png diff --git a/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_mic_grey600.png b/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_mic_grey600.png Binary files differindex b7403ff22..d80da4bb4 100644 --- a/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_mic_grey600.png +++ b/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_mic_grey600.png diff --git a/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_not_spam.png b/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_not_spam.png Binary files differindex 2a18de24e..d1634c13b 100644 --- a/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_not_spam.png +++ b/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_not_spam.png diff --git a/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_phone_24dp.png b/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_phone_24dp.png Binary files differindex 30d141db5..71c48f111 100644 --- a/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_phone_24dp.png +++ b/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_phone_24dp.png diff --git a/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_unblock.png b/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_unblock.png Binary files differindex 99a1842a2..01551e2fc 100644 --- a/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_unblock.png +++ b/java/com/android/dialer/app/res/drawable-xxxhdpi/ic_unblock.png diff --git a/java/com/android/dialer/app/res/drawable-xxxhdpi/nui_launcher_icon.png b/java/com/android/dialer/app/res/drawable-xxxhdpi/nui_launcher_icon.png Binary files differindex 7845ebca4..b0bb8f59f 100644 --- a/java/com/android/dialer/app/res/drawable-xxxhdpi/nui_launcher_icon.png +++ b/java/com/android/dialer/app/res/drawable-xxxhdpi/nui_launcher_icon.png diff --git a/java/com/android/dialer/app/res/drawable-xxxhdpi/old_ic_handle.png b/java/com/android/dialer/app/res/drawable-xxxhdpi/old_ic_handle.png Binary files differindex 72641c7ab..0a659982b 100644 --- a/java/com/android/dialer/app/res/drawable-xxxhdpi/old_ic_handle.png +++ b/java/com/android/dialer/app/res/drawable-xxxhdpi/old_ic_handle.png diff --git a/java/com/android/dialer/app/res/drawable-xxxhdpi/search_shadow.9.png b/java/com/android/dialer/app/res/drawable-xxxhdpi/search_shadow.9.png Binary files differindex ff55620d0..fc6f3bf5d 100644 --- a/java/com/android/dialer/app/res/drawable-xxxhdpi/search_shadow.9.png +++ b/java/com/android/dialer/app/res/drawable-xxxhdpi/search_shadow.9.png diff --git a/java/com/android/dialer/app/res/mipmap-hdpi/ic_launcher_phone.png b/java/com/android/dialer/app/res/mipmap-hdpi/ic_launcher_phone.png Binary files differindex 15c41423b..0d1769a78 100644 --- a/java/com/android/dialer/app/res/mipmap-hdpi/ic_launcher_phone.png +++ b/java/com/android/dialer/app/res/mipmap-hdpi/ic_launcher_phone.png diff --git a/java/com/android/dialer/app/res/mipmap-mdpi/ic_launcher_phone.png b/java/com/android/dialer/app/res/mipmap-mdpi/ic_launcher_phone.png Binary files differindex 3088f7502..667fc5deb 100644 --- a/java/com/android/dialer/app/res/mipmap-mdpi/ic_launcher_phone.png +++ b/java/com/android/dialer/app/res/mipmap-mdpi/ic_launcher_phone.png diff --git a/java/com/android/dialer/app/res/mipmap-xhdpi/ic_launcher_phone.png b/java/com/android/dialer/app/res/mipmap-xhdpi/ic_launcher_phone.png Binary files differindex e87de01fb..2298d0dcc 100644 --- a/java/com/android/dialer/app/res/mipmap-xhdpi/ic_launcher_phone.png +++ b/java/com/android/dialer/app/res/mipmap-xhdpi/ic_launcher_phone.png diff --git a/java/com/android/dialer/app/res/mipmap-xxhdpi/ic_launcher_phone.png b/java/com/android/dialer/app/res/mipmap-xxhdpi/ic_launcher_phone.png Binary files differindex b866b79a7..b269b5aa7 100644 --- a/java/com/android/dialer/app/res/mipmap-xxhdpi/ic_launcher_phone.png +++ b/java/com/android/dialer/app/res/mipmap-xxhdpi/ic_launcher_phone.png diff --git a/java/com/android/dialer/app/res/mipmap-xxxhdpi/ic_launcher_phone.png b/java/com/android/dialer/app/res/mipmap-xxxhdpi/ic_launcher_phone.png Binary files differindex 26f51f153..dbc76f340 100644 --- a/java/com/android/dialer/app/res/mipmap-xxxhdpi/ic_launcher_phone.png +++ b/java/com/android/dialer/app/res/mipmap-xxxhdpi/ic_launcher_phone.png diff --git a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java index 6cbaf4fe7..8746b2bf1 100644 --- a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java +++ b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java @@ -37,7 +37,7 @@ import com.android.dialer.preferredsim.PreferredSimModule; import com.android.dialer.preferredsim.suggestion.stub.StubSimSuggestionModule; import com.android.dialer.simulator.impl.SimulatorModule; import com.android.dialer.simulator.stub.StubSimulatorEnrichedCallModule; -import com.android.dialer.spam.StubSpamModule; +import com.android.dialer.spam.stub.StubSpamModule; import com.android.dialer.storage.StorageModule; import com.android.dialer.strictmode.impl.SystemStrictModeModule; import com.android.incallui.calllocation.stub.StubCallLocationModule; diff --git a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java index f4f7a0a3b..62b8ca251 100644 --- a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java +++ b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java @@ -37,7 +37,7 @@ import com.android.dialer.preferredsim.PreferredSimModule; import com.android.dialer.preferredsim.suggestion.stub.StubSimSuggestionModule; import com.android.dialer.simulator.impl.SimulatorModule; import com.android.dialer.simulator.stub.StubSimulatorEnrichedCallModule; -import com.android.dialer.spam.StubSpamModule; +import com.android.dialer.spam.stub.StubSpamModule; import com.android.dialer.storage.StorageModule; import com.android.dialer.strictmode.impl.SystemStrictModeModule; import com.android.incallui.calllocation.impl.CallLocationModule; diff --git a/java/com/android/dialer/callcomposer/cameraui/res/drawable-xhdpi/ic_capture.png b/java/com/android/dialer/callcomposer/cameraui/res/drawable-xhdpi/ic_capture.png Binary files differindex 4ec9f75e8..66f9f0503 100644 --- a/java/com/android/dialer/callcomposer/cameraui/res/drawable-xhdpi/ic_capture.png +++ b/java/com/android/dialer/callcomposer/cameraui/res/drawable-xhdpi/ic_capture.png diff --git a/java/com/android/dialer/callcomposer/cameraui/res/drawable-xxhdpi/ic_capture.png b/java/com/android/dialer/callcomposer/cameraui/res/drawable-xxhdpi/ic_capture.png Binary files differindex e2345dc86..4308defa3 100644 --- a/java/com/android/dialer/callcomposer/cameraui/res/drawable-xxhdpi/ic_capture.png +++ b/java/com/android/dialer/callcomposer/cameraui/res/drawable-xxhdpi/ic_capture.png diff --git a/java/com/android/dialer/callcomposer/cameraui/res/drawable-xxxhdpi/ic_capture.png b/java/com/android/dialer/callcomposer/cameraui/res/drawable-xxxhdpi/ic_capture.png Binary files differindex 3bab00984..53a2f1179 100644 --- a/java/com/android/dialer/callcomposer/cameraui/res/drawable-xxxhdpi/ic_capture.png +++ b/java/com/android/dialer/callcomposer/cameraui/res/drawable-xxxhdpi/ic_capture.png diff --git a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java index a08b50eb8..1b66f5099 100644 --- a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java +++ b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java @@ -62,11 +62,13 @@ import java.util.Arrays; import java.util.List; import java.util.Set; import javax.inject.Inject; +import javax.inject.Singleton; /** * Responsible for defining the rows in the annotated call log and maintaining the columns in it * which are derived from the system call log. */ +@Singleton @SuppressWarnings("MissingPermission") public class SystemCallLogDataSource implements CallLogDataSource { @@ -81,6 +83,7 @@ public class SystemCallLogDataSource implements CallLogDataSource { private final Duo duo; @Nullable private Long lastTimestampProcessed; + private boolean isCallLogContentObserverRegistered = false; @Inject SystemCallLogDataSource( @@ -106,7 +109,6 @@ public class SystemCallLogDataSource implements CallLogDataSource { LogUtil.i("SystemCallLogDataSource.registerContentObservers", "no call log permissions"); return; } - // TODO(zachh): Need to somehow register observers if user enables permission after launch? // The system call log has a last updated timestamp, but deletes are physical (the "deleted" // column is unused). This means that we can't detect deletes without scanning the entire table, @@ -115,6 +117,7 @@ public class SystemCallLogDataSource implements CallLogDataSource { appContext .getContentResolver() .registerContentObserver(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL, true, markDirtyObserver); + isCallLogContentObserverRegistered = true; if (!PermissionsUtil.hasAddVoicemailPermissions(appContext)) { LogUtil.i("SystemCallLogDataSource.registerContentObservers", "no add voicemail permissions"); @@ -129,6 +132,7 @@ public class SystemCallLogDataSource implements CallLogDataSource { @Override public void unregisterContentObservers() { appContext.getContentResolver().unregisterContentObserver(markDirtyObserver); + isCallLogContentObserverRegistered = false; } @Override @@ -140,7 +144,6 @@ public class SystemCallLogDataSource implements CallLogDataSource { return null; }); - // TODO(zachh): Test re-enabling after deleting database like this. return Futures.transform( Futures.allAsList(deleteSharedPref, annotatedCallLogDatabaseHelper.delete()), unused -> null, @@ -154,6 +157,14 @@ public class SystemCallLogDataSource implements CallLogDataSource { @Override public ListenableFuture<Boolean> isDirty() { + // This can happen if the call log permission is enabled after the application is started. + if (!isCallLogContentObserverRegistered + && PermissionsUtil.hasCallLogReadPermissions(appContext)) { + registerContentObservers(); + // Consider the data source dirty because calls could have been missed while the content + // observer wasn't registered. + return Futures.immediateFuture(true); + } return backgroundExecutorService.submit(this::isDirtyInternal); } diff --git a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java index 1890b7433..2feed4068 100644 --- a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java +++ b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java @@ -21,6 +21,7 @@ import android.os.Bundle; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.v4.app.Fragment; +import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.Loader; import android.support.v4.content.LocalBroadcastManager; @@ -41,18 +42,26 @@ import com.android.dialer.common.concurrent.ThreadUtil; import com.android.dialer.metrics.Metrics; import com.android.dialer.metrics.MetricsComponent; import com.android.dialer.metrics.jank.RecyclerViewJankLogger; +import com.android.dialer.util.PermissionsUtil; +import com.android.dialer.widget.EmptyContentView; +import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import java.util.Arrays; import java.util.concurrent.TimeUnit; /** The "new" call log fragment implementation, which is built on top of the annotated call log. */ public final class NewCallLogFragment extends Fragment implements LoaderCallbacks<Cursor> { + private static final int PHONE_PERMISSIONS_REQUEST_CODE = 1; + private static final int LOADER_ID = 0; + @VisibleForTesting static final long MARK_ALL_CALLS_READ_WAIT_MILLIS = TimeUnit.SECONDS.toMillis(3); private RecyclerView recyclerView; + private EmptyContentView emptyContentView; private RefreshAnnotatedCallLogReceiver refreshAnnotatedCallLogReceiver; private SupportUiListener<Cursor> coalesingAnnotatedCallLogListener; @@ -133,6 +142,22 @@ public final class NewCallLogFragment extends Fragment implements LoaderCallback * will be called but it is not visible. */ private void onFragmentShown() { + LoaderManager loaderManager = getLoaderManager(); + if (!PermissionsUtil.hasCallLogReadPermissions(getContext())) { + recyclerView.setVisibility(View.GONE); + emptyContentView.setVisibility(View.VISIBLE); + loaderManager.destroyLoader(LOADER_ID); + return; + } + + recyclerView.setVisibility(View.VISIBLE); + emptyContentView.setVisibility(View.GONE); + + // This can happen if permissions were not enabled when the fragment was created. + if (loaderManager.getLoader(LOADER_ID) == null) { + loaderManager.restartLoader(LOADER_ID, null, this); + } + registerRefreshAnnotatedCallLogReceiver(); CallLogComponent.get(getContext()) @@ -193,16 +218,53 @@ public final class NewCallLogFragment extends Fragment implements LoaderCallback new RecyclerViewJankLogger( MetricsComponent.get(getContext()).metrics(), Metrics.NEW_CALL_LOG_JANK_EVENT_NAME)); + emptyContentView = view.findViewById(R.id.new_call_log_empty_content_view); + configureEmptyContentView(); + coalesingAnnotatedCallLogListener = DialerExecutorComponent.get(getContext()) .createUiListener( getChildFragmentManager(), /* taskId = */ "NewCallLogFragment.coalescingAnnotatedCallLog"); - getLoaderManager().restartLoader(0, null, this); + + if (PermissionsUtil.hasCallLogReadPermissions(getContext())) { + getLoaderManager().restartLoader(LOADER_ID, null, this); + } return view; } + private void configureEmptyContentView() { + emptyContentView.setImage(R.drawable.quantum_ic_query_builder_vd_theme_24); + emptyContentView.setImageTint(R.color.empty_call_log_icon_tint_color, null); + emptyContentView.setDescription(R.string.new_call_log_permission_no_calllog); + emptyContentView.setActionLabel(com.android.dialer.widget.R.string.permission_single_turn_on); + emptyContentView.setActionClickedListener(new TurnOnPhonePermissions()); + } + + private class TurnOnPhonePermissions implements OnEmptyViewActionButtonClickedListener { + + @Override + public void onEmptyViewActionButtonClicked() { + if (getContext() == null) { + LogUtil.w("TurnOnPhonePermissions.onEmptyViewActionButtonClicked", "no context"); + return; + } + String[] deniedPermissions = + PermissionsUtil.getPermissionsCurrentlyDenied( + getContext(), PermissionsUtil.allPhoneGroupPermissionsUsedInDialer); + if (deniedPermissions.length > 0) { + LogUtil.i( + "TurnOnPhonePermissions.onEmptyViewActionButtonClicked", + "requesting permissions: %s", + Arrays.toString(deniedPermissions)); + // Don't implement onRequestPermissionsResult; instead rely on views being updated in + // #onFragmentShown. + requestPermissions(deniedPermissions, PHONE_PERMISSIONS_REQUEST_CODE); + } + } + } + private void registerRefreshAnnotatedCallLogReceiver() { LogUtil.enterBlock("NewCallLogFragment.registerRefreshAnnotatedCallLogReceiver"); diff --git a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml index 048d562d3..1a2ec22d6 100644 --- a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml +++ b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml @@ -15,11 +15,26 @@ ~ limitations under the License --> -<android.support.v7.widget.RecyclerView +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/new_call_log_recycler_view" - android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/background_dialer_white" - android:paddingBottom="@dimen/floating_action_button_list_bottom_padding" - android:clipToPadding="false"/> + android:layout_width="match_parent"> + + <android.support.v7.widget.RecyclerView + android:id="@+id/new_call_log_recycler_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingBottom="@dimen/floating_action_button_list_bottom_padding" + android:background="@color/background_dialer_white" + android:clipToPadding="false"/> + + <com.android.dialer.widget.EmptyContentView + android:gravity="center_vertical" + android:id="@+id/new_call_log_empty_content_view" + android:background="@color/background_dialer_white" + android:layout_gravity="center" + android:layout_height="match_parent" + android:layout_width="match_parent" + android:visibility="gone"/> + +</FrameLayout> diff --git a/java/com/android/dialer/calllog/ui/res/values/colors.xml b/java/com/android/dialer/calllog/ui/res/values/colors.xml index 0a6d512ef..002aaf959 100644 --- a/java/com/android/dialer/calllog/ui/res/values/colors.xml +++ b/java/com/android/dialer/calllog/ui/res/values/colors.xml @@ -21,4 +21,6 @@ <color name="call_type_icon_read_color">#757575</color> <color name="call_type_icon_unread_color">#D32F2F</color> + + <color name="empty_call_log_icon_tint_color">#E1E1E1</color> </resources>
\ No newline at end of file diff --git a/java/com/android/dialer/calllog/ui/res/values/strings.xml b/java/com/android/dialer/calllog/ui/res/values/strings.xml index ec8d59503..699dfe9a6 100644 --- a/java/com/android/dialer/calllog/ui/res/values/strings.xml +++ b/java/com/android/dialer/calllog/ui/res/values/strings.xml @@ -36,4 +36,7 @@ Google Duo video calling lets you chat with friends and family face-to-face. Data charges may apply. <xliff:g example="Learn More">%1$s</xliff:g> </string> + <!-- Shown as a prompt to turn on the phone permission to enable the call log [CHAR LIMIT=NONE]--> + <string name="new_call_log_permission_no_calllog">To see your call log, turn on the Phone permission.</string> + </resources> diff --git a/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_add_call.png b/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_add_call.png Binary files differindex 4e0d5649e..7bc443b5b 100755..100644 --- a/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_add_call.png +++ b/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_add_call.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_current_call.png b/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_current_call.png Binary files differindex 2cf41d598..dccddeb31 100755..100644 --- a/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_current_call.png +++ b/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_current_call.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_tt_keypad.png b/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_tt_keypad.png Binary files differindex 043685fd9..9ad63ff1f 100755..100644 --- a/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_tt_keypad.png +++ b/java/com/android/dialer/dialpadview/res/drawable-hdpi/ic_dialer_fork_tt_keypad.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_add_call.png b/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_add_call.png Binary files differindex 56ac2a33a..8b9634133 100644 --- a/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_add_call.png +++ b/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_add_call.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_current_call.png b/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_current_call.png Binary files differindex 16a44a078..0bc00b68f 100644 --- a/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_current_call.png +++ b/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_current_call.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_tt_keypad.png b/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_tt_keypad.png Binary files differindex 66df69eac..f4038cd03 100644 --- a/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_tt_keypad.png +++ b/java/com/android/dialer/dialpadview/res/drawable-mdpi/ic_dialer_fork_tt_keypad.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_add_call.png b/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_add_call.png Binary files differindex aff140fcd..bf657b833 100644 --- a/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_add_call.png +++ b/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_add_call.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_current_call.png b/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_current_call.png Binary files differindex 8975727e0..e8ad65af5 100644 --- a/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_current_call.png +++ b/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_current_call.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_tt_keypad.png b/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_tt_keypad.png Binary files differindex 4d48ea9ea..b9b817bab 100644 --- a/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_tt_keypad.png +++ b/java/com/android/dialer/dialpadview/res/drawable-xhdpi/ic_dialer_fork_tt_keypad.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_add_call.png b/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_add_call.png Binary files differindex 1657da4e2..4f042aa72 100644 --- a/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_add_call.png +++ b/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_add_call.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_current_call.png b/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_current_call.png Binary files differindex f25cce695..81bece640 100644 --- a/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_current_call.png +++ b/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_current_call.png diff --git a/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_tt_keypad.png b/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_tt_keypad.png Binary files differindex 7ac4d8b58..ed4717ba8 100644 --- a/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_tt_keypad.png +++ b/java/com/android/dialer/dialpadview/res/drawable-xxhdpi/ic_dialer_fork_tt_keypad.png diff --git a/java/com/android/dialer/main/impl/MainSearchController.java b/java/com/android/dialer/main/impl/MainSearchController.java index 7d476c8f6..fc4fc3dcb 100644 --- a/java/com/android/dialer/main/impl/MainSearchController.java +++ b/java/com/android/dialer/main/impl/MainSearchController.java @@ -115,6 +115,11 @@ public class MainSearchController implements SearchBarListener { this.toolbar = toolbar; this.toolbarShadow = toolbarShadow; this.fragmentContainer = fragmentContainer; + + dialpadFragment = + (DialpadFragment) activity.getFragmentManager().findFragmentByTag(DIALPAD_FRAGMENT_TAG); + searchFragment = + (NewSearchFragment) activity.getFragmentManager().findFragmentByTag(SEARCH_FRAGMENT_TAG); } /** Should be called if we're showing the dialpad because of a new ACTION_DIAL intent. */ diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java index 2d6b0a6e7..16f46c10f 100644 --- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java +++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java @@ -48,6 +48,7 @@ import android.telecom.PhoneAccountHandle; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.text.method.LinkMovementMethod; +import android.view.ActionMode; import android.view.DragEvent; import android.view.View; import android.widget.ImageView; @@ -255,6 +256,10 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen v -> { Logger.get(activity).logImpression(DialerImpression.Type.MAIN_CLICK_FAB_TO_OPEN_DIALPAD); searchController.showDialpad(true); + if (callLogAdapterOnActionModeStateChangedListener.isEnabled) { + LogUtil.i("OldMainActivityPeer.onFabClicked", "closing multiselect"); + callLogAdapterOnActionModeStateChangedListener.actionMode.finish(); + } }); MainToolbar toolbar = activity.findViewById(R.id.toolbar); @@ -798,9 +803,11 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen implements CallLogAdapter.OnActionModeStateChangedListener { private boolean isEnabled; + private ActionMode actionMode; @Override - public void onActionModeStateChanged(boolean isEnabled) { + public void onActionModeStateChanged(ActionMode actionMode, boolean isEnabled) { + this.actionMode = actionMode; this.isEnabled = isEnabled; } diff --git a/java/com/android/dialer/main/impl/res/drawable-xxxhdpi/nui_launcher_icon.png b/java/com/android/dialer/main/impl/res/drawable-xxxhdpi/nui_launcher_icon.png Binary files differindex 7845ebca4..b0bb8f59f 100644 --- a/java/com/android/dialer/main/impl/res/drawable-xxxhdpi/nui_launcher_icon.png +++ b/java/com/android/dialer/main/impl/res/drawable-xxxhdpi/nui_launcher_icon.png diff --git a/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java b/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java index 29a0de56b..efd7ae6f1 100644 --- a/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java +++ b/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java @@ -47,7 +47,8 @@ public final class PhoneLookupInfoConsolidator { NameSource.CP2_EXTENDED_DIRECTORY, NameSource.PEOPLE_API, NameSource.CEQUINT, - NameSource.CNAP + NameSource.CNAP, + NameSource.PHONE_NUMBER_CACHE }) @interface NameSource { int NONE = 0; // used when none of the other sources can provide the name @@ -56,6 +57,7 @@ public final class PhoneLookupInfoConsolidator { int PEOPLE_API = 3; int CEQUINT = 4; int CNAP = 5; + int PHONE_NUMBER_CACHE = 6; } /** @@ -81,7 +83,8 @@ public final class PhoneLookupInfoConsolidator { NameSource.CP2_EXTENDED_DIRECTORY, NameSource.PEOPLE_API, NameSource.CEQUINT, - NameSource.CNAP); + NameSource.CNAP, + NameSource.PHONE_NUMBER_CACHE); private final @NameSource int nameSource; private final PhoneLookupInfo phoneLookupInfo; @@ -113,6 +116,13 @@ public final class PhoneLookupInfoConsolidator { return ContactSource.Type.SOURCE_TYPE_CEQUINT_CALLER_ID; case NameSource.CNAP: return ContactSource.Type.SOURCE_TYPE_CNAP; + case NameSource.PHONE_NUMBER_CACHE: + ContactSource.Type sourceType = + ContactSource.Type.forNumber(phoneLookupInfo.getMigratedInfo().getSourceType()); + if (sourceType == null) { + sourceType = ContactSource.Type.UNKNOWN_SOURCE_TYPE; + } + return sourceType; case NameSource.NONE: return ContactSource.Type.UNKNOWN_SOURCE_TYPE; default: @@ -155,6 +165,8 @@ public final class PhoneLookupInfoConsolidator { return phoneLookupInfo.getCequintInfo().getName(); case NameSource.CNAP: return phoneLookupInfo.getCnapInfo().getName(); + case NameSource.PHONE_NUMBER_CACHE: + return phoneLookupInfo.getMigratedInfo().getName(); case NameSource.NONE: return ""; default: @@ -176,6 +188,8 @@ public final class PhoneLookupInfoConsolidator { return Assert.isNotNull(firstDefaultCp2Contact).getPhotoThumbnailUri(); case NameSource.CP2_EXTENDED_DIRECTORY: return Assert.isNotNull(firstExtendedCp2Contact).getPhotoThumbnailUri(); + case NameSource.PHONE_NUMBER_CACHE: + return phoneLookupInfo.getMigratedInfo().getPhotoUri(); case NameSource.PEOPLE_API: case NameSource.CEQUINT: case NameSource.CNAP: @@ -202,6 +216,8 @@ public final class PhoneLookupInfoConsolidator { return Assert.isNotNull(firstExtendedCp2Contact).getPhotoUri(); case NameSource.CEQUINT: return phoneLookupInfo.getCequintInfo().getPhotoUri(); + case NameSource.PHONE_NUMBER_CACHE: + return phoneLookupInfo.getMigratedInfo().getPhotoUri(); case NameSource.PEOPLE_API: case NameSource.CNAP: case NameSource.NONE: @@ -222,6 +238,7 @@ public final class PhoneLookupInfoConsolidator { return Math.max(Assert.isNotNull(firstDefaultCp2Contact).getPhotoId(), 0); case NameSource.CP2_EXTENDED_DIRECTORY: return Math.max(Assert.isNotNull(firstExtendedCp2Contact).getPhotoId(), 0); + case NameSource.PHONE_NUMBER_CACHE: case NameSource.PEOPLE_API: case NameSource.CEQUINT: case NameSource.CNAP: @@ -246,6 +263,7 @@ public final class PhoneLookupInfoConsolidator { return Assert.isNotNull(firstExtendedCp2Contact).getLookupUri(); case NameSource.PEOPLE_API: return Assert.isNotNull(phoneLookupInfo.getPeopleApiInfo().getLookupUri()); + case NameSource.PHONE_NUMBER_CACHE: case NameSource.CEQUINT: case NameSource.CNAP: case NameSource.NONE: @@ -270,6 +288,8 @@ public final class PhoneLookupInfoConsolidator { return Assert.isNotNull(firstDefaultCp2Contact).getLabel(); case NameSource.CP2_EXTENDED_DIRECTORY: return Assert.isNotNull(firstExtendedCp2Contact).getLabel(); + case NameSource.PHONE_NUMBER_CACHE: + return phoneLookupInfo.getMigratedInfo().getLabel(); case NameSource.PEOPLE_API: case NameSource.CEQUINT: case NameSource.CNAP: @@ -296,6 +316,7 @@ public final class PhoneLookupInfoConsolidator { case NameSource.CP2_EXTENDED_DIRECTORY: case NameSource.PEOPLE_API: case NameSource.CNAP: + case NameSource.PHONE_NUMBER_CACHE: case NameSource.NONE: return ""; default: @@ -309,8 +330,21 @@ public final class PhoneLookupInfoConsolidator { * returns whether the number belongs to a business place. */ public boolean isBusiness() { - return phoneLookupInfo.hasPeopleApiInfo() - && phoneLookupInfo.getPeopleApiInfo().getInfoType() == InfoType.NEARBY_BUSINESS; + switch (nameSource) { + case NameSource.PEOPLE_API: + return phoneLookupInfo.getPeopleApiInfo().getInfoType() == InfoType.NEARBY_BUSINESS; + case NameSource.PHONE_NUMBER_CACHE: + return phoneLookupInfo.getMigratedInfo().getIsBusiness(); + case NameSource.CP2_DEFAULT_DIRECTORY: + case NameSource.CP2_EXTENDED_DIRECTORY: + case NameSource.CEQUINT: + case NameSource.CNAP: + case NameSource.NONE: + return false; + default: + throw Assert.createUnsupportedOperationFailException( + String.format("Unsupported name source: %s", nameSource)); + } } /** @@ -366,6 +400,7 @@ public final class PhoneLookupInfoConsolidator { case NameSource.CP2_EXTENDED_DIRECTORY: case NameSource.CEQUINT: case NameSource.CNAP: + case NameSource.PHONE_NUMBER_CACHE: case NameSource.NONE: return false; case NameSource.PEOPLE_API: @@ -390,6 +425,7 @@ public final class PhoneLookupInfoConsolidator { case NameSource.PEOPLE_API: case NameSource.CEQUINT: case NameSource.CNAP: + case NameSource.PHONE_NUMBER_CACHE: case NameSource.NONE: return false; default: @@ -452,6 +488,11 @@ public final class PhoneLookupInfoConsolidator { return NameSource.CNAP; } break; + case NameSource.PHONE_NUMBER_CACHE: + if (!phoneLookupInfo.getMigratedInfo().getName().isEmpty()) { + return NameSource.PHONE_NUMBER_CACHE; + } + break; default: throw Assert.createUnsupportedOperationFailException( String.format("Unsupported name source: %s", nameSource)); diff --git a/java/com/android/dialer/phonelookup/phone_lookup_info.proto b/java/com/android/dialer/phonelookup/phone_lookup_info.proto index 9e9dfa918..f5ab5f0a9 100644 --- a/java/com/android/dialer/phonelookup/phone_lookup_info.proto +++ b/java/com/android/dialer/phonelookup/phone_lookup_info.proto @@ -14,7 +14,7 @@ package com.android.dialer.phonelookup; // "cp2_info_in_default_directory" corresponds to class // Cp2DefaultDirectoryPhoneLookup, and class Cp2DefaultDirectoryPhoneLookup // alone is responsible for populating it. -// Next ID: 10 +// Next ID: 11 message PhoneLookupInfo { // Information about a PhoneNumber retrieved from CP2. message Cp2Info { @@ -182,4 +182,19 @@ message PhoneLookupInfo { optional bool is_emergency_number = 1; } optional EmergencyInfo emergency_info = 9; + + // Information cached in the old calllog + message MigratedInfo { + // The display name + optional string name = 1; + // Display label, i.e. "Home", "Mobile" + optional string label = 2; + + optional string photo_uri = 3; + + optional bool is_business = 4; + // ContactSource.Type + optional int32 source_type = 5; + } + optional MigratedInfo migrated_info = 10; }
\ No newline at end of file diff --git a/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-hdpi/business_asset.png b/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-hdpi/business_asset.png Binary files differindex 8164c9a3e..062bba506 100644 --- a/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-hdpi/business_asset.png +++ b/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-hdpi/business_asset.png diff --git a/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-mdpi/business_asset.png b/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-mdpi/business_asset.png Binary files differindex e749e579e..60d84970c 100644 --- a/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-mdpi/business_asset.png +++ b/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-mdpi/business_asset.png diff --git a/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xhdpi/business_asset.png b/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xhdpi/business_asset.png Binary files differindex 6014f6801..e8a4e5de8 100644 --- a/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xhdpi/business_asset.png +++ b/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xhdpi/business_asset.png diff --git a/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xxhdpi/business_asset.png b/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xxhdpi/business_asset.png Binary files differindex 0dc4b4c89..73b716c8e 100644 --- a/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xxhdpi/business_asset.png +++ b/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xxhdpi/business_asset.png diff --git a/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xxxhdpi/business_asset.png b/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xxxhdpi/business_asset.png Binary files differindex ef7630302..b243f7182 100644 --- a/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xxxhdpi/business_asset.png +++ b/java/com/android/dialer/searchfragment/nearbyplaces/res/drawable-xxxhdpi/business_asset.png diff --git a/java/com/android/dialer/simulator/SimulatorComponent.java b/java/com/android/dialer/simulator/SimulatorComponent.java index 6fa3f0cb1..ff75e9fed 100644 --- a/java/com/android/dialer/simulator/SimulatorComponent.java +++ b/java/com/android/dialer/simulator/SimulatorComponent.java @@ -18,6 +18,7 @@ package com.android.dialer.simulator; import android.content.Context; import com.android.dialer.inject.HasRootComponent; +import com.android.dialer.inject.IncludeInDialerRoot; import dagger.Subcomponent; /** Subcomponent that can be used to access the simulator implementation. */ @@ -36,6 +37,7 @@ public abstract class SimulatorComponent { } /** Used to refer to the root application component. */ + @IncludeInDialerRoot public interface HasComponent { SimulatorComponent simulatorComponent(); } diff --git a/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java b/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java index 81a3d30de..8e794f051 100644 --- a/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java +++ b/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java @@ -32,7 +32,7 @@ import java.util.ArrayList; import java.util.Locale; /** Creates a conference with a given number of participants. */ -final class SimulatorConferenceCreator +public final class SimulatorConferenceCreator implements SimulatorConnectionService.Listener, SimulatorConnection.Listener, SimulatorConference.Listener { @@ -53,7 +53,12 @@ final class SimulatorConferenceCreator simulatorConnectionsBank = SimulatorComponent.get(context).getSimulatorConnectionsBank(); } - void start(int callCount) { + /** + * Starts to create certain number of calls to form a conference call. + * + * @param callCount the number of calls in conference to create. + */ + public void start(int callCount) { onNewIncomingConnectionEnabled = true; SimulatorConnectionService.addListener(this); if (conferenceType == Simulator.CONFERENCE_TYPE_VOLTE) { diff --git a/java/com/android/dialer/simulator/impl/SimulatorImpl.java b/java/com/android/dialer/simulator/impl/SimulatorImpl.java index c8b8af92e..44f8e118b 100644 --- a/java/com/android/dialer/simulator/impl/SimulatorImpl.java +++ b/java/com/android/dialer/simulator/impl/SimulatorImpl.java @@ -22,6 +22,7 @@ import com.android.dialer.buildtype.BuildType; import com.android.dialer.buildtype.BuildType.Type; import com.android.dialer.common.LogUtil; import com.android.dialer.simulator.Simulator; +import com.android.dialer.simulator.portal.SimulatorMainPortal; import javax.inject.Inject; /** The entry point for the simulator feature. */ @@ -39,7 +40,7 @@ final class SimulatorImpl implements Simulator { @Override public ActionProvider getActionProvider(AppCompatActivity activity) { - return SimulatorMainMenu.getActionProvider(activity); + return new SimulatorMainPortal(activity).getActionProvider(); } @Override diff --git a/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java b/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java index b8556156b..52d7352ac 100644 --- a/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java +++ b/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java @@ -30,14 +30,14 @@ import com.android.dialer.common.concurrent.ThreadUtil; * notifications instead of writing to the call log directly. This makes the simulator behave more * like the real application. */ -final class SimulatorMissedCallCreator implements SimulatorConnectionService.Listener { +public final class SimulatorMissedCallCreator implements SimulatorConnectionService.Listener { private static final String EXTRA_CALL_COUNT = "call_count"; private static final String EXTRA_IS_MISSED_CALL_CONNECTION = "is_missed_call_connection"; private static final int DISCONNECT_DELAY_MILLIS = 1000; private final Context context; - SimulatorMissedCallCreator(@NonNull Context context) { + public SimulatorMissedCallCreator(@NonNull Context context) { this.context = Assert.isNotNull(context); } diff --git a/java/com/android/dialer/simulator/impl/SimulatorNotifications.java b/java/com/android/dialer/simulator/impl/SimulatorNotifications.java deleted file mode 100644 index bd17b7ff8..000000000 --- a/java/com/android/dialer/simulator/impl/SimulatorNotifications.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.simulator.impl; - -import android.content.ContentValues; -import android.content.Context; -import android.provider.VoicemailContract.Voicemails; -import android.support.annotation.NonNull; -import android.view.ActionProvider; -import com.android.dialer.common.LogUtil; -import com.android.dialer.databasepopulator.VoicemailPopulator; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** Implements the simulator submenu. */ -final class SimulatorNotifications { - private static final int NOTIFICATION_COUNT = 12; - - static ActionProvider getActionProvider(@NonNull Context context) { - return new SimulatorSubMenu(context) - .addItem( - "Missed calls", () -> new SimulatorMissedCallCreator(context).start(NOTIFICATION_COUNT)) - .addItem("Voicemails", () -> addVoicemailNotifications(context)); - } - - private static void addVoicemailNotifications(@NonNull Context context) { - LogUtil.enterBlock("SimulatorNotifications.addVoicemailNotifications"); - List<ContentValues> voicemails = new ArrayList<>(); - for (int i = NOTIFICATION_COUNT; i > 0; i--) { - VoicemailPopulator.Voicemail voicemail = - VoicemailPopulator.Voicemail.builder() - .setPhoneNumber(String.format("+%d", i)) - .setTranscription(String.format("Short transcript %d", i)) - .setDurationSeconds(60) - .setIsRead(false) - .setPhoneAccountComponentName("") - .setTimeMillis(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(i)) - .build(); - voicemails.add(voicemail.getAsContentValues(context)); - } - context - .getContentResolver() - .bulkInsert( - Voicemails.buildSourceUri(context.getPackageName()), - voicemails.toArray(new ContentValues[voicemails.size()])); - } -} diff --git a/java/com/android/dialer/simulator/impl/SimulatorRttCall.java b/java/com/android/dialer/simulator/impl/SimulatorRttCall.java index 352b9e4ef..afd897775 100644 --- a/java/com/android/dialer/simulator/impl/SimulatorRttCall.java +++ b/java/com/android/dialer/simulator/impl/SimulatorRttCall.java @@ -21,7 +21,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.telecom.Connection; import android.telecom.DisconnectCause; -import android.view.ActionProvider; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.ThreadUtil; @@ -29,28 +28,21 @@ import com.android.dialer.simulator.Simulator; import com.android.dialer.simulator.Simulator.Event; /** Entry point in the simulator to create voice calls. */ -final class SimulatorRttCall +public final class SimulatorRttCall implements SimulatorConnectionService.Listener, SimulatorConnection.Listener { @NonNull private final Context context; @Nullable private String connectionTag; private RttChatBot rttChatBot; - static ActionProvider getActionProvider(@NonNull Context context) { - return new SimulatorSubMenu(context) - .addItem("Incoming call", () -> new SimulatorRttCall(context).addNewIncomingCall(false)) - .addItem("Outgoing call", () -> new SimulatorRttCall(context).addNewOutgoingCall()) - .addItem("Emergency call", () -> new SimulatorRttCall(context).addNewEmergencyCall()); - } - - private SimulatorRttCall(@NonNull Context context) { + public SimulatorRttCall(@NonNull Context context) { this.context = Assert.isNotNull(context); SimulatorConnectionService.addListener(this); SimulatorConnectionService.addListener( new SimulatorConferenceCreator(context, Simulator.CONFERENCE_TYPE_GSM)); } - private void addNewIncomingCall(boolean isSpam) { + public void addNewIncomingCall(boolean isSpam) { String callerId = isSpam ? "+1-661-778-3020" /* Blacklisted custom spam number */ @@ -60,14 +52,14 @@ final class SimulatorRttCall context, callerId, SimulatorSimCallManager.CALL_TYPE_RTT); } - private void addNewOutgoingCall() { + public void addNewOutgoingCall() { String callerId = "+55-31-2128-6800"; // Brazil office. connectionTag = SimulatorSimCallManager.addNewOutgoingCall( context, callerId, SimulatorSimCallManager.CALL_TYPE_RTT); } - private void addNewEmergencyCall() { + public void addNewEmergencyCall() { String callerId = "911"; connectionTag = SimulatorSimCallManager.addNewIncomingCall( diff --git a/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java b/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java index c56afb21f..0296ace4b 100644 --- a/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java +++ b/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java @@ -64,7 +64,7 @@ public class SimulatorSimCallManager { private static final String EXTRA_CONNECTION_TAG = "connection_tag"; private static final String EXTRA_CONNECTION_CALL_TYPE = "connection_call_type"; - static void register(@NonNull Context context) { + public static void register(@NonNull Context context) { LogUtil.enterBlock("SimulatorSimCallManager.register"); Assert.isNotNull(context); StrictModeUtils.bypass( @@ -75,7 +75,7 @@ public class SimulatorSimCallManager { }); } - static void unregister(@NonNull Context context) { + public static void unregister(@NonNull Context context) { LogUtil.enterBlock("SimulatorSimCallManager.unregister"); Assert.isNotNull(context); StrictModeUtils.bypass( diff --git a/java/com/android/dialer/simulator/impl/SimulatorSubMenu.java b/java/com/android/dialer/simulator/impl/SimulatorSubMenu.java deleted file mode 100644 index 64a2e7265..000000000 --- a/java/com/android/dialer/simulator/impl/SimulatorSubMenu.java +++ /dev/null @@ -1,100 +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.simulator.impl; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.ActionProvider; -import android.view.MenuItem; -import android.view.SubMenu; -import android.view.View; -import com.android.dialer.common.Assert; -import java.util.ArrayList; -import java.util.List; - -/** Makes it easier to create submenus in the simulator. */ -final class SimulatorSubMenu extends ActionProvider { - List<Item> items = new ArrayList<>(); - - SimulatorSubMenu(@NonNull Context context) { - super(Assert.isNotNull(context)); - } - - SimulatorSubMenu addItem(@NonNull String title, @NonNull Runnable clickHandler) { - items.add(new Item(title, clickHandler)); - return this; - } - - SimulatorSubMenu addItem(@NonNull String title, @NonNull ActionProvider actionProvider) { - items.add(new Item(title, actionProvider)); - return this; - } - - @Override - public View onCreateActionView() { - return null; - } - - @Override - public View onCreateActionView(MenuItem forItem) { - return null; - } - - @Override - public boolean hasSubMenu() { - return true; - } - - @Override - public void onPrepareSubMenu(SubMenu subMenu) { - super.onPrepareSubMenu(subMenu); - subMenu.clear(); - - for (Item item : items) { - if (item.clickHandler != null) { - subMenu - .add(item.title) - .setOnMenuItemClickListener( - (i) -> { - item.clickHandler.run(); - return true; - }); - } else { - subMenu.add(item.title).setActionProvider(item.actionProvider); - } - } - } - - private static final class Item { - @NonNull final String title; - @Nullable final Runnable clickHandler; - @Nullable final ActionProvider actionProvider; - - Item(@NonNull String title, @NonNull Runnable clickHandler) { - this.title = Assert.isNotNull(title); - this.clickHandler = Assert.isNotNull(clickHandler); - actionProvider = null; - } - - Item(@NonNull String title, @NonNull ActionProvider actionProvider) { - this.title = Assert.isNotNull(title); - this.clickHandler = null; - this.actionProvider = Assert.isNotNull(actionProvider); - } - } -} diff --git a/java/com/android/dialer/simulator/impl/SimulatorMainMenu.java b/java/com/android/dialer/simulator/impl/SimulatorUtils.java index ba2b55802..9e46f5aa9 100644 --- a/java/com/android/dialer/simulator/impl/SimulatorMainMenu.java +++ b/java/com/android/dialer/simulator/impl/SimulatorUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2018 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. @@ -16,73 +16,35 @@ package com.android.dialer.simulator.impl; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.provider.VoicemailContract; +import android.provider.VoicemailContract.Voicemails; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v7.app.AppCompatActivity; -import android.view.ActionProvider; +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.databasepopulator.BlockedBumberPopulator; import com.android.dialer.databasepopulator.CallLogPopulator; import com.android.dialer.databasepopulator.ContactsPopulator; import com.android.dialer.databasepopulator.VoicemailPopulator; -import com.android.dialer.enrichedcall.simulator.EnrichedCallSimulatorActivity; import com.android.dialer.persistentlog.PersistentLogger; import com.android.dialer.preferredsim.PreferredSimFallbackContract; -import com.android.dialer.simulator.SimulatorComponent; - -/** Implements the top level simulator menu. */ -final class SimulatorMainMenu { - - static ActionProvider getActionProvider(@NonNull AppCompatActivity activity) { - SimulatorSubMenu simulatorSubMenu = new SimulatorSubMenu(activity.getApplicationContext()); - simulatorSubMenu - .addItem("Voice call", SimulatorVoiceCall.getActionProvider(activity)) - .addItem("Rtt call", SimulatorRttCall.getActionProvider(activity.getApplicationContext())) - .addItem( - "IMS video", SimulatorVideoCall.getActionProvider(activity.getApplicationContext())) - .addItem( - "Notifications", - SimulatorNotifications.getActionProvider(activity.getApplicationContext())) - .addItem("Populate database", () -> populateDatabase(activity.getApplicationContext())) - .addItem("Populate voicemail", () -> populateVoicemail(activity.getApplicationContext())) - .addItem( - "Fast populate database", () -> fastPopulateDatabase(activity.getApplicationContext())) - .addItem( - "Fast populate voicemail database", - () -> populateVoicemailFast(activity.getApplicationContext())) - .addItem("Clean database", () -> cleanDatabase(activity.getApplicationContext())) - .addItem("clear preferred SIM", () -> clearPreferredSim(activity.getApplicationContext())) - .addItem("Sync voicemail", () -> syncVoicemail(activity.getApplicationContext())) - .addItem("Share persistent log", () -> sharePersistentLog(activity.getApplicationContext())) - .addItem( - "Enriched call simulator", - () -> - activity.startActivity( - EnrichedCallSimulatorActivity.newIntent(activity.getApplicationContext()))) - .addItem( - "Enable simulator mode", - () -> { - SimulatorComponent.get(activity.getApplicationContext()) - .getSimulator() - .enableSimulatorMode(); - SimulatorSimCallManager.register(activity.getApplicationContext()); - }) - .addItem( - "Disable simulator mode", - () -> { - SimulatorComponent.get(activity.getApplicationContext()) - .getSimulator() - .disableSimulatorMode(); - SimulatorSimCallManager.unregister(activity.getApplicationContext()); - }); - return simulatorSubMenu; - } +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +/** Contains utilities used often in test workflow. */ +public class SimulatorUtils { + + public static final int NOTIFICATION_COUNT_FEW = 1; + public static final int NOTIFICATION_COUNT = 12; - private static void populateDatabase(@NonNull Context context) { + /** Populates contacts database with predefined contacts entries. */ + public static void populateDatabase(@NonNull Context context) { DialerExecutorComponent.get(context) .dialerExecutorFactory() .createNonUiTaskBuilder(new PopulateDatabaseWorker()) @@ -90,7 +52,8 @@ final class SimulatorMainMenu { .executeSerial(new PopulateDatabaseWorkerInput(context, false)); } - private static void populateVoicemail(@NonNull Context context) { + /** Populates voicemail database with predefined voicemail entries. */ + public static void populateVoicemail(@NonNull Context context) { DialerExecutorComponent.get(context) .dialerExecutorFactory() .createNonUiTaskBuilder(new PopulateVoicemailWorker()) @@ -98,7 +61,8 @@ final class SimulatorMainMenu { .executeSerial(new PopulateDatabaseWorkerInput(context, false)); } - private static void populateVoicemailFast(@NonNull Context context) { + /** Populates voicemail database with only few predefined voicemail entries. */ + public static void populateVoicemailFast(@NonNull Context context) { DialerExecutorComponent.get(context) .dialerExecutorFactory() .createNonUiTaskBuilder(new PopulateVoicemailWorker()) @@ -106,17 +70,8 @@ final class SimulatorMainMenu { .executeSerial(new PopulateDatabaseWorkerInput(context, true)); } - private static class PopulateVoicemailWorker - implements Worker<PopulateDatabaseWorkerInput, Void> { - @Nullable - @Override - public Void doInBackground(PopulateDatabaseWorkerInput input) { - VoicemailPopulator.populateVoicemail(input.context, input.fastMode); - return null; - } - } - - private static void fastPopulateDatabase(@NonNull Context context) { + /** Populates contacts database with only few predefined contacts entries. */ + public static void fastPopulateDatabase(@NonNull Context context) { DialerExecutorComponent.get(context) .dialerExecutorFactory() .createNonUiTaskBuilder(new PopulateDatabaseWorker()) @@ -124,7 +79,8 @@ final class SimulatorMainMenu { .executeSerial(new PopulateDatabaseWorkerInput(context, true)); } - private static void cleanDatabase(@NonNull Context context) { + /** Clean contacts database. */ + public static void cleanDatabase(@NonNull Context context) { DialerExecutorComponent.get(context) .dialerExecutorFactory() .createNonUiTaskBuilder(new CleanDatabaseWorker()) @@ -132,7 +88,8 @@ final class SimulatorMainMenu { .executeSerial(context); } - private static void clearPreferredSim(Context context) { + /** Clear preference over sim. */ + public static void clearPreferredSim(Context context) { DialerExecutorComponent.get(context) .dialerExecutorFactory() .createNonUiTaskBuilder(new ClearPreferredSimWorker()) @@ -140,12 +97,13 @@ final class SimulatorMainMenu { .executeSerial(context); } - private static void syncVoicemail(@NonNull Context context) { + /** Sync voicemail by sending intents to system. */ + public static void syncVoicemail(@NonNull Context context) { Intent intent = new Intent(VoicemailContract.ACTION_SYNC_VOICEMAIL); context.sendBroadcast(intent); } - private static void sharePersistentLog(@NonNull Context context) { + public static void sharePersistentLog(@NonNull Context context) { DialerExecutorComponent.get(context) .dialerExecutorFactory() .createNonUiTaskBuilder(new ShareLogWorker()) @@ -162,7 +120,37 @@ final class SimulatorMainMenu { .executeSerial(null); } - private SimulatorMainMenu() {} + public static void addVoicemailNotifications(@NonNull Context context, int notificationNum) { + LogUtil.enterBlock("SimulatorNotifications.addVoicemailNotifications"); + List<ContentValues> voicemails = new ArrayList<>(); + for (int i = notificationNum; i > 0; i--) { + VoicemailPopulator.Voicemail voicemail = + VoicemailPopulator.Voicemail.builder() + .setPhoneNumber(String.format(Locale.ENGLISH, "+%d", i)) + .setTranscription(String.format(Locale.ENGLISH, "Short transcript %d", i)) + .setDurationSeconds(60) + .setIsRead(false) + .setPhoneAccountComponentName("") + .setTimeMillis(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(i)) + .build(); + voicemails.add(voicemail.getAsContentValues(context)); + } + context + .getContentResolver() + .bulkInsert( + Voicemails.buildSourceUri(context.getPackageName()), + voicemails.toArray(new ContentValues[voicemails.size()])); + } + + private static class PopulateVoicemailWorker + implements Worker<PopulateDatabaseWorkerInput, Void> { + @Nullable + @Override + public Void doInBackground(PopulateDatabaseWorkerInput input) { + VoicemailPopulator.populateVoicemail(input.context, input.fastMode); + return null; + } + } private static class PopulateDatabaseWorker implements Worker<PopulateDatabaseWorkerInput, Void> { @Nullable diff --git a/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java b/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java index 0bb56f1f9..c7c92e7b9 100644 --- a/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java +++ b/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java @@ -23,8 +23,6 @@ import android.support.annotation.Nullable; import android.telecom.Connection; import android.telecom.DisconnectCause; import android.telecom.TelecomManager; -import android.telecom.VideoProfile; -import android.view.ActionProvider; import android.widget.Toast; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; @@ -32,36 +30,14 @@ import com.android.dialer.common.concurrent.ThreadUtil; import com.android.dialer.simulator.Simulator.Event; /** Entry point in the simulator to create video calls. */ -final class SimulatorVideoCall +public final class SimulatorVideoCall implements SimulatorConnectionService.Listener, SimulatorConnection.Listener { @NonNull private final Context context; private final int initialVideoCapability; private final int initialVideoState; @Nullable private String connectionTag; - static ActionProvider getActionProvider(@NonNull Context context) { - return new SimulatorSubMenu(context) - .addItem( - "Incoming one way", - () -> - new SimulatorVideoCall(context, VideoProfile.STATE_RX_ENABLED).addNewIncomingCall()) - .addItem( - "Incoming two way", - () -> - new SimulatorVideoCall(context, VideoProfile.STATE_BIDIRECTIONAL) - .addNewIncomingCall()) - .addItem( - "Outgoing one way", - () -> - new SimulatorVideoCall(context, VideoProfile.STATE_TX_ENABLED).addNewOutgoingCall()) - .addItem( - "Outgoing two way", - () -> - new SimulatorVideoCall(context, VideoProfile.STATE_BIDIRECTIONAL) - .addNewOutgoingCall()); - } - - private SimulatorVideoCall(@NonNull Context context, int initialVideoState) { + public SimulatorVideoCall(@NonNull Context context, int initialVideoState) { this.context = Assert.isNotNull(context); this.initialVideoCapability = Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL @@ -70,7 +46,7 @@ final class SimulatorVideoCall SimulatorConnectionService.addListener(this); } - private void addNewIncomingCall() { + public void addNewIncomingCall() { if (!isVideoAccountEnabled()) { showVideoAccountSettings(); return; @@ -81,7 +57,7 @@ final class SimulatorVideoCall context, callerId, SimulatorSimCallManager.CALL_TYPE_VIDEO); } - private void addNewOutgoingCall() { + public void addNewOutgoingCall() { if (!isVideoAccountEnabled()) { showVideoAccountSettings(); return; diff --git a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java index e59cddd51..a9f332e4a 100644 --- a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java +++ b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java @@ -24,7 +24,6 @@ import android.support.v7.app.AppCompatActivity; import android.telecom.Connection; import android.telecom.Connection.RttModifyStatus; import android.telecom.DisconnectCause; -import android.view.ActionProvider; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.DialerExecutorComponent; @@ -37,58 +36,13 @@ import com.android.dialer.simulator.SimulatorComponent; import com.android.dialer.simulator.SimulatorEnrichedCall; /** Entry point in the simulator to create voice calls. */ -final class SimulatorVoiceCall +public final class SimulatorVoiceCall implements SimulatorConnectionService.Listener, SimulatorConnection.Listener { @NonNull private final Context context; @Nullable private String connectionTag; private final SimulatorEnrichedCall simulatorEnrichedCall; - static ActionProvider getActionProvider(@NonNull AppCompatActivity activity) { - return new SimulatorSubMenu(activity.getApplicationContext()) - .addItem( - "Incoming call", - () -> new SimulatorVoiceCall(activity.getApplicationContext()).addNewIncomingCall()) - .addItem( - "Outgoing call", - () -> new SimulatorVoiceCall(activity.getApplicationContext()).addNewOutgoingCall()) - .addItem( - "Customized incoming call", - () -> - new SimulatorVoiceCall(activity.getApplicationContext()) - .addNewIncomingCall(activity)) - .addItem( - "Customized outgoing call", - () -> - new SimulatorVoiceCall(activity.getApplicationContext()) - .addNewOutgoingCall(activity)) - .addItem( - "Incoming enriched call", - () -> new SimulatorVoiceCall(activity.getApplicationContext()).incomingEnrichedCall()) - .addItem( - "Outgoing enriched call", - () -> new SimulatorVoiceCall(activity.getApplicationContext()).outgoingEnrichedCall()) - .addItem( - "Spam incoming call", - () -> new SimulatorVoiceCall(activity.getApplicationContext()).addSpamIncomingCall()) - .addItem( - "Emergency call back", - () -> - new SimulatorVoiceCall(activity.getApplicationContext()).addNewEmergencyCallBack()) - .addItem( - "GSM conference", - () -> - new SimulatorConferenceCreator( - activity.getApplicationContext(), Simulator.CONFERENCE_TYPE_GSM) - .start(5)) - .addItem( - "VoLTE conference", - () -> - new SimulatorConferenceCreator( - activity.getApplicationContext(), Simulator.CONFERENCE_TYPE_VOLTE) - .start(5)); - } - - private SimulatorVoiceCall(@NonNull Context context) { + public SimulatorVoiceCall(@NonNull Context context) { this.context = Assert.isNotNull(context); simulatorEnrichedCall = SimulatorComponent.get(context).getSimulatorEnrichedCall(); SimulatorConnectionService.addListener(this); @@ -96,7 +50,7 @@ final class SimulatorVoiceCall new SimulatorConferenceCreator(context, Simulator.CONFERENCE_TYPE_GSM)); } - private void incomingEnrichedCall() { + public void incomingEnrichedCall() { simulatorEnrichedCall .setupIncomingEnrichedCall(Simulator.ENRICHED_CALL_INCOMING_NUMBER) .addListener( @@ -113,7 +67,7 @@ final class SimulatorVoiceCall DialerExecutorComponent.get(context).uiExecutor()); } - private void outgoingEnrichedCall() { + public void outgoingEnrichedCall() { getEnrichedCallManager().registerStateChangedListener(simulatorEnrichedCall); simulatorEnrichedCall .setupOutgoingEnrichedCall(Simulator.ENRICHED_CALL_OUTGOING_NUMBER) @@ -131,14 +85,14 @@ final class SimulatorVoiceCall DialerExecutorComponent.get(context).uiExecutor()); } - private void addNewIncomingCall() { + public void addNewIncomingCall() { String callerId = "+44 (0) 20 7031 3000" /* Google London office */; connectionTag = SimulatorSimCallManager.addNewIncomingCall( context, callerId, SimulatorSimCallManager.CALL_TYPE_VOICE); } - private void addNewIncomingCall(AppCompatActivity activity) { + public void addNewIncomingCall(AppCompatActivity activity) { SimulatorDialogFragment.newInstance( (callerId, callerIdPresentation) -> { Bundle extras = new Bundle(); @@ -150,14 +104,14 @@ final class SimulatorVoiceCall .show(activity.getSupportFragmentManager(), "SimulatorDialog"); } - private void addNewOutgoingCall() { + public void addNewOutgoingCall() { String callerId = "+55-31-2128-6800"; // Brazil office. connectionTag = SimulatorSimCallManager.addNewOutgoingCall( context, callerId, SimulatorSimCallManager.CALL_TYPE_VOICE); } - private void addNewOutgoingCall(AppCompatActivity activity) { + public void addNewOutgoingCall(AppCompatActivity activity) { SimulatorDialogFragment.newInstance( (callerId, callerIdPresentation) -> { Bundle extras = new Bundle(); @@ -169,14 +123,14 @@ final class SimulatorVoiceCall .show(activity.getSupportFragmentManager(), "SimulatorDialog"); } - private void addSpamIncomingCall() { + public void addSpamIncomingCall() { String callerId = "+1-661-778-3020"; /* Blacklisted custom spam number */ connectionTag = SimulatorSimCallManager.addNewIncomingCall( context, callerId, SimulatorSimCallManager.CALL_TYPE_VOICE); } - private void addNewEmergencyCallBack() { + public void addNewEmergencyCallBack() { String callerId = "911"; connectionTag = SimulatorSimCallManager.addNewIncomingCall( diff --git a/java/com/android/dialer/simulator/portal/SimulatorMainPortal.java b/java/com/android/dialer/simulator/portal/SimulatorMainPortal.java new file mode 100644 index 000000000..fdec2a540 --- /dev/null +++ b/java/com/android/dialer/simulator/portal/SimulatorMainPortal.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2018 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.simulator.portal; + +import android.content.Context; +import android.support.v7.app.AppCompatActivity; +import android.telecom.VideoProfile; +import android.view.ActionProvider; +import com.android.dialer.enrichedcall.simulator.EnrichedCallSimulatorActivity; +import com.android.dialer.simulator.Simulator; +import com.android.dialer.simulator.SimulatorComponent; +import com.android.dialer.simulator.impl.SimulatorConferenceCreator; +import com.android.dialer.simulator.impl.SimulatorMissedCallCreator; +import com.android.dialer.simulator.impl.SimulatorRttCall; +import com.android.dialer.simulator.impl.SimulatorSimCallManager; +import com.android.dialer.simulator.impl.SimulatorUtils; +import com.android.dialer.simulator.impl.SimulatorVideoCall; +import com.android.dialer.simulator.impl.SimulatorVoiceCall; +import com.google.common.collect.ImmutableMap; + +/** Implements the top level simulator menu. */ +public final class SimulatorMainPortal { + + private final Context context; + private final AppCompatActivity activity; + private SimulatorPortalEntryGroup simulatorMainPortal; + + public SimulatorMainPortal(AppCompatActivity activity) { + this.activity = activity; + this.context = activity.getApplicationContext(); + buildMainPortal(); + } + + private void buildMainPortal() { + this.simulatorMainPortal = + SimulatorPortalEntryGroup.builder() + .setMethods( + ImmutableMap.<String, Runnable>builder() + .put("Populate database", () -> SimulatorUtils.populateDatabase(context)) + .put("Populate voicemail", () -> SimulatorUtils.populateVoicemail(context)) + .put( + "Fast Populate database", + () -> SimulatorUtils.fastPopulateDatabase(context)) + .put( + "Fast populate voicemail database", + () -> SimulatorUtils.populateVoicemailFast(context)) + .put("Clean database", () -> SimulatorUtils.cleanDatabase(context)) + .put("clear preferred SIM", () -> SimulatorUtils.clearPreferredSim(context)) + .put("Sync voicemail", () -> SimulatorUtils.syncVoicemail(context)) + .put("Share persistent log", () -> SimulatorUtils.sharePersistentLog(context)) + .put( + "Enriched call simulator", + () -> + context.startActivity(EnrichedCallSimulatorActivity.newIntent(context))) + .put( + "Enable simulator mode", + () -> { + SimulatorComponent.get(context).getSimulator().enableSimulatorMode(); + SimulatorSimCallManager.register(context); + }) + .put( + "Disable simulator mode", + () -> { + SimulatorComponent.get(context).getSimulator().disableSimulatorMode(); + SimulatorSimCallManager.unregister(context); + }) + .build()) + .setSubPortals( + ImmutableMap.of( + "VoiceCall", + buildSimulatorVoiceCallPortal(), + "VideoCall", + buildSimulatorVideoCallPortal(), + "RttCall", + buildSimulatorRttCallPortal(), + "Notifications", + buildSimulatorNotificationsPortal())) + .build(); + } + + public SimulatorPortalEntryGroup buildSimulatorVoiceCallPortal() { + return SimulatorPortalEntryGroup.builder() + .setMethods( + ImmutableMap.<String, Runnable>builder() + .put("Incoming call", () -> new SimulatorVoiceCall(context).addNewIncomingCall()) + .put("Outgoing call", () -> new SimulatorVoiceCall(context).addNewOutgoingCall()) + .put( + "Customized incoming call", + () -> new SimulatorVoiceCall(context).addNewIncomingCall(activity)) + .put( + "Customized outgoing call", + () -> new SimulatorVoiceCall(context).addNewOutgoingCall(activity)) + .put( + "Incoming enriched call", + () -> new SimulatorVoiceCall(context).incomingEnrichedCall()) + .put( + "Outgoing enriched call", + () -> new SimulatorVoiceCall(context).outgoingEnrichedCall()) + .put( + "Spam incoming call", + () -> new SimulatorVoiceCall(context).addSpamIncomingCall()) + .put( + "Emergency call back", + () -> new SimulatorVoiceCall(context).addNewEmergencyCallBack()) + .put( + "GSM conference", + () -> + new SimulatorConferenceCreator(context, Simulator.CONFERENCE_TYPE_GSM) + .start(5)) + .put( + "VoLTE conference", + () -> + new SimulatorConferenceCreator(context, Simulator.CONFERENCE_TYPE_VOLTE) + .start(5)) + .build()) + .build(); + } + + private SimulatorPortalEntryGroup buildSimulatorVideoCallPortal() { + return SimulatorPortalEntryGroup.builder() + .setMethods( + ImmutableMap.<String, Runnable>builder() + .put( + "Incoming one way", + () -> + new SimulatorVideoCall(context, VideoProfile.STATE_RX_ENABLED) + .addNewIncomingCall()) + .put( + "Incoming two way", + () -> + new SimulatorVideoCall(context, VideoProfile.STATE_BIDIRECTIONAL) + .addNewIncomingCall()) + .put( + "Outgoing one way", + () -> + new SimulatorVideoCall(context, VideoProfile.STATE_TX_ENABLED) + .addNewOutgoingCall()) + .put( + "Outgoing two way", + () -> + new SimulatorVideoCall(context, VideoProfile.STATE_BIDIRECTIONAL) + .addNewOutgoingCall()) + .build()) + .build(); + } + + private SimulatorPortalEntryGroup buildSimulatorRttCallPortal() { + return SimulatorPortalEntryGroup.builder() + .setMethods( + ImmutableMap.<String, Runnable>builder() + .put("Incoming call", () -> new SimulatorRttCall(context).addNewIncomingCall(false)) + .put("Outgoing call", () -> new SimulatorRttCall(context).addNewOutgoingCall()) + .put("Emergency call", () -> new SimulatorRttCall(context).addNewEmergencyCall()) + .build()) + .build(); + } + + private SimulatorPortalEntryGroup buildSimulatorNotificationsPortal() { + return SimulatorPortalEntryGroup.builder() + .setMethods( + ImmutableMap.<String, Runnable>builder() + .put( + "Missed calls", + () -> + new SimulatorMissedCallCreator(context) + .start(SimulatorUtils.NOTIFICATION_COUNT)) + .put( + "Missed calls (few)", + () -> + new SimulatorMissedCallCreator(context) + .start(SimulatorUtils.NOTIFICATION_COUNT_FEW)) + .put( + "Voicemails", + () -> + SimulatorUtils.addVoicemailNotifications( + context, SimulatorUtils.NOTIFICATION_COUNT)) + .build()) + .build(); + } + + public ActionProvider getActionProvider() { + return new SimulatorMenu(context, simulatorMainPortal); + } +} diff --git a/java/com/android/dialer/simulator/portal/SimulatorMenu.java b/java/com/android/dialer/simulator/portal/SimulatorMenu.java new file mode 100644 index 000000000..01fd4aa0e --- /dev/null +++ b/java/com/android/dialer/simulator/portal/SimulatorMenu.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2018 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.simulator.portal; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.view.ActionProvider; +import android.view.MenuItem; +import android.view.SubMenu; +import android.view.View; +import com.android.dialer.common.Assert; +import java.util.Map.Entry; + +/** Makes option menu for simulator. */ +public final class SimulatorMenu extends ActionProvider { + + SimulatorPortalEntryGroup portal; + + Context context; + + public SimulatorMenu(@NonNull Context context, SimulatorPortalEntryGroup portal) { + super(Assert.isNotNull(context)); + this.context = context; + this.portal = portal; + } + + @Override + public View onCreateActionView() { + return null; + } + + @Override + public View onCreateActionView(MenuItem forItem) { + return null; + } + + @Override + public boolean hasSubMenu() { + return true; + } + + @Override + public void onPrepareSubMenu(SubMenu subMenu) { + super.onPrepareSubMenu(subMenu); + subMenu.clear(); + + for (Entry<String, SimulatorPortalEntryGroup> subPortal : portal.subPortals().entrySet()) { + subMenu + .add(subPortal.getKey()) + .setActionProvider(new SimulatorMenu(context, subPortal.getValue())); + } + for (Entry<String, Runnable> method : portal.methods().entrySet()) { + subMenu + .add(method.getKey()) + .setOnMenuItemClickListener( + (i) -> { + method.getValue().run(); + return true; + }); + } + } +} diff --git a/java/com/android/dialer/simulator/portal/SimulatorPortalEntryGroup.java b/java/com/android/dialer/simulator/portal/SimulatorPortalEntryGroup.java new file mode 100644 index 000000000..30a248cb1 --- /dev/null +++ b/java/com/android/dialer/simulator/portal/SimulatorPortalEntryGroup.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 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.simulator.portal; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableMap; +import java.util.Collections; +import java.util.Map; + +/** Represents a portal that receives requests from either UI or IPC. */ +@AutoValue +public abstract class SimulatorPortalEntryGroup { + abstract ImmutableMap<String, Runnable> methods(); + + abstract ImmutableMap<String, SimulatorPortalEntryGroup> subPortals(); + + static Builder builder() { + return new AutoValue_SimulatorPortalEntryGroup.Builder() + .setMethods(Collections.emptyMap()) + .setSubPortals(Collections.emptyMap()); + } + + @AutoValue.Builder + abstract static class Builder { + abstract Builder setMethods(Map<String, Runnable> value); + + abstract Builder setSubPortals(Map<String, SimulatorPortalEntryGroup> value); + + abstract SimulatorPortalEntryGroup build(); + } +} diff --git a/java/com/android/dialer/spam/Spam.java b/java/com/android/dialer/spam/Spam.java index 181a55dea..0229782bf 100644 --- a/java/com/android/dialer/spam/Spam.java +++ b/java/com/android/dialer/spam/Spam.java @@ -18,7 +18,6 @@ package com.android.dialer.spam; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.android.dialer.DialerPhoneNumber; import com.android.dialer.logging.ContactLookupResult; @@ -75,30 +74,6 @@ public interface Spam { ListenableFuture<Void> updateSpamListDownload(boolean isEnabledByUser); /** - * @param number The number to check if the number is in the user's white list (non spam list) - * @param countryIso The country ISO of the call. - * @param listener The callback to be invoked after {@code Info} is fetched. - */ - void checkUserMarkedNonSpamStatus( - String number, @Nullable String countryIso, @NonNull Listener listener); - - /** - * @param number The number to check if it is in user's spam list - * @param countryIso The country ISO of the call. - * @param listener The callback to be invoked after {@code Info} is fetched. - */ - void checkUserMarkedSpamStatus( - String number, @Nullable String countryIso, @NonNull Listener listener); - - /** - * @param number The number to check if it is in the global spam list - * @param countryIso The country ISO of the call. - * @param listener The callback to be invoked after {@code Info} is fetched. - */ - void checkGlobalSpamListStatus( - String number, @Nullable String countryIso, @NonNull Listener listener); - - /** * Synchronously checks if the given number is suspected of being a spamer. * * @param number The phone number of the call. @@ -191,11 +166,4 @@ public interface Spam { int callType, ReportingLocation.Type from, ContactSource.Type contactSourceType); - - /** Callback to be invoked when data is fetched. */ - interface Listener { - - /** Called when data is fetched. */ - void onComplete(boolean isSpam); - } } diff --git a/java/com/android/dialer/spam/status/SimpleSpamStatus.java b/java/com/android/dialer/spam/status/SimpleSpamStatus.java index ff080ed1d..5f45c1a4f 100644 --- a/java/com/android/dialer/spam/status/SimpleSpamStatus.java +++ b/java/com/android/dialer/spam/status/SimpleSpamStatus.java @@ -26,7 +26,11 @@ public abstract class SimpleSpamStatus implements SpamStatus { /** Returns a SimpleSpamStatus with the given boolean and timestamp. */ public static SimpleSpamStatus create(boolean isSpam, @Nullable Long timestampMillis) { - return new AutoValue_SimpleSpamStatus(isSpam, Optional.fromNullable(timestampMillis)); + return builder() + .setSpam(isSpam) + .setTimestampMillis(timestampMillis) + .setSpamMetadata(SpamMetadata.empty()) + .build(); } /** Returns a SimpleSpamStatus that's not marked as spam and has no timestamp. */ @@ -34,9 +38,23 @@ public abstract class SimpleSpamStatus implements SpamStatus { return create(false, null); } - /** Returns an empty {@link SpamMetadata}. */ - @Override - public final SpamMetadata getSpamMetadata() { - return SpamMetadata.empty(); + public static Builder builder() { + return new AutoValue_SimpleSpamStatus.Builder(); + } + + /** Creates instances of SimpleSpamStatus. */ + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder setSpam(boolean isSpam); + + abstract Builder setTimestampMillis(Optional<Long> timestamp); + + public Builder setTimestampMillis(@Nullable Long timestampMillis) { + return setTimestampMillis(Optional.fromNullable(timestampMillis)); + } + + public abstract Builder setSpamMetadata(SpamMetadata spamMetadata); + + public abstract SimpleSpamStatus build(); } } diff --git a/java/com/android/dialer/spam/SpamSettingsStub.java b/java/com/android/dialer/spam/stub/SpamSettingsStub.java index 905daa45c..194d18451 100644 --- a/java/com/android/dialer/spam/SpamSettingsStub.java +++ b/java/com/android/dialer/spam/stub/SpamSettingsStub.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.android.dialer.spam; +package com.android.dialer.spam.stub; import android.content.Context; import android.content.Intent; +import com.android.dialer.spam.SpamSettings; import javax.inject.Inject; /** Default implementation of SpamSettings. */ diff --git a/java/com/android/dialer/spam/SpamStub.java b/java/com/android/dialer/spam/stub/SpamStub.java index 2789c01e7..5eeed4571 100644 --- a/java/com/android/dialer/spam/SpamStub.java +++ b/java/com/android/dialer/spam/stub/SpamStub.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.dialer.spam; +package com.android.dialer.spam.stub; import android.support.annotation.Nullable; import com.android.dialer.DialerPhoneNumber; @@ -22,6 +22,7 @@ import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; import com.android.dialer.logging.ContactLookupResult; import com.android.dialer.logging.ContactSource; import com.android.dialer.logging.ReportingLocation; +import com.android.dialer.spam.Spam; import com.android.dialer.spam.status.SimpleSpamStatus; import com.android.dialer.spam.status.SpamStatus; import com.google.common.collect.ImmutableMap; @@ -73,21 +74,6 @@ public class SpamStub implements Spam { } @Override - public void checkUserMarkedNonSpamStatus(String number, String countryIso, Listener listener) { - listener.onComplete(false); - } - - @Override - public void checkUserMarkedSpamStatus(String number, String countryIso, Listener listener) { - listener.onComplete(false); - } - - @Override - public void checkGlobalSpamListStatus(String number, String countryIso, Listener listener) { - listener.onComplete(false); - } - - @Override public boolean checkSpamStatusSynchronous(String number, String countryIso) { return false; } diff --git a/java/com/android/dialer/spam/StubSpamModule.java b/java/com/android/dialer/spam/stub/StubSpamModule.java index b60967475..e6b4622df 100644 --- a/java/com/android/dialer/spam/StubSpamModule.java +++ b/java/com/android/dialer/spam/stub/StubSpamModule.java @@ -14,10 +14,12 @@ * limitations under the License. */ -package com.android.dialer.spam; +package com.android.dialer.spam.stub; import com.android.dialer.inject.DialerVariant; import com.android.dialer.inject.InstallIn; +import com.android.dialer.spam.Spam; +import com.android.dialer.spam.SpamSettings; import dagger.Binds; import dagger.Module; diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java index fac9a13d2..d9593c211 100644 --- a/java/com/android/dialer/speeddial/SpeedDialFragment.java +++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java @@ -16,12 +16,16 @@ package com.android.dialer.speeddial; +import android.Manifest; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Contacts; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; @@ -35,6 +39,7 @@ import android.view.View; import android.view.ViewGroup; import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; +import com.android.dialer.common.Assert; import com.android.dialer.common.FragmentUtils; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.DefaultFutureCallback; @@ -59,9 +64,13 @@ import com.android.dialer.speeddial.draghelper.SpeedDialLayoutManager; import com.android.dialer.speeddial.loader.SpeedDialUiItem; import com.android.dialer.speeddial.loader.UiItemLoaderComponent; 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 com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.Futures; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -76,6 +85,20 @@ import java.util.List; */ public class SpeedDialFragment extends Fragment { + private static final int READ_CONTACTS_PERMISSION_REQUEST_CODE = 1; + + /** + * 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) { + loadContacts(); + } + }; + private final SpeedDialHeaderListener headerListener = new SpeedDialFragmentHeaderListener(); private final SpeedDialSuggestedListener suggestedListener = new SpeedDialSuggestedListener(); @@ -83,6 +106,8 @@ public class SpeedDialFragment extends Fragment { private SupportUiListener<ImmutableList<SpeedDialUiItem>> speedDialLoaderListener; private SpeedDialFavoritesListener favoritesListener; + private EmptyContentView emptyContentView; + /** * We update the UI every time the fragment is resumed. This boolean suppresses that functionality * once per onResume call. @@ -99,6 +124,12 @@ public class SpeedDialFragment extends Fragment { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { LogUtil.enterBlock("SpeedDialFragment.onCreateView"); View rootLayout = inflater.inflate(R.layout.fragment_speed_dial, container, false); + emptyContentView = rootLayout.findViewById(R.id.speed_dial_empty_content_view); + emptyContentView.setActionLabel(R.string.speed_dial_turn_on_contacts_permission); + emptyContentView.setDescription(R.string.speed_dial_contacts_permission_description); + emptyContentView.setImage(R.drawable.empty_speed_dial); + emptyContentView.setActionClickedListener( + new SpeedDialEmptyContentViewClickedListener(getContext(), this)); speedDialLoaderListener = DialerExecutorComponent.get(getContext()) @@ -132,11 +163,69 @@ public class SpeedDialFragment extends Fragment { @Override public void onResume() { super.onResume(); + loadContacts(); + } + + @Override + public void onPause() { + super.onPause(); + favoritesListener.hideMenu(); + suggestedListener.onPause(); + } + + @Override + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); + if (hidden) { + onHidden(); + } else { + loadContacts(); + } + } + + private void onHidden() { + if (!PermissionsUtil.hasContactsReadPermissions(getContext())) { + return; + } + + Futures.addCallback( + DialerExecutorComponent.get(getContext()) + .backgroundExecutor() + .submit( + () -> { + UiItemLoaderComponent.get(getContext()) + .speedDialUiItemMutator() + .updatePinnedPosition(adapter.getSpeedDialUiItems()); + return null; + }), + new DefaultFutureCallback<>(), + DialerExecutorComponent.get(getContext()).backgroundExecutor()); + } + + @Override + public void onRequestPermissionsResult( + int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (requestCode == READ_CONTACTS_PERMISSION_REQUEST_CODE + && grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + PermissionsUtil.notifyPermissionGranted(getContext(), Manifest.permission.READ_CONTACTS); + loadContacts(); + } + } + + private void loadContacts() { if (!updateSpeedDialItemsOnResume) { updateSpeedDialItemsOnResume = true; return; } + if (!PermissionsUtil.hasContactsReadPermissions(getContext())) { + emptyContentView.setVisibility(View.VISIBLE); + return; + } else { + emptyContentView.setVisibility(View.GONE); + } + speedDialLoaderListener.listen( getContext(), UiItemLoaderComponent.get(getContext()).speedDialUiItemMutator().loadSpeedDialUiItems(), @@ -179,22 +268,17 @@ public class SpeedDialFragment extends Fragment { } @Override - public void onPause() { - super.onPause(); - favoritesListener.hideMenu(); - Futures.addCallback( - DialerExecutorComponent.get(getContext()) - .backgroundExecutor() - .submit( - () -> { - UiItemLoaderComponent.get(getContext()) - .speedDialUiItemMutator() - .updatePinnedPosition(adapter.getSpeedDialUiItems()); - return null; - }), - new DefaultFutureCallback<>(), - DialerExecutorComponent.get(getContext()).backgroundExecutor()); - suggestedListener.onPause(); + public void onStart() { + super.onStart(); + PermissionsUtil.registerPermissionReceiver( + getActivity(), readContactsPermissionGrantedReceiver, Manifest.permission.READ_CONTACTS); + } + + @Override + public void onStop() { + super.onStop(); + PermissionsUtil.unregisterPermissionReceiver( + getContext(), readContactsPermissionGrantedReceiver); } private class SpeedDialFragmentHeaderListener implements SpeedDialHeaderListener { @@ -455,6 +539,30 @@ public class SpeedDialFragment extends Fragment { } } + private static final class SpeedDialEmptyContentViewClickedListener + implements OnEmptyViewActionButtonClickedListener { + + private final Context context; + private final Fragment fragment; + + private SpeedDialEmptyContentViewClickedListener(Context context, Fragment fragment) { + this.context = context; + this.fragment = fragment; + } + + @Override + public void onEmptyViewActionButtonClicked() { + String[] deniedPermissions = + PermissionsUtil.getPermissionsCurrentlyDenied( + context, PermissionsUtil.allContactsGroupPermissionsUsedInDialer); + Assert.checkArgument(deniedPermissions.length > 0); + LogUtil.i( + "OldSpeedDialFragment.onEmptyViewActionButtonClicked", + "Requesting permissions: " + Arrays.toString(deniedPermissions)); + fragment.requestPermissions(deniedPermissions, READ_CONTACTS_PERMISSION_REQUEST_CODE); + } + } + /** Listener for when a SpeedDialUiItem is updated. */ private class UpdateSpeedDialAdapterListener { diff --git a/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java b/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java index 1416a203d..211af86ad 100644 --- a/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java +++ b/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java @@ -125,7 +125,7 @@ public final class SpeedDialEntryDatabaseHelper extends SQLiteOpenHelper Channel.builder() .setNumber(number) .setPhoneType(cursor.getInt(POSITION_PHONE_TYPE)) - .setLabel(cursor.getString(POSITION_PHONE_LABEL)) + .setLabel(Optional.of(cursor.getString(POSITION_PHONE_LABEL)).or("")) .setTechnology(cursor.getInt(POSITION_PHONE_TECHNOLOGY)) .build(); } diff --git a/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml b/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml index 9a42377be..1e35091c9 100644 --- a/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml +++ b/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml @@ -26,5 +26,12 @@ android:clipToPadding="false" android:background="@color/background_dialer_light" android:paddingBottom="@dimen/floating_action_button_list_bottom_padding"/> + + <com.android.dialer.widget.EmptyContentView + android:id="@+id/speed_dial_empty_content_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:visibility="gone"/> </FrameLayout> diff --git a/java/com/android/dialer/speeddial/res/values/strings.xml b/java/com/android/dialer/speeddial/res/values/strings.xml index 0053074b2..7f11119c7 100644 --- a/java/com/android/dialer/speeddial/res/values/strings.xml +++ b/java/com/android/dialer/speeddial/res/values/strings.xml @@ -59,4 +59,10 @@ <!-- Text shown to the user in a button to prompt them to mark a contact as a favorite contact [CHAR LIMIT=30]. --> <string name="suggested_contact_bottom_sheet_add_favorite_option">Add favorite</string> + + <!-- Shown as a prompt to turn on the contacts permission to enable speed dial [CHAR LIMIT=NONE]--> + <string name="speed_dial_contacts_permission_description">To enable speed dial, turn on the Contacts permission.</string> + + <!-- The label of the button used to turn on a single permission [CHAR LIMIT=30]--> + <string name="speed_dial_turn_on_contacts_permission">Turn on</string> </resources>
\ No newline at end of file diff --git a/java/com/android/dialer/theme/res/drawable-hdpi/empty_speed_dial.png b/java/com/android/dialer/theme/res/drawable-hdpi/empty_speed_dial.png Binary files differnew file mode 100644 index 000000000..5a1829599 --- /dev/null +++ b/java/com/android/dialer/theme/res/drawable-hdpi/empty_speed_dial.png diff --git a/java/com/android/dialer/theme/res/drawable-mdpi/empty_speed_dial.png b/java/com/android/dialer/theme/res/drawable-mdpi/empty_speed_dial.png Binary files differnew file mode 100644 index 000000000..3c95eeb33 --- /dev/null +++ b/java/com/android/dialer/theme/res/drawable-mdpi/empty_speed_dial.png diff --git a/java/com/android/dialer/theme/res/drawable-xhdpi/empty_speed_dial.png b/java/com/android/dialer/theme/res/drawable-xhdpi/empty_speed_dial.png Binary files differnew file mode 100644 index 000000000..9335011fe --- /dev/null +++ b/java/com/android/dialer/theme/res/drawable-xhdpi/empty_speed_dial.png diff --git a/java/com/android/dialer/theme/res/drawable-xxhdpi/empty_speed_dial.png b/java/com/android/dialer/theme/res/drawable-xxhdpi/empty_speed_dial.png Binary files differnew file mode 100644 index 000000000..04ab7b4dc --- /dev/null +++ b/java/com/android/dialer/theme/res/drawable-xxhdpi/empty_speed_dial.png diff --git a/java/com/android/dialer/widget/res/drawable-hdpi/empty_contacts.png b/java/com/android/dialer/widget/res/drawable-hdpi/empty_contacts.png Binary files differindex d3c0378f5..628f301b2 100644 --- a/java/com/android/dialer/widget/res/drawable-hdpi/empty_contacts.png +++ b/java/com/android/dialer/widget/res/drawable-hdpi/empty_contacts.png diff --git a/java/com/android/dialer/widget/res/drawable-mdpi/empty_contacts.png b/java/com/android/dialer/widget/res/drawable-mdpi/empty_contacts.png Binary files differindex 2ce7eae37..bb2a13340 100644 --- a/java/com/android/dialer/widget/res/drawable-mdpi/empty_contacts.png +++ b/java/com/android/dialer/widget/res/drawable-mdpi/empty_contacts.png diff --git a/java/com/android/dialer/widget/res/drawable-xhdpi/empty_contacts.png b/java/com/android/dialer/widget/res/drawable-xhdpi/empty_contacts.png Binary files differindex 65b1de333..5edeab210 100644 --- a/java/com/android/dialer/widget/res/drawable-xhdpi/empty_contacts.png +++ b/java/com/android/dialer/widget/res/drawable-xhdpi/empty_contacts.png diff --git a/java/com/android/dialer/widget/res/drawable-xxhdpi/empty_contacts.png b/java/com/android/dialer/widget/res/drawable-xxhdpi/empty_contacts.png Binary files differindex 407d78c9c..7d6c05963 100644 --- a/java/com/android/dialer/widget/res/drawable-xxhdpi/empty_contacts.png +++ b/java/com/android/dialer/widget/res/drawable-xxhdpi/empty_contacts.png diff --git a/java/com/android/dialer/widget/res/drawable-xxxhdpi/empty_contacts.png b/java/com/android/dialer/widget/res/drawable-xxxhdpi/empty_contacts.png Binary files differindex 5893965e9..ad44d2452 100644 --- a/java/com/android/dialer/widget/res/drawable-xxxhdpi/empty_contacts.png +++ b/java/com/android/dialer/widget/res/drawable-xxxhdpi/empty_contacts.png diff --git a/java/com/android/incallui/CallButtonPresenter.java b/java/com/android/incallui/CallButtonPresenter.java index 3fd3ee64b..a8b060daa 100644 --- a/java/com/android/incallui/CallButtonPresenter.java +++ b/java/com/android/incallui/CallButtonPresenter.java @@ -62,13 +62,14 @@ public class CallButtonPresenter Listener, InCallButtonUiDelegate { - private static final String KEY_AUTOMATICALLY_MUTED = "incall_key_automatically_muted"; + private static final String KEY_AUTOMATICALLY_MUTED_BY_ADD_CALL = + "incall_key_automatically_muted_by_add_call"; private static final String KEY_PREVIOUS_MUTE_STATE = "incall_key_previous_mute_state"; private final Context context; private InCallButtonUi inCallButtonUi; private DialerCall call; - private boolean automaticallyMuted = false; + private boolean automaticallyMutedByAddCall = false; private boolean previousMuteState = false; private boolean isInCallButtonUiReady; private PhoneAccountHandle otherAccount; @@ -276,8 +277,14 @@ public class CallButtonPresenter DialerImpression.Type.IN_CALL_ADD_CALL_BUTTON_PRESSED, call.getUniqueCallId(), call.getTimeAddedMs()); + if (automaticallyMutedByAddCall) { + // Since clicking add call button brings user to MainActivity and coming back refreshes mute + // state, add call button should only be clicked once during InCallActivity shows. Otherwise, + // we set previousMuteState wrong. + return; + } // Automatically mute the current call - automaticallyMuted = true; + automaticallyMutedByAddCall = true; previousMuteState = AudioModeProvider.getInstance().getAudioState().isMuted(); // Simulate a click on the mute button muteClicked(true /* checked */, false /* clickedByUser */); @@ -540,25 +547,27 @@ public class CallButtonPresenter @Override public void refreshMuteState() { // Restore the previous mute state - if (automaticallyMuted + if (automaticallyMutedByAddCall && AudioModeProvider.getInstance().getAudioState().isMuted() != previousMuteState) { if (inCallButtonUi == null) { return; } muteClicked(previousMuteState, false /* clickedByUser */); } - automaticallyMuted = false; + automaticallyMutedByAddCall = false; } @Override public void onSaveInstanceState(Bundle outState) { - outState.putBoolean(KEY_AUTOMATICALLY_MUTED, automaticallyMuted); + outState.putBoolean(KEY_AUTOMATICALLY_MUTED_BY_ADD_CALL, automaticallyMutedByAddCall); outState.putBoolean(KEY_PREVIOUS_MUTE_STATE, previousMuteState); } @Override public void onRestoreInstanceState(Bundle savedInstanceState) { - automaticallyMuted = savedInstanceState.getBoolean(KEY_AUTOMATICALLY_MUTED, automaticallyMuted); + automaticallyMutedByAddCall = + savedInstanceState.getBoolean( + KEY_AUTOMATICALLY_MUTED_BY_ADD_CALL, automaticallyMutedByAddCall); previousMuteState = savedInstanceState.getBoolean(KEY_PREVIOUS_MUTE_STATE, previousMuteState); } diff --git a/java/com/android/incallui/answer/impl/AnswerFragment.java b/java/com/android/incallui/answer/impl/AnswerFragment.java index fb1de05bd..d44a5daa2 100644 --- a/java/com/android/incallui/answer/impl/AnswerFragment.java +++ b/java/com/android/incallui/answer/impl/AnswerFragment.java @@ -82,9 +82,11 @@ import com.android.incallui.incalluilock.InCallUiLock; import com.android.incallui.maps.MapsComponent; import com.android.incallui.sessiondata.AvatarPresenter; import com.android.incallui.sessiondata.MultimediaFragment; +import com.android.incallui.speakeasy.SpeakEasyComponent; import com.android.incallui.util.AccessibilityUtil; import com.android.incallui.video.protocol.VideoCallScreen; import com.android.incallui.videotech.utils.VideoUtils; +import com.google.common.base.Optional; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -206,7 +208,7 @@ public class AnswerFragment extends Fragment } }; - @DrawableRes public final int icon; + @DrawableRes public int icon; @StringRes public final int contentDescription; @StringRes public final int accessibilityLabel; @StringRes public final int hintText; @@ -456,6 +458,11 @@ public class AnswerFragment extends Fragment answerAndReleaseButton.setVisibility(View.VISIBLE); answerScreenDelegate.onAnswerAndReleaseButtonEnabled(); } else if (allowSpeakEasy()) { + Optional<Integer> alternativeIcon = SpeakEasyComponent.get(getContext()).speakEasyIcon(); + if (alternativeIcon.isPresent()) { + // TODO(erfanian): Replace enum hack when we have a dedicated button. + SecondaryBehavior.SPEAKEASY.icon = alternativeIcon.get(); + } answerAndReleaseBehavior = SecondaryBehavior.SPEAKEASY; answerAndReleaseBehavior.applyToView(answerAndReleaseButton); answerAndReleaseButton.setVisibility(View.VISIBLE); diff --git a/java/com/android/incallui/call/CallList.java b/java/com/android/incallui/call/CallList.java index 13be252dd..6940f7d6c 100644 --- a/java/com/android/incallui/call/CallList.java +++ b/java/com/android/incallui/call/CallList.java @@ -23,13 +23,11 @@ import android.os.Trace; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; -import android.support.v4.os.BuildCompat; import android.telecom.Call; import android.telecom.DisconnectCause; import android.telecom.PhoneAccount; import android.util.ArrayMap; 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.DialerExecutorComponent; @@ -41,7 +39,6 @@ import com.android.dialer.metrics.Metrics; import com.android.dialer.metrics.MetricsComponent; import com.android.dialer.promotion.RttPromotion; import com.android.dialer.shortcuts.ShortcutUsageReporter; -import com.android.dialer.spam.Spam; import com.android.dialer.spam.SpamComponent; import com.android.dialer.spam.status.SpamStatus; import com.android.dialer.telecom.TelecomCallUtil; @@ -164,20 +161,7 @@ public class CallList implements DialerCallDelegate { call.getState() == DialerCallState.INCOMING || call.getState() == DialerCallState.CALL_WAITING; boolean isSpam = result.isSpam(); - if (isSpam) { - if (!isIncomingCall) { - LogUtil.i( - "CallList.onCallAdded", - "marking spam call as not spam because it's not an incoming call"); - isSpam = false; - } else if (isPotentialEmergencyCallback(context, call)) { - LogUtil.i( - "CallList.onCallAdded", - "marking spam call as not spam because an emergency call was made on this" - + " device recently"); - isSpam = false; - } - } + call.setSpamStatus(result); if (isIncomingCall) { Logger.get(context) @@ -188,7 +172,6 @@ public class CallList implements DialerCallDelegate { call.getUniqueCallId(), call.getTimeAddedMs()); } - call.setSpam(isSpam); onUpdateCall(call); notifyGenericListeners(); } @@ -201,7 +184,6 @@ public class CallList implements DialerCallDelegate { DialerExecutorComponent.get(context).uiExecutor()); Trace.beginSection("updateUserMarkedSpamStatus"); - updateUserMarkedSpamStatus(call, context, number); Trace.endSection(); } Trace.endSection(); @@ -279,60 +261,11 @@ public class CallList implements DialerCallDelegate { impression, incomingCall.getUniqueCallId(), incomingCall.getTimeAddedMs()); } - private static boolean isPotentialEmergencyCallback(Context context, DialerCall call) { - if (BuildCompat.isAtLeastO()) { - return call.isPotentialEmergencyCallback(); - } else { - long timestampMillis = FilteredNumbersUtil.getLastEmergencyCallTimeMillis(context); - return call.isInEmergencyCallbackWindow(timestampMillis); - } - } - @Override public DialerCall getDialerCallFromTelecomCall(Call telecomCall) { return callByTelecomCall.get(telecomCall); } - private void updateUserMarkedSpamStatus( - final DialerCall call, final Context context, String number) { - - SpamComponent.get(context) - .spam() - .checkUserMarkedNonSpamStatus( - number, - call.getCountryIso(), - new Spam.Listener() { - @Override - public void onComplete(boolean isInUserWhiteList) { - call.setIsInUserWhiteList(isInUserWhiteList); - } - }); - - SpamComponent.get(context) - .spam() - .checkGlobalSpamListStatus( - number, - call.getCountryIso(), - new Spam.Listener() { - @Override - public void onComplete(boolean isInGlobalSpamList) { - call.setIsInGlobalSpamList(isInGlobalSpamList); - } - }); - - SpamComponent.get(context) - .spam() - .checkUserMarkedSpamStatus( - number, - call.getCountryIso(), - new Spam.Listener() { - @Override - public void onComplete(boolean isInUserSpamList) { - call.setIsInUserSpamList(isInUserSpamList); - } - }); - } - public void onCallRemoved(Context context, android.telecom.Call telecomCall) { if (callByTelecomCall.containsKey(telecomCall)) { DialerCall call = callByTelecomCall.get(telecomCall); diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java index 431634a0c..da7c54d27 100644 --- a/java/com/android/incallui/call/DialerCall.java +++ b/java/com/android/incallui/call/DialerCall.java @@ -52,6 +52,7 @@ import android.widget.Toast; import com.android.contacts.common.compat.CallCompat; import com.android.dialer.assisteddialing.ConcreteCreator; import com.android.dialer.assisteddialing.TransformationInfo; +import com.android.dialer.blocking.FilteredNumbersUtil; import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentParser; import com.android.dialer.callintent.CallSpecificAppData; @@ -76,6 +77,7 @@ import com.android.dialer.logging.Logger; import com.android.dialer.preferredsim.PreferredAccountRecorder; import com.android.dialer.rtt.RttTranscript; import com.android.dialer.rtt.RttTranscriptUtil; +import com.android.dialer.spam.status.SpamStatus; import com.android.dialer.telecom.TelecomCallUtil; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.theme.R; @@ -91,6 +93,7 @@ import com.android.incallui.videotech.duo.DuoVideoTech; import com.android.incallui.videotech.empty.EmptyVideoTech; import com.android.incallui.videotech.ims.ImsVideoTech; import com.android.incallui.videotech.utils.VideoUtils; +import com.google.common.base.Optional; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.MoreExecutors; import java.io.IOException; @@ -165,14 +168,10 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa private String callSubject; @Nullable private PhoneAccountHandle phoneAccountHandle; @CallHistoryStatus private int callHistoryStatus = CALL_HISTORY_STATUS_UNKNOWN; - private boolean isSpam; - private boolean isBlocked; - - @Nullable private Boolean isInUserSpamList; - @Nullable private Boolean isInUserWhiteList; + @Nullable private SpamStatus spamStatus; + private boolean isBlocked; - @Nullable private Boolean isInGlobalSpamList; private boolean didShowCameraPermission; private boolean didDismissVideoChargesAlertDialog; private PersistableBundle carrierConfig; @@ -820,6 +819,13 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa if (hasProperty(Details.PROPERTY_EMERGENCY_CALLBACK_MODE)) { return true; } + + // Call.EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS is available starting in O + if (VERSION.SDK_INT < VERSION_CODES.O) { + long timestampMillis = FilteredNumbersUtil.getLastEmergencyCallTimeMillis(context); + return isInEmergencyCallbackWindow(timestampMillis); + } + // We want to treat any incoming call that arrives a short time after an outgoing emergency call // as a potential emergency callback. if (getExtras() != null @@ -1270,39 +1276,28 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa didDismissVideoChargesAlertDialog = didDismiss; } - @Nullable - public Boolean isInGlobalSpamList() { - return isInGlobalSpamList; - } - - public void setIsInGlobalSpamList(boolean inSpamList) { - isInGlobalSpamList = inSpamList; - } - - @Nullable - public Boolean isInUserSpamList() { - return isInUserSpamList; + public void setSpamStatus(@Nullable SpamStatus spamStatus) { + this.spamStatus = spamStatus; } - public void setIsInUserSpamList(boolean inSpamList) { - isInUserSpamList = inSpamList; + public Optional<SpamStatus> getSpamStatus() { + return Optional.fromNullable(spamStatus); } - @Nullable - public Boolean isInUserWhiteList() { - return isInUserWhiteList; - } + public boolean isSpam() { + if (spamStatus == null || !spamStatus.isSpam()) { + return false; + } - public void setIsInUserWhiteList(boolean inWhiteList) { - isInUserWhiteList = inWhiteList; - } + if (!isIncoming()) { + return false; + } - public boolean isSpam() { - return isSpam; - } + if (isPotentialEmergencyCallback()) { + return false; + } - public void setSpam(boolean isSpam) { - this.isSpam = isSpam; + return true; } public boolean isBlocked() { diff --git a/java/com/android/incallui/speakeasy/SpeakEasyComponent.java b/java/com/android/incallui/speakeasy/SpeakEasyComponent.java index 320bc69ee..6dae44128 100644 --- a/java/com/android/incallui/speakeasy/SpeakEasyComponent.java +++ b/java/com/android/incallui/speakeasy/SpeakEasyComponent.java @@ -30,6 +30,8 @@ public abstract class SpeakEasyComponent { public abstract Optional<Fragment> speakEasySettingsFragment(); + public abstract Optional<Integer> speakEasyIcon(); + public static SpeakEasyComponent get(Context context) { return ((SpeakEasyComponent.HasComponent) ((HasRootComponent) context.getApplicationContext()).component()) diff --git a/java/com/android/incallui/speakeasy/StubSpeakEasyModule.java b/java/com/android/incallui/speakeasy/StubSpeakEasyModule.java index d5f644372..67b564cb0 100644 --- a/java/com/android/incallui/speakeasy/StubSpeakEasyModule.java +++ b/java/com/android/incallui/speakeasy/StubSpeakEasyModule.java @@ -36,4 +36,9 @@ public abstract class StubSpeakEasyModule { static Optional<Fragment> provideSpeakEasySettingsFragment() { return Optional.absent(); } + + @Provides + static Optional<Integer> provideSpeakEasyIcon() { + return Optional.absent(); + } } |