diff options
40 files changed, 490 insertions, 58 deletions
diff --git a/java/com/android/dialer/calllog/CallLogModule.java b/java/com/android/dialer/calllog/CallLogModule.java index 56572705d..0e3a3be9e 100644 --- a/java/com/android/dialer/calllog/CallLogModule.java +++ b/java/com/android/dialer/calllog/CallLogModule.java @@ -22,11 +22,14 @@ import com.android.dialer.calllog.datasources.DataSources; import com.android.dialer.calllog.datasources.phonelookup.PhoneLookupDataSource; import com.android.dialer.calllog.datasources.systemcalllog.SystemCallLogDataSource; import com.android.dialer.calllog.datasources.voicemail.VoicemailDataSource; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.google.common.collect.ImmutableList; import dagger.Module; import dagger.Provides; /** Dagger module which satisfies call log dependencies. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module(includes = CallLogDatabaseModule.class) public abstract class CallLogModule { diff --git a/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java b/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java index 7fd8132aa..69cc02be4 100644 --- a/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java +++ b/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java @@ -31,6 +31,7 @@ import com.android.dialer.common.Assert; import com.android.dialer.duo.Duo; import com.android.dialer.duo.DuoComponent; import com.android.dialer.logging.Logger; +import com.android.dialer.promotion.RttPromotion; import com.android.dialer.storage.StorageComponent; import com.android.dialer.time.Clock; import java.lang.annotation.Retention; @@ -173,6 +174,9 @@ final class NewCallLogAdapter extends RecyclerView.Adapter<ViewHolder> { } private boolean shouldShowDuoDisclosureCard() { + if (new RttPromotion(activity).shouldShow()) { + return false; + } // Don't show the Duo disclosure card if // (1) Duo integration is not enabled on the device, or // (2) Duo is not activated. diff --git a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_duo_disclosure_card.xml b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_duo_disclosure_card.xml index 1e24c8ba2..a28101c6f 100644 --- a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_duo_disclosure_card.xml +++ b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_duo_disclosure_card.xml @@ -68,7 +68,7 @@ android:layout_gravity="end" android:paddingLeft="14dp" android:paddingRight="14dp" - android:text="@string/new_call_log_duo_disclosure_card_ok" + android:text="@string/ok_got_it" android:textSize="14sp"/> </LinearLayout> </LinearLayout> 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 f04bffa3f..ec8d59503 100644 --- a/java/com/android/dialer/calllog/ui/res/values/strings.xml +++ b/java/com/android/dialer/calllog/ui/res/values/strings.xml @@ -36,7 +36,4 @@ 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> - <!-- Text on the button on the Duo disclosure card. [CHAR_LIMIT=30] --> - <string name="new_call_log_duo_disclosure_card_ok">OK, got it</string> - </resources> diff --git a/java/com/android/dialer/commandline/CommandLineComponent.java b/java/com/android/dialer/commandline/CommandLineComponent.java index c9abc532d..50a1ff2b2 100644 --- a/java/com/android/dialer/commandline/CommandLineComponent.java +++ b/java/com/android/dialer/commandline/CommandLineComponent.java @@ -19,6 +19,7 @@ package com.android.dialer.commandline; import android.content.Context; import com.android.dialer.function.Supplier; import com.android.dialer.inject.HasRootComponent; +import com.android.dialer.inject.IncludeInDialerRoot; import com.google.common.collect.ImmutableMap; import dagger.Subcomponent; @@ -34,6 +35,7 @@ public abstract class CommandLineComponent { } /** Used to refer to the root application component. */ + @IncludeInDialerRoot public interface HasComponent { CommandLineComponent commandLineComponent(); } diff --git a/java/com/android/dialer/commandline/CommandLineModule.java b/java/com/android/dialer/commandline/CommandLineModule.java index c78de21e5..c3b58d1d5 100644 --- a/java/com/android/dialer/commandline/CommandLineModule.java +++ b/java/com/android/dialer/commandline/CommandLineModule.java @@ -23,12 +23,15 @@ import com.android.dialer.commandline.impl.Echo; import com.android.dialer.commandline.impl.Help; import com.android.dialer.commandline.impl.Version; import com.android.dialer.function.Supplier; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.google.common.collect.ImmutableMap; import dagger.Module; import dagger.Provides; import javax.inject.Inject; /** Provides {@link Command} */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public abstract class CommandLineModule { diff --git a/java/com/android/dialer/common/res/values/strings.xml b/java/com/android/dialer/common/res/values/strings.xml index cc0594dee..3bd21d5c1 100644 --- a/java/com/android/dialer/common/res/values/strings.xml +++ b/java/com/android/dialer/common/res/values/strings.xml @@ -21,4 +21,6 @@ <string name="content_description_overflow">More options</string> <!-- Text for undo button in snackbar for voicemail deletion/blocking/unblocking number. [CHAR LIMIT=10] --> <string name="snackbar_undo">UNDO</string> + <!-- Text on button of "OK, got it". [CHAR_LIMIT=30] --> + <string name="ok_got_it">OK, got it</string> </resources> diff --git a/java/com/android/dialer/configprovider/SharedPrefConfigProvider.java b/java/com/android/dialer/configprovider/SharedPrefConfigProvider.java index 54e9c9aff..c68312f56 100644 --- a/java/com/android/dialer/configprovider/SharedPrefConfigProvider.java +++ b/java/com/android/dialer/configprovider/SharedPrefConfigProvider.java @@ -102,6 +102,10 @@ public class SharedPrefConfigProvider implements ConfigProvider { sharedPreferences.edit().putLong(PREF_PREFIX + key, value).apply(); } + public void putString(String key, String value) { + sharedPreferences.edit().putString(PREF_PREFIX + key, value).apply(); + } + @Override public String getString(String key, String defaultValue) { // Reading shared prefs on the main thread is generally safe since a single instance is cached. diff --git a/java/com/android/dialer/dialpadview/DialpadFragment.java b/java/com/android/dialer/dialpadview/DialpadFragment.java index d48870dfc..8fb7533f4 100644 --- a/java/com/android/dialer/dialpadview/DialpadFragment.java +++ b/java/com/android/dialer/dialpadview/DialpadFragment.java @@ -478,12 +478,7 @@ public class DialpadFragment extends Fragment } digits.setContentDescription(null); - // TOOD(77908301): Investigate why this is the case - // It's not clear why digitsHint would be null when digits is initialized as the time, so adding - // a todo to investigate why. - if (digitsHint != null) { - digitsHint.setVisibility(View.GONE); - } + digitsHint.setVisibility(View.GONE); } /** diff --git a/java/com/android/dialer/feedback/stub/StubFeedbackModule.java b/java/com/android/dialer/feedback/stub/StubFeedbackModule.java index 49df09a04..19f7e2e6c 100644 --- a/java/com/android/dialer/feedback/stub/StubFeedbackModule.java +++ b/java/com/android/dialer/feedback/stub/StubFeedbackModule.java @@ -20,6 +20,8 @@ import android.content.Context; import com.android.dialer.common.LogUtil; import com.android.dialer.feedback.FeedbackSender; import com.android.dialer.inject.ApplicationContext; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.android.dialer.logging.LoggingBindings; import com.android.dialer.logging.LoggingBindingsFactory; import com.android.dialer.logging.LoggingBindingsStub; @@ -28,6 +30,7 @@ import dagger.Module; import dagger.Provides; /** Module which bind {@link com.android.dialer.feedback.stub.CallFeedbackListenerStub}. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public class StubFeedbackModule { diff --git a/java/com/android/dialer/glidephotomanager/GlidePhotoManagerModule.java b/java/com/android/dialer/glidephotomanager/GlidePhotoManagerModule.java index 79629d69e..d4199f0a8 100644 --- a/java/com/android/dialer/glidephotomanager/GlidePhotoManagerModule.java +++ b/java/com/android/dialer/glidephotomanager/GlidePhotoManagerModule.java @@ -17,11 +17,14 @@ package com.android.dialer.glidephotomanager; import com.android.dialer.glidephotomanager.impl.GlidePhotoManagerImpl; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import dagger.Binds; import dagger.Module; import javax.inject.Singleton; /** Module for {@link GlidePhotoManagerComponent} */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public abstract class GlidePhotoManagerModule { @Binds diff --git a/java/com/android/dialer/main/impl/MainSearchController.java b/java/com/android/dialer/main/impl/MainSearchController.java index 72c46cc7a..7d476c8f6 100644 --- a/java/com/android/dialer/main/impl/MainSearchController.java +++ b/java/com/android/dialer/main/impl/MainSearchController.java @@ -23,6 +23,7 @@ import android.content.Intent; import android.os.Bundle; import android.speech.RecognizerIntent; import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; import android.support.design.widget.FloatingActionButton; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; @@ -98,6 +99,9 @@ public class MainSearchController implements SearchBarListener { private boolean callPlacedFromSearch; private boolean requestingPermission; + private DialpadFragment dialpadFragment; + private NewSearchFragment searchFragment; + public MainSearchController( TransactionSafeActivity activity, BottomNavBar bottomNav, @@ -122,7 +126,7 @@ public class MainSearchController implements SearchBarListener { LogUtil.i("MainSearchController.showDialpadFromNewIntent", "Dialpad is already visible."); // Mark started from new intent in case there is a phone number in the intent - getDialpadFragment().setStartedFromNewIntent(true); + dialpadFragment.setStartedFromNewIntent(true); return; } showDialpad(/* animate=*/ false, /* fromNewIntent=*/ true); @@ -150,7 +154,6 @@ public class MainSearchController implements SearchBarListener { activity.setTitle(R.string.dialpad_activity_title); FragmentTransaction transaction = activity.getFragmentManager().beginTransaction(); - NewSearchFragment searchFragment = getSearchFragment(); // Show Search if (searchFragment == null) { @@ -162,16 +165,14 @@ public class MainSearchController implements SearchBarListener { } // Show Dialpad - if (getDialpadFragment() == null) { - DialpadFragment dialpadFragment = new DialpadFragment(); + if (dialpadFragment == null) { + dialpadFragment = new DialpadFragment(); dialpadFragment.setStartedFromNewIntent(fromNewIntent); transaction.add(R.id.dialpad_fragment_container, dialpadFragment, DIALPAD_FRAGMENT_TAG); searchFragment.setQuery("", CallInitiationType.Type.DIALPAD); } else { - DialpadFragment dialpadFragment = getDialpadFragment(); dialpadFragment.setStartedFromNewIntent(fromNewIntent); transaction.show(dialpadFragment); - searchFragment.setQuery(dialpadFragment.getQuery(), CallInitiationType.Type.DIALPAD); } transaction.commit(); @@ -189,7 +190,6 @@ public class MainSearchController implements SearchBarListener { */ private void hideDialpad(boolean animate) { LogUtil.enterBlock("MainSearchController.hideDialpad"); - DialpadFragment dialpadFragment = getDialpadFragment(); if (dialpadFragment == null) { LogUtil.e("MainSearchController.hideDialpad", "Dialpad fragment is null."); return; @@ -212,7 +212,7 @@ public class MainSearchController implements SearchBarListener { fab.show(); toolbar.slideDown(animate, fragmentContainer); - toolbar.transferQueryFromDialpad(getDialpadFragment().getQuery()); + toolbar.transferQueryFromDialpad(dialpadFragment.getQuery()); activity.setTitle(R.string.main_activity_label); dialpadFragment.setAnimate(animate); @@ -246,7 +246,7 @@ public class MainSearchController implements SearchBarListener { /** Should be called when {@link DialpadListener#onDialpadShown()} is called. */ public void onDialpadShown() { LogUtil.enterBlock("MainSearchController.onDialpadShown"); - getDialpadFragment().slideUp(true); + dialpadFragment.slideUp(true); hideBottomNav(); } @@ -263,7 +263,7 @@ public class MainSearchController implements SearchBarListener { public void onSearchListTouch() { LogUtil.enterBlock("MainSearchController.onSearchListTouched"); if (isDialpadVisible()) { - if (TextUtils.isEmpty(getDialpadFragment().getQuery())) { + if (TextUtils.isEmpty(dialpadFragment.getQuery())) { Logger.get(activity) .logImpression( DialerImpression.Type.MAIN_TOUCH_DIALPAD_SEARCH_LIST_TO_CLOSE_SEARCH_AND_DIALPAD); @@ -292,7 +292,7 @@ public class MainSearchController implements SearchBarListener { * @return true if #onBackPressed() handled to action. */ public boolean onBackPressed() { - if (isDialpadVisible() && !TextUtils.isEmpty(getDialpadFragment().getQuery())) { + if (isDialpadVisible() && !TextUtils.isEmpty(dialpadFragment.getQuery())) { LogUtil.i("MainSearchController.onBackPressed", "Dialpad visible with query"); Logger.get(activity) .logImpression(DialerImpression.Type.MAIN_PRESS_BACK_BUTTON_TO_HIDE_DIALPAD); @@ -315,7 +315,6 @@ public class MainSearchController implements SearchBarListener { /** Calls {@link #hideDialpad(boolean)}, removes the search fragment and clears the dialpad. */ private void closeSearch(boolean animate) { LogUtil.enterBlock("MainSearchController.closeSearch"); - NewSearchFragment searchFragment = getSearchFragment(); if (searchFragment == null) { LogUtil.e("MainSearchController.closeSearch", "Search fragment is null."); return; @@ -342,7 +341,6 @@ public class MainSearchController implements SearchBarListener { activity.getFragmentManager().beginTransaction().hide(searchFragment).commit(); // Clear the dialpad so the phone number isn't persisted between search sessions. - DialpadFragment dialpadFragment = getDialpadFragment(); if (dialpadFragment != null) { // Temporarily disable accessibility when we clear the dialpad, since it should be // invisible and should not announce anything. @@ -360,25 +358,18 @@ public class MainSearchController implements SearchBarListener { @Nullable protected DialpadFragment getDialpadFragment() { - return (DialpadFragment) activity.getFragmentManager().findFragmentByTag(DIALPAD_FRAGMENT_TAG); - } - - @Nullable - private NewSearchFragment getSearchFragment() { - return (NewSearchFragment) activity.getFragmentManager().findFragmentByTag(SEARCH_FRAGMENT_TAG); + return dialpadFragment; } private boolean isDialpadVisible() { - DialpadFragment fragment = getDialpadFragment(); - return fragment != null - && fragment.isAdded() - && !fragment.isHidden() - && fragment.isDialpadSlideUp(); + return dialpadFragment != null + && dialpadFragment.isAdded() + && !dialpadFragment.isHidden() + && dialpadFragment.isDialpadSlideUp(); } private boolean isSearchVisible() { - NewSearchFragment fragment = getSearchFragment(); - return fragment != null && fragment.isAdded() && !fragment.isHidden(); + return searchFragment != null && searchFragment.isAdded() && !searchFragment.isHidden(); } /** Returns true if the search UI is visible. */ @@ -388,8 +379,7 @@ public class MainSearchController implements SearchBarListener { /** Closes the keyboard if necessary. */ private void closeKeyboard() { - NewSearchFragment fragment = getSearchFragment(); - if (fragment != null && fragment.isAdded()) { + if (searchFragment != null && searchFragment.isAdded()) { toolbar.hideKeyboard(); } } @@ -418,15 +408,13 @@ public class MainSearchController implements SearchBarListener { hideBottomNav(); FragmentTransaction transaction = activity.getFragmentManager().beginTransaction(); - NewSearchFragment searchFragment = getSearchFragment(); - // Show Search if (searchFragment == null) { searchFragment = NewSearchFragment.newInstance(); transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG); transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); } else if (!isSearchVisible()) { - transaction.show(getSearchFragment()); + transaction.show(searchFragment); } searchFragment.setQuery( @@ -444,20 +432,18 @@ public class MainSearchController implements SearchBarListener { @Override public void onSearchQueryUpdated(String query) { - NewSearchFragment fragment = getSearchFragment(); - if (fragment != null) { - fragment.setQuery(query, CallInitiationType.Type.REGULAR_SEARCH); + if (searchFragment != null) { + searchFragment.setQuery(query, CallInitiationType.Type.REGULAR_SEARCH); } } /** @see OnDialpadQueryChangedListener#onDialpadQueryChanged(java.lang.String) */ public void onDialpadQueryChanged(String query) { query = SmartDialNameMatcher.normalizeNumber(/* context = */ activity, query); - NewSearchFragment fragment = getSearchFragment(); - if (fragment != null) { - fragment.setQuery(query, CallInitiationType.Type.DIALPAD); + if (searchFragment != null) { + searchFragment.setQuery(query, CallInitiationType.Type.DIALPAD); } - getDialpadFragment().process_quote_emergency_unquote(query); + dialpadFragment.process_quote_emergency_unquote(query); } @Override @@ -589,4 +575,14 @@ public class MainSearchController implements SearchBarListener { void onSearchClose(); } + + @VisibleForTesting + void setDialpadFragment(DialpadFragment dialpadFragment) { + this.dialpadFragment = dialpadFragment; + } + + @VisibleForTesting + void setSearchFragment(NewSearchFragment searchFragment) { + this.searchFragment = searchFragment; + } } diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java index e426ed215..2d6b0a6e7 100644 --- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java +++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java @@ -36,6 +36,7 @@ import android.provider.ContactsContract.QuickContact; import android.provider.VoicemailContract; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.design.widget.BottomSheetBehavior; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v4.content.ContextCompat; @@ -46,9 +47,11 @@ import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.text.method.LinkMovementMethod; import android.view.DragEvent; import android.view.View; import android.widget.ImageView; +import android.widget.TextView; import com.android.contacts.common.list.OnPhoneNumberPickerActionListener; import com.android.dialer.animation.AnimUtils; import com.android.dialer.app.DialtactsActivity; @@ -104,6 +107,8 @@ import com.android.dialer.metrics.Metrics; import com.android.dialer.metrics.MetricsComponent; import com.android.dialer.postcall.PostCall; import com.android.dialer.precall.PreCall; +import com.android.dialer.promotion.Promotion; +import com.android.dialer.promotion.RttPromotion; import com.android.dialer.searchfragment.list.NewSearchFragment.SearchFragmentListener; import com.android.dialer.smartdial.util.SmartDialPrefix; import com.android.dialer.speeddial.SpeedDialFragment; @@ -196,6 +201,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen private MissedCallCountObserver missedCallCountObserver; private UiListener<String> getLastOutgoingCallListener; private UiListener<Integer> missedCallObserverUiListener; + private View bottomSheet; public static Intent getShowTabIntent(Context context, @TabIndex int tabIndex) { Intent intent = new Intent(context, MainActivity.class); @@ -240,6 +246,9 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen dialpadFragmentHostInterface = new MainDialpadFragmentHost(); snackbarContainer = activity.findViewById(R.id.coordinator_layout); + bottomSheet = activity.findViewById(R.id.promotion_bottom_sheet); + BottomSheetBehavior<View> bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet); + bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); FloatingActionButton fab = activity.findViewById(R.id.fab); fab.setOnClickListener( @@ -255,7 +264,11 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen bottomNav = activity.findViewById(R.id.bottom_nav_bar); bottomNavTabListener = new MainBottomNavBarBottomNavTabListener( - activity, activity.getFragmentManager(), activity.getSupportFragmentManager(), fab); + activity, + activity.getFragmentManager(), + activity.getSupportFragmentManager(), + fab, + bottomSheet); bottomNav.addOnTabSelectedListener(bottomNavTabListener); // TODO(uabdullah): Handle case of when a sim is inserted/removed while the activity is open. boolean showVoicemailTab = canVoicemailTabBeShown(activity); @@ -1245,6 +1258,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen private final FragmentManager fragmentManager; private final android.support.v4.app.FragmentManager supportFragmentManager; private final FloatingActionButton fab; + private final View bottomSheet; @TabIndex private int selectedTab = -1; @@ -1252,11 +1266,13 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen TransactionSafeActivity activity, FragmentManager fragmentManager, android.support.v4.app.FragmentManager supportFragmentManager, - FloatingActionButton fab) { + FloatingActionButton fab, + View bottomSheet) { this.activity = activity; this.fragmentManager = fragmentManager; this.supportFragmentManager = supportFragmentManager; this.fab = fab; + this.bottomSheet = bottomSheet; } @Override @@ -1300,6 +1316,34 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen showFragment(fragment == null ? new CallLogFragment() : fragment, CALL_LOG_TAG); } fab.show(); + showPromotionBottomSheet(activity, bottomSheet); + } + + private static void showPromotionBottomSheet(Context context, View view) { + // TODO(a bug): Use a promotion manager to get promotion to show. + Promotion promotion = new RttPromotion(context); + BottomSheetBehavior<View> bottomSheetBehavior = BottomSheetBehavior.from(view); + + if (!promotion.shouldShow()) { + bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); + return; + } + ImageView icon = view.findViewById(R.id.promotion_icon); + icon.setImageResource(promotion.getIconRes()); + TextView details = view.findViewById(R.id.promotion_details); + details.setText(promotion.getDetails()); + // Required to make link clickable. + details.setMovementMethod(LinkMovementMethod.getInstance()); + TextView title = view.findViewById(R.id.promotion_title); + title.setText(promotion.getTitle()); + view.findViewById(R.id.ok_got_it) + .setOnClickListener( + v -> { + promotion.dismiss(); + bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); + }); + view.setVisibility(View.VISIBLE); + bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); } void disableNewCallLogFragment() { diff --git a/java/com/android/dialer/main/impl/res/layout/main_activity.xml b/java/com/android/dialer/main/impl/res/layout/main_activity.xml index a1d6e5372..b47806ece 100644 --- a/java/com/android/dialer/main/impl/res/layout/main_activity.xml +++ b/java/com/android/dialer/main/impl/res/layout/main_activity.xml @@ -63,6 +63,9 @@ android:src="@drawable/quantum_ic_dialpad_white_24" android:contentDescription="@string/dialpad_button_content_description" app:backgroundTint="?android:attr/colorAccent"/> + + <include android:id="@+id/promotion_bottom_sheet" + layout="@layout/promotion_bottom_sheet"/> </android.support.design.widget.CoordinatorLayout> <!-- BottomNavBar --> diff --git a/java/com/android/dialer/main/impl/res/layout/promotion_bottom_sheet.xml b/java/com/android/dialer/main/impl/res/layout/promotion_bottom_sheet.xml new file mode 100644 index 000000000..3f1e709fb --- /dev/null +++ b/java/com/android/dialer/main/impl/res/layout/promotion_bottom_sheet.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="24dp" + android:paddingBottom="8dp" + android:paddingStart="16dp" + android:paddingEnd="24dp" + android:background="#FAFAFA" + android:clickable="true" + android:elevation="8dp" + android:orientation="horizontal" + android:visibility="gone" + app:behavior_hideable="true" + app:behavior_skipCollapsed="true" + app:layout_behavior="android.support.design.widget.BottomSheetBehavior" + app:layout_insetEdge="bottom"> + + <ImageView + android:id="@+id/promotion_icon" + android:layout_width="36dp" + android:layout_height="36dp" + android:tint="@color/dialer_theme_color"/> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingStart="32dp" + android:orientation="vertical"> + <TextView + android:id="@+id/promotion_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fontFamily="sans-serif-medium" + android:textColor="#DD000000" + android:textSize="16sp" + /> + <TextView + android:id="@+id/promotion_details" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginBottom="16dp" + android:lineSpacingMultiplier="1.5" + android:textColor="#DD000000" + android:textSize="14sp"/> + <Button + android:id="@+id/ok_got_it" + style="@style/Widget.AppCompat.Button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginBottom="8dp" + android:layout_gravity="end" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:backgroundTint="@color/dialer_theme_color" + android:fontFamily="sans-serif-medium" + android:stateListAnimator="@null" + android:text="@string/ok_got_it" + android:textColor="@android:color/white" + android:textSize="16sp"/> + </LinearLayout> + +</LinearLayout>
\ No newline at end of file diff --git a/java/com/android/dialer/metrics/StubMetricsModule.java b/java/com/android/dialer/metrics/StubMetricsModule.java index a2d9ebfe2..46b2b4d84 100644 --- a/java/com/android/dialer/metrics/StubMetricsModule.java +++ b/java/com/android/dialer/metrics/StubMetricsModule.java @@ -16,10 +16,13 @@ package com.android.dialer.metrics; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import dagger.Binds; import dagger.Module; /** Binds stub {@link Metrics}. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public interface StubMetricsModule { diff --git a/java/com/android/dialer/phonelookup/PhoneLookupComponent.java b/java/com/android/dialer/phonelookup/PhoneLookupComponent.java index 832587c81..70743c84d 100644 --- a/java/com/android/dialer/phonelookup/PhoneLookupComponent.java +++ b/java/com/android/dialer/phonelookup/PhoneLookupComponent.java @@ -17,6 +17,7 @@ package com.android.dialer.phonelookup; import android.content.Context; import com.android.dialer.inject.HasRootComponent; +import com.android.dialer.inject.IncludeInDialerRoot; import com.android.dialer.phonelookup.composite.CompositePhoneLookup; import dagger.Subcomponent; @@ -32,6 +33,7 @@ public abstract class PhoneLookupComponent { } /** Used to refer to the root application component. */ + @IncludeInDialerRoot public interface HasComponent { PhoneLookupComponent phoneLookupComponent(); } diff --git a/java/com/android/dialer/phonelookup/PhoneLookupModule.java b/java/com/android/dialer/phonelookup/PhoneLookupModule.java index 16aa8e516..6d5ffd2ec 100644 --- a/java/com/android/dialer/phonelookup/PhoneLookupModule.java +++ b/java/com/android/dialer/phonelookup/PhoneLookupModule.java @@ -16,6 +16,8 @@ package com.android.dialer.phonelookup; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.android.dialer.phonelookup.blockednumber.SystemBlockedNumberPhoneLookup; import com.android.dialer.phonelookup.cequint.CequintPhoneLookup; import com.android.dialer.phonelookup.cnap.CnapPhoneLookup; @@ -28,6 +30,7 @@ import dagger.Module; import dagger.Provides; /** Dagger module which binds the PhoneLookup implementation. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public abstract class PhoneLookupModule { diff --git a/java/com/android/dialer/phonenumbergeoutil/impl/PhoneNumberGeoUtilModule.java b/java/com/android/dialer/phonenumbergeoutil/impl/PhoneNumberGeoUtilModule.java index 3878ac508..db4f7fa43 100644 --- a/java/com/android/dialer/phonenumbergeoutil/impl/PhoneNumberGeoUtilModule.java +++ b/java/com/android/dialer/phonenumbergeoutil/impl/PhoneNumberGeoUtilModule.java @@ -16,12 +16,15 @@ package com.android.dialer.phonenumbergeoutil.impl; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.android.dialer.phonenumbergeoutil.PhoneNumberGeoUtil; import dagger.Binds; import dagger.Module; import javax.inject.Singleton; /** Module which binds {@link PhoneNumberGeoUtilImpl}. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public abstract class PhoneNumberGeoUtilModule { diff --git a/java/com/android/dialer/precall/impl/PreCallModule.java b/java/com/android/dialer/precall/impl/PreCallModule.java index 455453ef3..fa78cba5c 100644 --- a/java/com/android/dialer/precall/impl/PreCallModule.java +++ b/java/com/android/dialer/precall/impl/PreCallModule.java @@ -16,6 +16,8 @@ package com.android.dialer.precall.impl; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.android.dialer.precall.PreCall; import com.android.dialer.precall.PreCallAction; import com.google.common.collect.ImmutableList; @@ -25,6 +27,7 @@ import dagger.Provides; import javax.inject.Singleton; /** Dagger module for {@link PreCall}. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public abstract class PreCallModule { diff --git a/java/com/android/dialer/promotion/AndroidManifest.xml b/java/com/android/dialer/promotion/AndroidManifest.xml new file mode 100644 index 000000000..bd85b104f --- /dev/null +++ b/java/com/android/dialer/promotion/AndroidManifest.xml @@ -0,0 +1,16 @@ +<!-- + ~ 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 + --> +<manifest package="com.android.dialer.promotion"/> diff --git a/java/com/android/dialer/promotion/Promotion.java b/java/com/android/dialer/promotion/Promotion.java new file mode 100644 index 000000000..3cd16d4a6 --- /dev/null +++ b/java/com/android/dialer/promotion/Promotion.java @@ -0,0 +1,39 @@ +/* + * 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.promotion; + +import android.support.annotation.DrawableRes; + +/** Interface for promotion bottom sheet. */ +public interface Promotion { + + /** Returns if this promotion should be shown. */ + boolean shouldShow(); + + /** Sets to show this promotion. */ + void setShouldShow(boolean shouldShow); + + /** Dismisses this promotion. This is called when user acknowledged the promotion. */ + void dismiss(); + + CharSequence getTitle(); + + CharSequence getDetails(); + + @DrawableRes + int getIconRes(); +} diff --git a/java/com/android/dialer/promotion/RttPromotion.java b/java/com/android/dialer/promotion/RttPromotion.java new file mode 100644 index 000000000..feb6e4734 --- /dev/null +++ b/java/com/android/dialer/promotion/RttPromotion.java @@ -0,0 +1,84 @@ +/* + * 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.promotion; + +import android.content.Context; +import android.content.SharedPreferences; +import android.support.annotation.DrawableRes; +import com.android.dialer.common.LogUtil; +import com.android.dialer.configprovider.ConfigProviderBindings; +import com.android.dialer.spannable.ContentWithLearnMoreSpanner; +import com.android.dialer.storage.StorageComponent; + +/** RTT promotion. */ +public final class RttPromotion implements Promotion { + private static final String SHARED_PREFERENCE_KEY_ENABLED = "rtt_promotion_enabled"; + private static final String SHARED_PREFERENCE_KEY_DISMISSED = "rtt_promotion_dismissed"; + private final Context appContext; + + public RttPromotion(Context context) { + appContext = context.getApplicationContext(); + } + + @Override + public boolean shouldShow() { + SharedPreferences sharedPreferences = StorageComponent.get(appContext).unencryptedSharedPrefs(); + return sharedPreferences.getBoolean(SHARED_PREFERENCE_KEY_ENABLED, false) + && !sharedPreferences.getBoolean(SHARED_PREFERENCE_KEY_DISMISSED, false); + } + + @Override + public CharSequence getTitle() { + return appContext.getString(R.string.rtt_promotion_title); + } + + @Override + public CharSequence getDetails() { + return new ContentWithLearnMoreSpanner(appContext) + .create( + appContext.getString(R.string.rtt_promotion_details), + ConfigProviderBindings.get(appContext) + .getString( + "rtt_promo_learn_more_link_full_url", + "http://support.google.com/pixelphone/?p=dialer_rtt")); + } + + @Override + @DrawableRes + public int getIconRes() { + return R.drawable.quantum_ic_rtt_vd_theme_24; + } + + @Override + public void setShouldShow(boolean shouldShow) { + LogUtil.i("RttPromotion.setShouldShow", "shouldShow: %b", shouldShow); + StorageComponent.get(appContext) + .unencryptedSharedPrefs() + .edit() + .putBoolean(SHARED_PREFERENCE_KEY_ENABLED, shouldShow) + .apply(); + } + + @Override + public void dismiss() { + StorageComponent.get(appContext) + .unencryptedSharedPrefs() + .edit() + .putBoolean(SHARED_PREFERENCE_KEY_DISMISSED, true) + .apply(); + } +} diff --git a/java/com/android/dialer/promotion/res/values/strings.xml b/java/com/android/dialer/promotion/res/values/strings.xml new file mode 100644 index 000000000..633671546 --- /dev/null +++ b/java/com/android/dialer/promotion/res/values/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Title for RTT promotion dialog. [CHAR LIMIT=NONE] --> + <string name="rtt_promotion_title">Real-time text messaging within a call</string> + + <!-- Details for RTT promotion dialog. [CHAR LIMIT=NONE] --> + <string name="rtt_promotion_details">RTT assists callers who are deaf, hard of hearing, have a speech + disability, or need more than voice alone. RTT messaging transcripts are stored on your device + in the call history. <xliff:g exmaple="Learn More">%1$s</xliff:g></string> + +</resources> diff --git a/java/com/android/dialer/simulator/impl/SimulatorModule.java b/java/com/android/dialer/simulator/impl/SimulatorModule.java index 2bc72c956..af554b66f 100644 --- a/java/com/android/dialer/simulator/impl/SimulatorModule.java +++ b/java/com/android/dialer/simulator/impl/SimulatorModule.java @@ -16,6 +16,8 @@ package com.android.dialer.simulator.impl; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.android.dialer.simulator.Simulator; import com.android.dialer.simulator.SimulatorConnectionsBank; import dagger.Binds; @@ -23,6 +25,7 @@ import dagger.Module; import javax.inject.Singleton; /** This module provides an instance of the simulator. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public abstract class SimulatorModule { @Binds diff --git a/java/com/android/dialer/simulator/stub/StubSimulatorEnrichedCallModule.java b/java/com/android/dialer/simulator/stub/StubSimulatorEnrichedCallModule.java index 36314e7a9..6a002f0e1 100644 --- a/java/com/android/dialer/simulator/stub/StubSimulatorEnrichedCallModule.java +++ b/java/com/android/dialer/simulator/stub/StubSimulatorEnrichedCallModule.java @@ -16,12 +16,15 @@ package com.android.dialer.simulator.stub; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.android.dialer.simulator.SimulatorEnrichedCall; import dagger.Binds; import dagger.Module; import javax.inject.Singleton; /** Provides a stub instance of SimulatorEnrichedCall. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public abstract class StubSimulatorEnrichedCallModule { @Binds diff --git a/java/com/android/dialer/spam/status/SimpleSpamStatus.java b/java/com/android/dialer/spam/status/SimpleSpamStatus.java index ec28b9dce..ff080ed1d 100644 --- a/java/com/android/dialer/spam/status/SimpleSpamStatus.java +++ b/java/com/android/dialer/spam/status/SimpleSpamStatus.java @@ -33,4 +33,10 @@ public abstract class SimpleSpamStatus implements SpamStatus { public static SimpleSpamStatus notSpam() { return create(false, null); } + + /** Returns an empty {@link SpamMetadata}. */ + @Override + public final SpamMetadata getSpamMetadata() { + return SpamMetadata.empty(); + } } diff --git a/java/com/android/dialer/spam/status/SpamMetadata.java b/java/com/android/dialer/spam/status/SpamMetadata.java new file mode 100644 index 000000000..40feba1a7 --- /dev/null +++ b/java/com/android/dialer/spam/status/SpamMetadata.java @@ -0,0 +1,52 @@ +/* + * 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.spam.status; + +import com.google.auto.value.AutoValue; +import com.google.common.base.Optional; + +/** + * Holds information which can be used to determine a number's spam status. + * + * @see SpamStatus + */ +@AutoValue +public abstract class SpamMetadata { + + /** Returns an empty spam metadata, no optional data is set. */ + public static SpamMetadata empty() { + return builder().build(); + } + + public static SpamMetadata.Builder builder() { + return new AutoValue_SpamMetadata.Builder(); + } + + public abstract Optional<GlobalSpamListStatus> globalSpamListStatus(); + + public abstract Optional<UserSpamListStatus> userSpamListStatus(); + + /** Creates instances of SpamMetadata. */ + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder setGlobalSpamListStatus(GlobalSpamListStatus globalSpamListStatus); + + public abstract Builder setUserSpamListStatus(UserSpamListStatus userSpamListStatus); + + public abstract SpamMetadata build(); + } +} diff --git a/java/com/android/dialer/spam/status/SpamStatus.java b/java/com/android/dialer/spam/status/SpamStatus.java index 8186ac5cc..10e8213ab 100644 --- a/java/com/android/dialer/spam/status/SpamStatus.java +++ b/java/com/android/dialer/spam/status/SpamStatus.java @@ -37,4 +37,7 @@ public interface SpamStatus { * </ul> */ Optional<Long> getTimestampMillis(); + + /** Returns the {@link SpamMetadata} associated with this status. */ + SpamMetadata getSpamMetadata(); } diff --git a/java/com/android/dialer/strictmode/impl/SystemStrictModeModule.java b/java/com/android/dialer/strictmode/impl/SystemStrictModeModule.java index 6ece874fe..ac6416cfc 100644 --- a/java/com/android/dialer/strictmode/impl/SystemStrictModeModule.java +++ b/java/com/android/dialer/strictmode/impl/SystemStrictModeModule.java @@ -16,12 +16,15 @@ package com.android.dialer.strictmode.impl; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.android.dialer.strictmode.DialerStrictMode; import dagger.Binds; import dagger.Module; import javax.inject.Singleton; /** Module which binds {@link SystemDialerStrictMode}. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public abstract class SystemStrictModeModule { diff --git a/java/com/android/incallui/AnswerScreenPresenter.java b/java/com/android/incallui/AnswerScreenPresenter.java index e41bac606..8b789f317 100644 --- a/java/com/android/incallui/AnswerScreenPresenter.java +++ b/java/com/android/incallui/AnswerScreenPresenter.java @@ -176,9 +176,6 @@ public class AnswerScreenPresenter return; } incomingCall.setIsSpeakEasyCall(true); - InCallActivity inCallActivity = - (InCallActivity) answerScreen.getAnswerScreenFragment().getActivity(); - inCallActivity.onPrimaryCallStateChanged(); } @Override diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java index 98f001925..70ba71ba1 100644 --- a/java/com/android/incallui/InCallActivity.java +++ b/java/com/android/incallui/InCallActivity.java @@ -1247,13 +1247,13 @@ public class InCallActivity extends TransactionSafeFragmentActivity ShouldShowUiResult shouldShowSpeakEasyUi = getShouldShowSpeakEasyUi(); LogUtil.i( "InCallActivity.showMainInCallFragment", - "shouldShowAnswerUi: %b, shouldShowRttUi: %b, shouldShowVideoUi: %b " - + "didShowAnswerScreen: %b, didShowInCallScreen: %b, didShowRttCallScreen: %b, " - + "didShowVideoCallScreen: %b" - + "didShowSpeakEasyScreen: %b", + "shouldShowAnswerUi: %b, shouldShowRttUi: %b, shouldShowVideoUi: %b, " + + "shouldShowSpeakEasyUi: %b, didShowAnswerScreen: %b, didShowInCallScreen: %b, " + + "didShowRttCallScreen: %b, didShowVideoCallScreen: %b, didShowSpeakEasyScreen: %b", shouldShowAnswerUi.shouldShow, shouldShowRttUi.shouldShow, shouldShowVideoUi.shouldShow, + shouldShowSpeakEasyUi.shouldShow, didShowAnswerScreen, didShowInCallScreen, didShowRttCallScreen, diff --git a/java/com/android/incallui/InCallPresenter.java b/java/com/android/incallui/InCallPresenter.java index ccc564806..da5d20fa3 100644 --- a/java/com/android/incallui/InCallPresenter.java +++ b/java/com/android/incallui/InCallPresenter.java @@ -990,6 +990,13 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud } @Override + public void onSpeakEasyStateChange() { + if (inCallActivity != null) { + inCallActivity.onPrimaryCallStateChanged(); + } + } + + @Override public void onSessionModificationStateChange(DialerCall call) { int newState = call.getVideoTech().getSessionModificationState(); LogUtil.i("InCallPresenter.onSessionModificationStateChange", "state: %d", newState); diff --git a/java/com/android/incallui/call/CallList.java b/java/com/android/incallui/call/CallList.java index 0e89ac75d..13be252dd 100644 --- a/java/com/android/incallui/call/CallList.java +++ b/java/com/android/incallui/call/CallList.java @@ -39,6 +39,7 @@ import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; 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; @@ -226,6 +227,9 @@ public class CallList implements DialerCallDelegate { if (call.getState() == DialerCallState.INCOMING || call.getState() == DialerCallState.CALL_WAITING) { if (call.isActiveRttCall()) { + if (!call.isPhoneAccountRttCapable()) { + new RttPromotion(context).setShouldShow(true); + } Logger.get(context) .logCallImpression( DialerImpression.Type.INCOMING_RTT_CALL, @@ -816,6 +820,9 @@ public class CallList implements DialerCallDelegate { */ default void onUpgradeToRtt(DialerCall call, int rttRequestId) {} + /** Called when the SpeakEasy state of a Dialer call is mutated. */ + default void onSpeakEasyStateChange() {} + /** Called when the session modification state of a call changes. */ void onSessionModificationStateChange(DialerCall call); @@ -894,6 +901,13 @@ public class CallList implements DialerCallDelegate { } @Override + public void onDialerCallSpeakEasyStateChange() { + for (Listener listener : listeners) { + listener.onSpeakEasyStateChange(); + } + } + + @Override public void onDialerCallUpgradeToVideo() { for (Listener listener : listeners) { listener.onUpgradeToVideo(call); diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java index 77e2ea30b..431634a0c 100644 --- a/java/com/android/incallui/call/DialerCall.java +++ b/java/com/android/incallui/call/DialerCall.java @@ -1067,7 +1067,7 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa } @TargetApi(28) - public boolean canUpgradeToRttCall() { + public boolean isPhoneAccountRttCapable() { PhoneAccount phoneAccount = getPhoneAccount(); if (phoneAccount == null) { return false; @@ -1075,6 +1075,14 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa if (!phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_RTT)) { return false; } + return true; + } + + @TargetApi(28) + public boolean canUpgradeToRttCall() { + if (!isPhoneAccountRttCapable()) { + return false; + } if (isActiveRttCall()) { return false; } @@ -1718,6 +1726,11 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa /** Sets the user preference for SpeakEasy */ public void setIsSpeakEasyCall(boolean isSpeakEasyCall) { this.isSpeakEasyCall = isSpeakEasyCall; + if (listeners != null) { + for (DialerCallListener listener : listeners) { + listener.onDialerCallSpeakEasyStateChange(); + } + } } /** diff --git a/java/com/android/incallui/call/DialerCallListener.java b/java/com/android/incallui/call/DialerCallListener.java index 37c30d30c..a42ccbd66 100644 --- a/java/com/android/incallui/call/DialerCallListener.java +++ b/java/com/android/incallui/call/DialerCallListener.java @@ -31,6 +31,8 @@ public interface DialerCallListener { default void onDialerCallUpgradeToRtt(int rttRequestId) {} + default void onDialerCallSpeakEasyStateChange() {} + void onDialerCallSessionModificationStateChange(); void onWiFiToLteHandover(); diff --git a/java/com/android/incallui/calllocation/stub/StubCallLocationModule.java b/java/com/android/incallui/calllocation/stub/StubCallLocationModule.java index 20460699a..c60663bff 100644 --- a/java/com/android/incallui/calllocation/stub/StubCallLocationModule.java +++ b/java/com/android/incallui/calllocation/stub/StubCallLocationModule.java @@ -20,12 +20,15 @@ import android.content.Context; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import com.android.dialer.common.Assert; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.android.incallui.calllocation.CallLocation; import dagger.Binds; import dagger.Module; import javax.inject.Inject; /** This module provides an instance of call location. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public abstract class StubCallLocationModule { diff --git a/java/com/android/incallui/speakeasy/StubSpeakEasyModule.java b/java/com/android/incallui/speakeasy/StubSpeakEasyModule.java index 960692b20..d5f644372 100644 --- a/java/com/android/incallui/speakeasy/StubSpeakEasyModule.java +++ b/java/com/android/incallui/speakeasy/StubSpeakEasyModule.java @@ -17,12 +17,15 @@ package com.android.incallui.speakeasy; import android.support.v4.app.Fragment; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.google.common.base.Optional; import dagger.Binds; import dagger.Module; import dagger.Provides; /** Module which binds {@link SpeakEasyCallManagerStub}. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public abstract class StubSpeakEasyModule { diff --git a/java/com/android/voicemail/impl/VoicemailModule.java b/java/com/android/voicemail/impl/VoicemailModule.java index e689e47d2..c4c72d30c 100644 --- a/java/com/android/voicemail/impl/VoicemailModule.java +++ b/java/com/android/voicemail/impl/VoicemailModule.java @@ -19,6 +19,8 @@ package com.android.voicemail.impl; import android.content.Context; import android.support.v4.os.BuildCompat; import com.android.dialer.inject.ApplicationContext; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; import com.android.voicemail.VoicemailClient; import com.android.voicemail.VoicemailPermissionHelper; import com.android.voicemail.stub.StubVoicemailClient; @@ -27,6 +29,7 @@ import dagger.Provides; import javax.inject.Singleton; /** This module provides an instance of the voicemail client. */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) @Module public final class VoicemailModule { diff --git a/packages.mk b/packages.mk index f31066906..3f94af240 100644 --- a/packages.mk +++ b/packages.mk @@ -53,6 +53,7 @@ LOCAL_AAPT_FLAGS := \ com.android.dialer.precall.externalreceiver \ com.android.dialer.preferredsim.impl \ com.android.dialer.preferredsim.suggestion \ + com.android.dialer.promotion \ com.android.dialer.rtt \ com.android.dialer.searchfragment.common \ com.android.dialer.searchfragment.cp2 \ |