summaryrefslogtreecommitdiff
path: root/java/com/android/dialer
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer')
-rw-r--r--java/com/android/dialer/activecalls/ActiveCallInfo.java48
-rw-r--r--java/com/android/dialer/activecalls/ActiveCalls.java34
-rw-r--r--java/com/android/dialer/activecalls/ActiveCallsComponent.java40
-rw-r--r--java/com/android/dialer/activecalls/ActiveCallsModule.java34
-rw-r--r--java/com/android/dialer/activecalls/impl/ActiveCallsImpl.java45
-rw-r--r--java/com/android/dialer/binary/aosp/AospDialerRootComponent.java2
-rw-r--r--java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java4
-rw-r--r--java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java2
-rw-r--r--java/com/android/dialer/commandline/CommandLineModule.java7
-rw-r--r--java/com/android/dialer/commandline/impl/ActiveCallsCommand.java67
-rw-r--r--java/com/android/dialer/common/FragmentUtils.java5
-rw-r--r--java/com/android/dialer/dialpadview/SpecialCharSequenceMgr.java11
-rw-r--r--java/com/android/dialer/logging/dialer_impression.proto12
-rw-r--r--java/com/android/dialer/main/impl/NewMainActivityPeer.java23
-rw-r--r--java/com/android/dialer/main/impl/OldMainActivityPeer.java23
-rw-r--r--java/com/android/dialer/oem/CequintCallerIdManager.java56
-rw-r--r--java/com/android/dialer/phonelookup/PhoneLookupModule.java3
-rw-r--r--java/com/android/dialer/phonelookup/cequint/CequintPhoneLookup.java90
-rw-r--r--java/com/android/dialer/phonelookup/phone_lookup_info.proto14
-rw-r--r--java/com/android/dialer/phonenumbercache/ContactInfoHelper.java12
-rw-r--r--java/com/android/dialer/precall/impl/CallingAccountSelector.java203
-rw-r--r--java/com/android/dialer/precall/impl/res/values/strings.xml6
-rw-r--r--java/com/android/dialer/preferredsim/suggestion/SuggestionProvider.java45
-rw-r--r--java/com/android/dialer/speeddial/SpeedDialAdapter.java5
-rw-r--r--java/com/android/dialer/speeddial/SpeedDialFragment.java17
-rw-r--r--java/com/android/dialer/speeddial/database/SpeedDialEntryDao.java8
-rw-r--r--java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java27
-rw-r--r--java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java9
-rw-r--r--java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java63
-rw-r--r--java/com/android/dialer/theme/res/color/dialer_primary_text_color.xml21
-rw-r--r--java/com/android/dialer/theme/res/color/dialer_secondary_text_color.xml21
-rw-r--r--java/com/android/dialer/theme/res/values/colors.xml6
32 files changed, 808 insertions, 155 deletions
diff --git a/java/com/android/dialer/activecalls/ActiveCallInfo.java b/java/com/android/dialer/activecalls/ActiveCallInfo.java
new file mode 100644
index 000000000..d4f76b393
--- /dev/null
+++ b/java/com/android/dialer/activecalls/ActiveCallInfo.java
@@ -0,0 +1,48 @@
+/*
+ * 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.activecalls;
+
+import android.support.annotation.Nullable;
+import android.telecom.PhoneAccountHandle;
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Optional;
+
+/** Info of an active call */
+@AutoValue
+@SuppressWarnings("Guava")
+public abstract class ActiveCallInfo {
+
+ /** The {@link PhoneAccountHandle} the call is made with */
+ public abstract Optional<PhoneAccountHandle> phoneAccountHandle();
+
+ public static Builder builder() {
+ return new AutoValue_ActiveCallInfo.Builder();
+ }
+
+ /** Builder for {@link ActiveCallInfo}. Only In Call UI should create ActiveCallInfo */
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public Builder setPhoneAccountHandle(@Nullable PhoneAccountHandle phoneAccountHandle) {
+ return setPhoneAccountHandle(Optional.fromNullable(phoneAccountHandle));
+ }
+
+ public abstract Builder setPhoneAccountHandle(Optional<PhoneAccountHandle> phoneAccountHandle);
+
+ public abstract ActiveCallInfo build();
+ }
+}
diff --git a/java/com/android/dialer/activecalls/ActiveCalls.java b/java/com/android/dialer/activecalls/ActiveCalls.java
new file mode 100644
index 000000000..600839c73
--- /dev/null
+++ b/java/com/android/dialer/activecalls/ActiveCalls.java
@@ -0,0 +1,34 @@
+/*
+ * 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.activecalls;
+
+import android.support.annotation.MainThread;
+import com.google.common.collect.ImmutableList;
+
+/** Exposes information about current active calls to the whole dialer. */
+public interface ActiveCalls {
+
+ /**
+ * Return a list of current active calls. Any call that is not disconnected is regarded as active.
+ * Ordering of elements are not guaranteed.
+ */
+ ImmutableList<ActiveCallInfo> getActiveCalls();
+
+ /** Should only be called by in call UI. */
+ @MainThread
+ void setActiveCalls(ImmutableList<ActiveCallInfo> activeCalls);
+}
diff --git a/java/com/android/dialer/activecalls/ActiveCallsComponent.java b/java/com/android/dialer/activecalls/ActiveCallsComponent.java
new file mode 100644
index 000000000..99e0e9493
--- /dev/null
+++ b/java/com/android/dialer/activecalls/ActiveCallsComponent.java
@@ -0,0 +1,40 @@
+/*
+ * 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.activecalls;
+
+import android.content.Context;
+import com.android.dialer.inject.HasRootComponent;
+import com.android.dialer.inject.IncludeInDialerRoot;
+import dagger.Subcomponent;
+
+/** Component for {@link ActiveCalls} */
+@Subcomponent
+public abstract class ActiveCallsComponent {
+
+ public abstract ActiveCalls activeCalls();
+
+ public static ActiveCallsComponent get(Context context) {
+ return ((HasComponent) ((HasRootComponent) context.getApplicationContext()).component())
+ .activeCallsComponent();
+ }
+
+ /** Used to refer to the root application component. */
+ @IncludeInDialerRoot
+ public interface HasComponent {
+ ActiveCallsComponent activeCallsComponent();
+ }
+}
diff --git a/java/com/android/dialer/activecalls/ActiveCallsModule.java b/java/com/android/dialer/activecalls/ActiveCallsModule.java
new file mode 100644
index 000000000..4d7f44858
--- /dev/null
+++ b/java/com/android/dialer/activecalls/ActiveCallsModule.java
@@ -0,0 +1,34 @@
+/*
+ * 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.activecalls;
+
+import com.android.dialer.activecalls.impl.ActiveCallsImpl;
+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 ActiveCallsComponent} */
+@Module
+@InstallIn(variants = DialerVariant.DIALER_TEST) // TODO(weijiaxu): put all variants.
+public abstract class ActiveCallsModule {
+
+ @Singleton
+ @Binds
+ public abstract ActiveCalls to(ActiveCallsImpl impl);
+}
diff --git a/java/com/android/dialer/activecalls/impl/ActiveCallsImpl.java b/java/com/android/dialer/activecalls/impl/ActiveCallsImpl.java
new file mode 100644
index 000000000..3449cc8b0
--- /dev/null
+++ b/java/com/android/dialer/activecalls/impl/ActiveCallsImpl.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.activecalls.impl;
+
+import android.support.annotation.MainThread;
+import com.android.dialer.activecalls.ActiveCallInfo;
+import com.android.dialer.activecalls.ActiveCalls;
+import com.android.dialer.common.Assert;
+import com.google.common.collect.ImmutableList;
+import javax.inject.Inject;
+
+/** Implementation of {@link ActiveCalls} */
+public class ActiveCallsImpl implements ActiveCalls {
+
+ ImmutableList<ActiveCallInfo> activeCalls = ImmutableList.of();
+
+ @Inject
+ ActiveCallsImpl() {}
+
+ @Override
+ public ImmutableList<ActiveCallInfo> getActiveCalls() {
+ return activeCalls;
+ }
+
+ @Override
+ @MainThread
+ public void setActiveCalls(ImmutableList<ActiveCallInfo> activeCalls) {
+ Assert.isMainThread();
+ this.activeCalls = Assert.isNotNull(activeCalls);
+ }
+}
diff --git a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
index 21a282ded..e1021894f 100644
--- a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
+++ b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
@@ -17,6 +17,7 @@
package com.android.dialer.binary.aosp;
import com.android.bubble.stub.StubBubbleModule;
+import com.android.dialer.activecalls.ActiveCallsModule;
import com.android.dialer.binary.basecomponent.BaseDialerRootComponent;
import com.android.dialer.calllog.CallLogModule;
import com.android.dialer.calllog.config.CallLogConfigModule;
@@ -49,6 +50,7 @@ import javax.inject.Singleton;
@Singleton
@Component(
modules = {
+ ActiveCallsModule.class,
CallLogModule.class,
CallLogConfigModule.class,
CommandLineModule.class,
diff --git a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
index 11e952cbc..75ddaf7f0 100644
--- a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
+++ b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
@@ -17,6 +17,7 @@
package com.android.dialer.binary.basecomponent;
import com.android.bubble.BubbleComponent;
+import com.android.dialer.activecalls.ActiveCallsComponent;
import com.android.dialer.calllog.CallLogComponent;
import com.android.dialer.calllog.config.CallLogConfigComponent;
import com.android.dialer.calllog.database.CallLogDatabaseComponent;
@@ -50,7 +51,8 @@ import com.android.voicemail.VoicemailComponent;
* from this component.
*/
public interface BaseDialerRootComponent
- extends BluetoothDeviceProviderComponent.HasComponent,
+ extends ActiveCallsComponent.HasComponent,
+ BluetoothDeviceProviderComponent.HasComponent,
BubbleComponent.HasComponent,
CallLocationComponent.HasComponent,
CallLogComponent.HasComponent,
diff --git a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
index 0da2f9577..bdbdeb9dd 100644
--- a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
+++ b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
@@ -17,6 +17,7 @@
package com.android.dialer.binary.google;
import com.android.bubble.stub.StubBubbleModule;
+import com.android.dialer.activecalls.ActiveCallsModule;
import com.android.dialer.binary.basecomponent.BaseDialerRootComponent;
import com.android.dialer.calllog.CallLogModule;
import com.android.dialer.calllog.config.CallLogConfigModule;
@@ -52,6 +53,7 @@ import javax.inject.Singleton;
@Singleton
@Component(
modules = {
+ ActiveCallsModule.class,
CallLocationModule.class,
CallLogModule.class,
CallLogConfigModule.class,
diff --git a/java/com/android/dialer/commandline/CommandLineModule.java b/java/com/android/dialer/commandline/CommandLineModule.java
index 915578722..c78de21e5 100644
--- a/java/com/android/dialer/commandline/CommandLineModule.java
+++ b/java/com/android/dialer/commandline/CommandLineModule.java
@@ -16,6 +16,7 @@
package com.android.dialer.commandline;
+import com.android.dialer.commandline.impl.ActiveCallsCommand;
import com.android.dialer.commandline.impl.BlockingCommand;
import com.android.dialer.commandline.impl.CallCommand;
import com.android.dialer.commandline.impl.Echo;
@@ -45,6 +46,7 @@ public abstract class CommandLineModule {
private final Echo echo;
private final BlockingCommand blockingCommand;
private final CallCommand callCommand;
+ private final ActiveCallsCommand activeCallsCommand;
@Inject
AospCommandInjector(
@@ -52,12 +54,14 @@ public abstract class CommandLineModule {
Version version,
Echo echo,
BlockingCommand blockingCommand,
- CallCommand callCommand) {
+ CallCommand callCommand,
+ ActiveCallsCommand activeCallsCommand) {
this.help = help;
this.version = version;
this.echo = echo;
this.blockingCommand = blockingCommand;
this.callCommand = callCommand;
+ this.activeCallsCommand = activeCallsCommand;
}
public CommandSupplier.Builder inject(CommandSupplier.Builder builder) {
@@ -66,6 +70,7 @@ public abstract class CommandLineModule {
builder.addCommand("echo", echo);
builder.addCommand("blocking", blockingCommand);
builder.addCommand("call", callCommand);
+ builder.addCommand("activecalls", activeCallsCommand);
return builder;
}
}
diff --git a/java/com/android/dialer/commandline/impl/ActiveCallsCommand.java b/java/com/android/dialer/commandline/impl/ActiveCallsCommand.java
new file mode 100644
index 000000000..81641ed50
--- /dev/null
+++ b/java/com/android/dialer/commandline/impl/ActiveCallsCommand.java
@@ -0,0 +1,67 @@
+/*
+ * 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.commandline.impl;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import com.android.dialer.activecalls.ActiveCallsComponent;
+import com.android.dialer.commandline.Arguments;
+import com.android.dialer.commandline.Command;
+import com.android.dialer.inject.ApplicationContext;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import javax.inject.Inject;
+
+/** Manipulates {@link com.android.dialer.activecalls.ActiveCalls} */
+public class ActiveCallsCommand implements Command {
+
+ private final Context appContext;
+
+ @Inject
+ ActiveCallsCommand(@ApplicationContext Context appContext) {
+ this.appContext = appContext;
+ }
+
+ @NonNull
+ @Override
+ public String getShortDescription() {
+ return "manipulate active calls";
+ }
+
+ @NonNull
+ @Override
+ public String getUsage() {
+ return "activecalls list";
+ }
+
+ @Override
+ public ListenableFuture<String> run(Arguments args) throws IllegalCommandLineArgumentException {
+ if (args.getPositionals().isEmpty()) {
+ return Futures.immediateFuture(getUsage());
+ }
+
+ String command = args.getPositionals().get(0);
+
+ switch (command) {
+ case "list":
+ return Futures.immediateFuture(
+ ActiveCallsComponent.get(appContext).activeCalls().getActiveCalls().toString());
+ default:
+ throw new IllegalCommandLineArgumentException("unknown command " + command);
+ }
+ }
+}
diff --git a/java/com/android/dialer/common/FragmentUtils.java b/java/com/android/dialer/common/FragmentUtils.java
index c07d9a799..aa4441eeb 100644
--- a/java/com/android/dialer/common/FragmentUtils.java
+++ b/java/com/android/dialer/common/FragmentUtils.java
@@ -59,6 +59,11 @@ public class FragmentUtils {
@SuppressWarnings("unchecked") // Casts are checked using runtime methods
T parent = ((FragmentUtilListener) fragment.getActivity()).getImpl(callbackInterface);
return parent;
+ } else if (fragment.getActivity() instanceof MainActivityPeer.PeerSupplier) {
+ MainActivityPeer peer = ((MainActivityPeer.PeerSupplier) fragment.getActivity()).getPeer();
+ if (peer instanceof FragmentUtilListener) {
+ return ((FragmentUtilListener) peer).getImpl(callbackInterface);
+ }
}
return null;
}
diff --git a/java/com/android/dialer/dialpadview/SpecialCharSequenceMgr.java b/java/com/android/dialer/dialpadview/SpecialCharSequenceMgr.java
index 9929ddd3b..d2652ee66 100644
--- a/java/com/android/dialer/dialpadview/SpecialCharSequenceMgr.java
+++ b/java/com/android/dialer/dialpadview/SpecialCharSequenceMgr.java
@@ -56,6 +56,7 @@ import com.android.contacts.common.database.NoNullCursorAsyncQueryHandler;
import com.android.contacts.common.util.ContactDisplayUtils;
import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment;
import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment.SelectPhoneAccountListener;
+import com.android.contacts.common.widget.SelectPhoneAccountDialogOptionsUtil;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.compat.telephony.TelephonyManagerCompat;
@@ -234,10 +235,12 @@ public class SpecialCharSequenceMgr {
} else {
SelectPhoneAccountListener callback =
new HandleAdnEntryAccountSelectedCallback(applicationContext, handler, sc);
-
DialogFragment dialogFragment =
SelectPhoneAccountDialogFragment.newInstance(
- subscriptionAccountHandles, callback, null);
+ SelectPhoneAccountDialogOptionsUtil.builderWithAccounts(
+ subscriptionAccountHandles)
+ .build(),
+ callback);
dialogFragment.show(((Activity) context).getFragmentManager(), TAG_SELECT_ACCT_FRAGMENT);
}
@@ -292,7 +295,9 @@ public class SpecialCharSequenceMgr {
DialogFragment dialogFragment =
SelectPhoneAccountDialogFragment.newInstance(
- subscriptionAccountHandles, listener, null);
+ SelectPhoneAccountDialogOptionsUtil.builderWithAccounts(subscriptionAccountHandles)
+ .build(),
+ listener);
dialogFragment.show(((Activity) context).getFragmentManager(), TAG_SELECT_ACCT_FRAGMENT);
}
return true;
diff --git a/java/com/android/dialer/logging/dialer_impression.proto b/java/com/android/dialer/logging/dialer_impression.proto
index 5d40bb1ea..7cd22079c 100644
--- a/java/com/android/dialer/logging/dialer_impression.proto
+++ b/java/com/android/dialer/logging/dialer_impression.proto
@@ -12,7 +12,7 @@ message DialerImpression {
// Event enums to be used for Impression Logging in Dialer.
// It's perfectly acceptable for this enum to be large
// Values should be from 1000 to 100000.
- // Next Tag: 1387
+ // Next Tag: 1392
enum Type {
UNKNOWN_AOSP_EVENT_TYPE = 1000;
@@ -626,7 +626,11 @@ message DialerImpression {
DUAL_SIM_SELECTION_NON_SUGGESTED_SIM_SELECTED = 1304;
DUAL_SIM_SELECTION_PREFERRED_SET = 1305;
DUAL_SIM_SELECTION_PREFERRED_USED = 1306;
+ DUAL_SIM_SELECTION_PREFERRED_NOT_SELECTABLE = 1389;
DUAL_SIM_SELECTION_GLOBAL_USED = 1307;
+ DUAL_SIM_SELECTION_GLOBAL_NOT_SELECTABLE = 1390;
+ DUAL_SIM_SELECTION_SUGGESTION_AUTO_SELECTED = 1322;
+ DUAL_SIM_SELECTION_SUGGESTION_AUTO_NOT_SELECTABLE = 1391;
DUO_CALL_LOG_SET_UP_INSTALL = 1308;
DUO_CALL_LOG_SET_UP_ACTIVATE = 1309;
@@ -655,8 +659,6 @@ message DialerImpression {
// Drag bubble to bottom and end call
BUBBLE_V2_BOTTOM_ACTION_END_CALL = 1321;
- DUAL_SIM_SELECTION_SUGGESTION_AUTO_SELECTED = 1322;
-
// Bubble appears
BUBBLE_V2_SHOW = 1323;
@@ -764,5 +766,9 @@ message DialerImpression {
RTT_MID_CALL_ACCEPTED = 1385;
// Mid call RTT request rejected.
RTT_MID_CALL_REJECTED = 1386;
+
+ // Send button clicked in RTT call, this includes send button on keyboard.
+ RTT_SEND_BUTTON_CLICKED = 1387;
+ RTT_KEYBOARD_SEND_BUTTON_CLICKED = 1388;
}
}
diff --git a/java/com/android/dialer/main/impl/NewMainActivityPeer.java b/java/com/android/dialer/main/impl/NewMainActivityPeer.java
index 0ab69a443..f2d6fa6d3 100644
--- a/java/com/android/dialer/main/impl/NewMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/NewMainActivityPeer.java
@@ -29,7 +29,6 @@ import com.android.dialer.main.MainActivityPeer;
import com.android.dialer.main.impl.bottomnav.BottomNavBar;
import com.android.dialer.main.impl.bottomnav.BottomNavBar.OnBottomNavTabSelectedListener;
import com.android.dialer.main.impl.bottomnav.BottomNavBar.TabIndex;
-import com.android.dialer.speeddial.SpeedDialFragment;
import com.android.dialer.voicemail.listui.NewVoicemailFragment;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
@@ -106,16 +105,18 @@ public class NewMainActivityPeer implements MainActivityPeer {
@Override
public void onSpeedDialSelected() {
hideAllFragments();
- SpeedDialFragment fragment =
- (SpeedDialFragment) supportFragmentManager.findFragmentByTag(SPEED_DIAL_TAG);
- if (fragment == null) {
- supportFragmentManager
- .beginTransaction()
- .add(R.id.fragment_container, SpeedDialFragment.newInstance(), SPEED_DIAL_TAG)
- .commit();
- } else {
- supportFragmentManager.beginTransaction().show(fragment).commit();
- }
+ // TODO(calderwoodra): Since we aren't using fragment utils in this peer, let's disable
+ // speed dial until we figure out a solution.
+ // SpeedDialFragment fragment =
+ // (SpeedDialFragment) supportFragmentManager.findFragmentByTag(SPEED_DIAL_TAG);
+ // if (fragment == null) {
+ // supportFragmentManager
+ // .beginTransaction()
+ // .add(R.id.fragment_container, SpeedDialFragment.newInstance(), SPEED_DIAL_TAG)
+ // .commit();
+ // } else {
+ // supportFragmentManager.beginTransaction().show(fragment).commit();
+ // }
}
@Override
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index 1c0cad0b0..9ac351094 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -183,6 +183,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
// Speed Dial
private MainOnPhoneNumberPickerActionListener onPhoneNumberPickerActionListener;
private MainOldSpeedDialFragmentHost oldSpeedDialFragmentHost;
+ private MainSpeedDialFragmentHost speedDialFragmentHost;
/** Language the device was in last time {@link #onSaveInstanceState(Bundle)} was called. */
private String savedLanguageCode;
@@ -293,6 +294,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
activity.findViewById(R.id.remove_view),
activity.findViewById(R.id.search_view_container),
toolbar);
+ speedDialFragmentHost = new MainSpeedDialFragmentHost(toolbar);
lastTabController = new LastTabController(activity, bottomNav, showVoicemailTab);
@@ -639,6 +641,8 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
return (T) oldSpeedDialFragmentHost;
} else if (callbackInterface.isInstance(searchController)) {
return (T) searchController;
+ } else if (callbackInterface.isInstance(speedDialFragmentHost)) {
+ return (T) speedDialFragmentHost;
} else {
return null;
}
@@ -1191,6 +1195,25 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
}
/**
+ * Handles the callbacks for {@link SpeedDialFragment}.
+ *
+ * @see SpeedDialFragment.HostInterface
+ */
+ private static final class MainSpeedDialFragmentHost implements SpeedDialFragment.HostInterface {
+
+ private final MainToolbar toolbar;
+
+ MainSpeedDialFragmentHost(MainToolbar toolbar) {
+ this.toolbar = toolbar;
+ }
+
+ @Override
+ public void setHasFrequents(boolean hasFrequents) {
+ toolbar.showClearFrequents(hasFrequents);
+ }
+ }
+
+ /**
* Implementation of {@link OnBottomNavTabSelectedListener} that handles logic for showing each of
* the main tabs and FAB.
*
diff --git a/java/com/android/dialer/oem/CequintCallerIdManager.java b/java/com/android/dialer/oem/CequintCallerIdManager.java
index ee865bc14..55cafc15e 100644
--- a/java/com/android/dialer/oem/CequintCallerIdManager.java
+++ b/java/com/android/dialer/oem/CequintCallerIdManager.java
@@ -30,6 +30,7 @@ import android.text.TextUtils;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.configprovider.ConfigProviderBindings;
+import com.google.auto.value.AutoValue;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -70,20 +71,37 @@ public class CequintCallerIdManager {
// TODO(wangqi): Revisit it and maybe remove it if it's not necessary.
private final ConcurrentHashMap<String, CequintCallerIdContact> callLogCache;
- /** Cequint caller id contact information. */
- public static class CequintCallerIdContact {
- public final String name;
- public final String geoDescription;
- public final String imageUrl;
+ /** Cequint caller ID contact information. */
+ @AutoValue
+ public abstract static class CequintCallerIdContact {
- private CequintCallerIdContact(String name, String geoDescription, String imageUrl) {
- this.name = name;
- this.geoDescription = geoDescription;
- this.imageUrl = imageUrl;
+ public abstract String name();
+
+ /**
+ * Description of the geolocation (e.g., "Mountain View, CA"), which is for display purpose
+ * only.
+ */
+ public abstract String geolocation();
+
+ public abstract String photoUri();
+
+ static Builder builder() {
+ return new AutoValue_CequintCallerIdManager_CequintCallerIdContact.Builder();
+ }
+
+ @AutoValue.Builder
+ abstract static class Builder {
+ abstract Builder setName(String name);
+
+ abstract Builder setGeolocation(String geolocation);
+
+ abstract Builder setPhotoUri(String photoUri);
+
+ abstract CequintCallerIdContact build();
}
}
- /** Check whether Cequint Caller Id provider package is available and enabled. */
+ /** Check whether Cequint Caller ID provider package is available and enabled. */
@AnyThread
public static synchronized boolean isCequintCallerIdEnabled(@NonNull Context context) {
if (!ConfigProviderBindings.get(context).getBoolean(CONFIG_CALLER_ID_ENABLED, true)) {
@@ -175,22 +193,26 @@ public class CequintCallerIdManager {
String name = getString(cursor, cursor.getColumnIndex(NAME));
String firstName = getString(cursor, cursor.getColumnIndex(FIRST_NAME));
String lastName = getString(cursor, cursor.getColumnIndex(LAST_NAME));
- String imageUrl = getString(cursor, cursor.getColumnIndex(IMAGE));
+ String photoUri = getString(cursor, cursor.getColumnIndex(IMAGE));
String displayName = getString(cursor, cursor.getColumnIndex(DISPLAY_NAME));
String contactName =
TextUtils.isEmpty(displayName)
? generateDisplayName(firstName, lastName, company, name)
: displayName;
- String geoDescription = getGeoDescription(city, state, stateAbbr, country);
+ String geolocation = getGeolocation(city, state, stateAbbr, country);
LogUtil.d(
"CequintCallerIdManager.lookup",
"number: %s, contact name: %s, geo: %s, photo url: %s",
LogUtil.sanitizePhoneNumber(number),
LogUtil.sanitizePii(contactName),
- LogUtil.sanitizePii(geoDescription),
- imageUrl);
- return new CequintCallerIdContact(contactName, geoDescription, imageUrl);
+ LogUtil.sanitizePii(geolocation),
+ photoUri);
+ return CequintCallerIdContact.builder()
+ .setName(contactName)
+ .setGeolocation(geolocation)
+ .setPhotoUri(photoUri)
+ .build();
} else {
LogUtil.d("CequintCallerIdManager.lookup", "No CequintCallerIdContact found");
return null;
@@ -249,8 +271,8 @@ public class CequintCallerIdManager {
return null;
}
- /** Returns geo location information. e.g. Mountain View, CA. */
- private static String getGeoDescription(
+ /** Returns geolocation information (e.g., "Mountain View, CA"). */
+ private static String getGeolocation(
String city, String state, String stateAbbr, String country) {
String geoDescription = null;
diff --git a/java/com/android/dialer/phonelookup/PhoneLookupModule.java b/java/com/android/dialer/phonelookup/PhoneLookupModule.java
index 86e6991c1..c6e91c4a4 100644
--- a/java/com/android/dialer/phonelookup/PhoneLookupModule.java
+++ b/java/com/android/dialer/phonelookup/PhoneLookupModule.java
@@ -17,6 +17,7 @@
package com.android.dialer.phonelookup;
import com.android.dialer.phonelookup.blockednumber.SystemBlockedNumberPhoneLookup;
+import com.android.dialer.phonelookup.cequint.CequintPhoneLookup;
import com.android.dialer.phonelookup.cnap.CnapPhoneLookup;
import com.android.dialer.phonelookup.cp2.Cp2DefaultDirectoryPhoneLookup;
import com.android.dialer.phonelookup.cp2.Cp2ExtendedDirectoryPhoneLookup;
@@ -32,12 +33,14 @@ public abstract class PhoneLookupModule {
@Provides
@SuppressWarnings({"unchecked", "rawtype"})
static ImmutableList<PhoneLookup> providePhoneLookupList(
+ CequintPhoneLookup cequintPhoneLookup,
CnapPhoneLookup cnapPhoneLookup,
Cp2DefaultDirectoryPhoneLookup cp2DefaultDirectoryPhoneLookup,
Cp2ExtendedDirectoryPhoneLookup cp2ExtendedDirectoryPhoneLookup,
SystemBlockedNumberPhoneLookup systemBlockedNumberPhoneLookup,
SpamPhoneLookup spamPhoneLookup) {
return ImmutableList.of(
+ cequintPhoneLookup,
cnapPhoneLookup,
cp2DefaultDirectoryPhoneLookup,
cp2ExtendedDirectoryPhoneLookup,
diff --git a/java/com/android/dialer/phonelookup/cequint/CequintPhoneLookup.java b/java/com/android/dialer/phonelookup/cequint/CequintPhoneLookup.java
new file mode 100644
index 000000000..ce2cd18ad
--- /dev/null
+++ b/java/com/android/dialer/phonelookup/cequint/CequintPhoneLookup.java
@@ -0,0 +1,90 @@
+/*
+ * 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.phonelookup.cequint;
+
+import android.content.Context;
+import android.telecom.Call;
+import com.android.dialer.DialerPhoneNumber;
+import com.android.dialer.phonelookup.PhoneLookup;
+import com.android.dialer.phonelookup.PhoneLookupInfo;
+import com.android.dialer.phonelookup.PhoneLookupInfo.CequintInfo;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import javax.inject.Inject;
+
+/** PhoneLookup implementation for Cequint. */
+public class CequintPhoneLookup implements PhoneLookup<CequintInfo> {
+
+ @Inject
+ CequintPhoneLookup() {}
+
+ @Override
+ public ListenableFuture<CequintInfo> lookup(Context appContext, Call call) {
+ // TODO(a bug): Override the default implementation in the PhoneLookup interface
+ // as a Cequint lookup requires info in the provided call.
+ return Futures.immediateFuture(CequintInfo.getDefaultInstance());
+ }
+
+ @Override
+ public ListenableFuture<CequintInfo> lookup(DialerPhoneNumber dialerPhoneNumber) {
+ // TODO(a bug): Implement this method.
+ return Futures.immediateFuture(CequintInfo.getDefaultInstance());
+ }
+
+ @Override
+ public ListenableFuture<Boolean> isDirty(ImmutableSet<DialerPhoneNumber> phoneNumbers) {
+ return Futures.immediateFuture(false);
+ }
+
+ @Override
+ public ListenableFuture<ImmutableMap<DialerPhoneNumber, CequintInfo>> getMostRecentInfo(
+ ImmutableMap<DialerPhoneNumber, CequintInfo> existingInfoMap) {
+ return Futures.immediateFuture(existingInfoMap);
+ }
+
+ @Override
+ public void setSubMessage(PhoneLookupInfo.Builder destination, CequintInfo subMessage) {
+ destination.setCequintInfo(subMessage);
+ }
+
+ @Override
+ public CequintInfo getSubMessage(PhoneLookupInfo phoneLookupInfo) {
+ return phoneLookupInfo.getCequintInfo();
+ }
+
+ @Override
+ public ListenableFuture<Void> onSuccessfulBulkUpdate() {
+ return Futures.immediateFuture(null);
+ }
+
+ @Override
+ public void registerContentObservers() {
+ // No content observers for Cequint info.
+ }
+
+ @Override
+ public void unregisterContentObservers() {
+ // No content observers for Cequint info.
+ }
+
+ @Override
+ public ListenableFuture<Void> clearData() {
+ return Futures.immediateFuture(null);
+ }
+}
diff --git a/java/com/android/dialer/phonelookup/phone_lookup_info.proto b/java/com/android/dialer/phonelookup/phone_lookup_info.proto
index 1beff6ca9..50817c4e3 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: 8
+// Next ID: 9
message PhoneLookupInfo {
// Information about a PhoneNumber retrieved from CP2.
message Cp2Info {
@@ -163,4 +163,16 @@ message PhoneLookupInfo {
optional string name = 1;
}
optional CnapInfo cnap_info = 7;
+
+ // Information obtained via Cequint
+ // Next ID: 4
+ message CequintInfo {
+ optional string name = 1;
+
+ // Description of the geolocation (e.g., "Mountain View, CA")
+ optional string geolocation = 2;
+
+ optional string photo_uri = 3;
+ }
+ optional CequintInfo cequint_info = 8;
} \ No newline at end of file
diff --git a/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java b/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java
index 777175e00..4302436a7 100644
--- a/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java
+++ b/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java
@@ -625,16 +625,16 @@ public class ContactInfoHelper {
if (cequintCallerIdContact == null) {
return;
}
- if (TextUtils.isEmpty(info.name) && !TextUtils.isEmpty(cequintCallerIdContact.name)) {
- info.name = cequintCallerIdContact.name;
+ if (TextUtils.isEmpty(info.name) && !TextUtils.isEmpty(cequintCallerIdContact.name())) {
+ info.name = cequintCallerIdContact.name();
}
- if (!TextUtils.isEmpty(cequintCallerIdContact.geoDescription)) {
- info.geoDescription = cequintCallerIdContact.geoDescription;
+ if (!TextUtils.isEmpty(cequintCallerIdContact.geolocation())) {
+ info.geoDescription = cequintCallerIdContact.geolocation();
info.sourceType = ContactSource.Type.SOURCE_TYPE_CEQUINT_CALLER_ID;
}
// Only update photo if local lookup has no result.
- if (!info.contactExists && info.photoUri == null && cequintCallerIdContact.imageUrl != null) {
- info.photoUri = UriUtils.parseUriOrNull(cequintCallerIdContact.imageUrl);
+ if (!info.contactExists && info.photoUri == null && cequintCallerIdContact.photoUri() != null) {
+ info.photoUri = UriUtils.parseUriOrNull(cequintCallerIdContact.photoUri());
}
}
}
diff --git a/java/com/android/dialer/precall/impl/CallingAccountSelector.java b/java/com/android/dialer/precall/impl/CallingAccountSelector.java
index 16e7641ba..8f63fa0db 100644
--- a/java/com/android/dialer/precall/impl/CallingAccountSelector.java
+++ b/java/com/android/dialer/precall/impl/CallingAccountSelector.java
@@ -28,12 +28,15 @@ import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment;
import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment.SelectPhoneAccountListener;
+import com.android.contacts.common.widget.SelectPhoneAccountDialogOptions;
+import com.android.contacts.common.widget.SelectPhoneAccountDialogOptionsUtil;
+import com.android.dialer.activecalls.ActiveCallInfo;
+import com.android.dialer.activecalls.ActiveCallsComponent;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.configprovider.ConfigProviderBindings;
-import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.DialerImpression.Type;
import com.android.dialer.logging.Logger;
import com.android.dialer.precall.PreCallAction;
@@ -41,10 +44,13 @@ import com.android.dialer.precall.PreCallCoordinator;
import com.android.dialer.precall.PreCallCoordinator.PendingAction;
import com.android.dialer.preferredsim.PreferredAccountRecorder;
import com.android.dialer.preferredsim.PreferredAccountWorker;
+import com.android.dialer.preferredsim.PreferredAccountWorker.Result;
import com.android.dialer.preferredsim.suggestion.SuggestionProvider;
import com.android.dialer.preferredsim.suggestion.SuggestionProvider.Suggestion;
-import com.android.dialer.telecom.TelecomUtil;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
import java.util.List;
+import java.util.Objects;
/** PreCallAction to select which phone account to call with. Ignored if there's only one account */
@SuppressWarnings("MissingPermission")
@@ -75,17 +81,6 @@ public class CallingAccountSelector implements PreCallAction {
if (accounts.size() <= 1) {
return false;
}
-
- if (TelecomUtil.isInManagedCall(context)) {
- // Most devices are DSDS (dual SIM dual standby) which only one SIM can have active calls at
- // a time. Telecom will ignore the phone account handle and use the current active SIM, thus
- // there's no point of selecting SIMs
- // TODO(a bug): let the user know selections are not available and preferred SIM is not
- // used
- // TODO(twyen): support other dual SIM modes when the API is exposed.
- return false;
- }
-
return true;
}
@@ -134,12 +129,7 @@ public class CallingAccountSelector implements PreCallAction {
return;
}
if (result.getPhoneAccountHandle().isPresent()) {
- Logger.get(coordinator.getActivity())
- .logImpression(DialerImpression.Type.DUAL_SIM_SELECTION_PREFERRED_USED);
- coordinator
- .getBuilder()
- .setPhoneAccountHandle(result.getPhoneAccountHandle().get());
- pendingAction.finish();
+ usePreferredAccount(coordinator, pendingAction, result);
return;
}
PhoneAccountHandle defaultPhoneAccount =
@@ -147,10 +137,7 @@ public class CallingAccountSelector implements PreCallAction {
.getSystemService(TelecomManager.class)
.getDefaultOutgoingPhoneAccount(builder.getUri().getScheme());
if (defaultPhoneAccount != null) {
- Logger.get(coordinator.getActivity())
- .logImpression(DialerImpression.Type.DUAL_SIM_SELECTION_GLOBAL_USED);
- builder.setPhoneAccountHandle(defaultPhoneAccount);
- pendingAction.finish();
+ useDefaultAccount(coordinator, pendingAction, result, defaultPhoneAccount);
return;
}
if (result.getSuggestion().isPresent()) {
@@ -158,18 +145,7 @@ public class CallingAccountSelector implements PreCallAction {
"CallingAccountSelector.processPreferredAccount",
"SIM suggested: " + result.getSuggestion().get().reason);
if (result.getSuggestion().get().shouldAutoSelect) {
- Logger.get(coordinator.getActivity())
- .logImpression(
- DialerImpression.Type.DUAL_SIM_SELECTION_SUGGESTION_AUTO_SELECTED);
- LogUtil.i(
- "CallingAccountSelector.processPreferredAccount", "Auto selected suggestion");
- builder.setPhoneAccountHandle(result.getSuggestion().get().phoneAccountHandle);
- builder
- .getInCallUiIntentExtras()
- .putString(
- SuggestionProvider.EXTRA_SIM_SUGGESTION_REASON,
- result.getSuggestion().get().reason.name());
- pendingAction.finish();
+ useSuggestedAccount(coordinator, pendingAction, result);
return;
}
}
@@ -184,6 +160,120 @@ public class CallingAccountSelector implements PreCallAction {
.executeParallel(activity);
}
+ private void usePreferredAccount(
+ PreCallCoordinator coordinator, PendingAction pendingAction, Result result) {
+ String phoneNumber = coordinator.getBuilder().getUri().getSchemeSpecificPart();
+ if (isSelectable(coordinator.getActivity(), result.getPhoneAccountHandle().get())) {
+ Logger.get(coordinator.getActivity()).logImpression(Type.DUAL_SIM_SELECTION_PREFERRED_USED);
+ coordinator.getBuilder().setPhoneAccountHandle(result.getPhoneAccountHandle().get());
+ pendingAction.finish();
+ } else {
+ Logger.get(coordinator.getActivity())
+ .logImpression(Type.DUAL_SIM_SELECTION_PREFERRED_NOT_SELECTABLE);
+ LogUtil.i("CallingAccountSelector.usePreferredAccount", "preferred account not selectable");
+ showDialog(
+ coordinator,
+ pendingAction,
+ result.getDataId().orNull(),
+ phoneNumber,
+ result.getSuggestion().orNull());
+ }
+ }
+
+ private void useDefaultAccount(
+ PreCallCoordinator coordinator,
+ PendingAction pendingAction,
+ Result result,
+ PhoneAccountHandle defaultPhoneAccount) {
+ CallIntentBuilder builder = coordinator.getBuilder();
+ String phoneNumber = builder.getUri().getSchemeSpecificPart();
+ if (isSelectable(coordinator.getActivity(), defaultPhoneAccount)) {
+ Logger.get(coordinator.getActivity()).logImpression(Type.DUAL_SIM_SELECTION_GLOBAL_USED);
+ builder.setPhoneAccountHandle(defaultPhoneAccount);
+ pendingAction.finish();
+ } else {
+ Logger.get(coordinator.getActivity())
+ .logImpression(Type.DUAL_SIM_SELECTION_GLOBAL_NOT_SELECTABLE);
+ LogUtil.i("CallingAccountSelector.useDefaultAccount", "default account not selectable");
+ showDialog(
+ coordinator,
+ pendingAction,
+ result.getDataId().orNull(),
+ phoneNumber,
+ result.getSuggestion().orNull());
+ }
+ }
+
+ private void useSuggestedAccount(
+ PreCallCoordinator coordinator, PendingAction pendingAction, Result result) {
+ CallIntentBuilder builder = coordinator.getBuilder();
+ String phoneNumber = builder.getUri().getSchemeSpecificPart();
+ if (isSelectable(coordinator.getActivity(), result.getSuggestion().get().phoneAccountHandle)) {
+ Logger.get(coordinator.getActivity())
+ .logImpression(Type.DUAL_SIM_SELECTION_SUGGESTION_AUTO_SELECTED);
+ LogUtil.i("CallingAccountSelector.processPreferredAccount", "Auto selected suggestion");
+ builder.setPhoneAccountHandle(result.getSuggestion().get().phoneAccountHandle);
+ builder
+ .getInCallUiIntentExtras()
+ .putString(
+ SuggestionProvider.EXTRA_SIM_SUGGESTION_REASON,
+ result.getSuggestion().get().reason.name());
+ pendingAction.finish();
+ } else {
+ LogUtil.i("CallingAccountSelector.useSuggestedAccount", "suggested account not selectable");
+ Logger.get(coordinator.getActivity())
+ .logImpression(Type.DUAL_SIM_SELECTION_SUGGESTION_AUTO_NOT_SELECTABLE);
+ showDialog(
+ coordinator,
+ pendingAction,
+ result.getDataId().orNull(),
+ phoneNumber,
+ result.getSuggestion().orNull());
+ }
+ }
+
+ /**
+ * Most devices are DSDS (dual SIM dual standby) which only one SIM can have active calls at a
+ * time. TODO(twyen): support other dual SIM modes when the API is exposed.
+ */
+ private static boolean isSelectable(Context context, PhoneAccountHandle phoneAccountHandle) {
+ ImmutableList<ActiveCallInfo> activeCalls =
+ ActiveCallsComponent.get(context).activeCalls().getActiveCalls();
+ if (activeCalls.isEmpty()) {
+ return true;
+ }
+ for (ActiveCallInfo activeCall : activeCalls) {
+ if (Objects.equals(phoneAccountHandle, activeCall.phoneAccountHandle().orNull())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static Optional<String> getActiveCallLabel(Context context) {
+ ImmutableList<ActiveCallInfo> activeCalls =
+ ActiveCallsComponent.get(context).activeCalls().getActiveCalls();
+
+ if (activeCalls.isEmpty()) {
+ LogUtil.e("CallingAccountSelector.getActiveCallLabel", "active calls no longer exist");
+ return Optional.absent();
+ }
+ ActiveCallInfo activeCall = activeCalls.get(0);
+ if (!activeCall.phoneAccountHandle().isPresent()) {
+ LogUtil.e("CallingAccountSelector.getActiveCallLabel", "active call has no phone account");
+ return Optional.absent();
+ }
+ PhoneAccount phoneAccount =
+ context
+ .getSystemService(TelecomManager.class)
+ .getPhoneAccount(activeCall.phoneAccountHandle().get());
+ if (phoneAccount == null) {
+ LogUtil.e("CallingAccountSelector.getActiveCallLabel", "phone account not found");
+ return Optional.absent();
+ }
+ return Optional.of(phoneAccount.getLabel().toString());
+ }
+
@MainThread
private void showDialog(
PreCallCoordinator coordinator,
@@ -211,24 +301,47 @@ public class CallingAccountSelector implements PreCallAction {
default:
}
}
- List<PhoneAccountHandle> phoneAccountHandles =
+ SelectPhoneAccountDialogOptions.Builder optionsBuilder =
+ SelectPhoneAccountDialogOptions.newBuilder()
+ .setTitle(R.string.pre_call_select_phone_account)
+ .setCanSetDefault(dataId != null)
+ .setSetDefaultLabel(R.string.pre_call_select_phone_account_remember);
+
+ for (PhoneAccountHandle phoneAccountHandle :
coordinator
.getActivity()
.getSystemService(TelecomManager.class)
- .getCallCapablePhoneAccounts();
+ .getCallCapablePhoneAccounts()) {
+ SelectPhoneAccountDialogOptions.Entry.Builder entryBuilder =
+ SelectPhoneAccountDialogOptions.Entry.newBuilder();
+ SelectPhoneAccountDialogOptionsUtil.setPhoneAccountHandle(entryBuilder, phoneAccountHandle);
+ if (isSelectable(coordinator.getActivity(), phoneAccountHandle)) {
+ Optional<String> hint =
+ SuggestionProvider.getHint(coordinator.getActivity(), phoneAccountHandle, suggestion);
+ if (hint.isPresent()) {
+ entryBuilder.setHint(hint.get());
+ }
+ } else {
+ entryBuilder.setEnabled(false);
+ Optional<String> activeCallLabel = getActiveCallLabel(coordinator.getActivity());
+ if (activeCallLabel.isPresent()) {
+ entryBuilder.setHint(
+ coordinator
+ .getActivity()
+ .getString(
+ R.string.pre_call_select_phone_account_hint_other_sim_in_use,
+ activeCallLabel.get()));
+ }
+ }
+ optionsBuilder.addEntries(entryBuilder);
+ }
selectPhoneAccountDialogFragment =
SelectPhoneAccountDialogFragment.newInstance(
- R.string.pre_call_select_phone_account,
- dataId != null /* canSetDefault */,
- R.string.pre_call_select_phone_account_remember,
- phoneAccountHandles,
+ optionsBuilder.build(),
new SelectedListener(
coordinator,
pendingAction,
- new PreferredAccountRecorder(number, suggestion, dataId)),
- null /* call ID */,
- SuggestionProvider.buildHint(
- coordinator.getActivity(), phoneAccountHandles, suggestion));
+ new PreferredAccountRecorder(number, suggestion, dataId)));
selectPhoneAccountDialogFragment.show(
coordinator.getActivity().getFragmentManager(), TAG_CALLING_ACCOUNT_SELECTOR);
}
diff --git a/java/com/android/dialer/precall/impl/res/values/strings.xml b/java/com/android/dialer/precall/impl/res/values/strings.xml
index 4bd5d36f2..5e7ddd36c 100644
--- a/java/com/android/dialer/precall/impl/res/values/strings.xml
+++ b/java/com/android/dialer/precall/impl/res/values/strings.xml
@@ -14,7 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<resources>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Toast when the user tried to place a call but has revoked phone permission [CHAR_LIMIT=none] -->
<string name="pre_call_permission_check_no_phone_permission">Cannot make call without phone permission</string>
@@ -26,4 +26,8 @@
same contact and never ask again [CHAR LIMIT=40]-->
<string name="pre_call_select_phone_account_remember">Remember this choice</string>
+ <!-- Hint to show under a SIM entry when selecting SIM for call on a multi-SIM device, when the
+ call cannot be placed with the SIM because there is already a call on the other SIM,
+ [CHAR LIMIT=NONE]-->
+ <string name="pre_call_select_phone_account_hint_other_sim_in_use">Not available while using <xliff:g example="SIM 1" id="other_sim">%1$s</xliff:g></string>
</resources> \ No newline at end of file
diff --git a/java/com/android/dialer/preferredsim/suggestion/SuggestionProvider.java b/java/com/android/dialer/preferredsim/suggestion/SuggestionProvider.java
index f710f734c..50ae01fd0 100644
--- a/java/com/android/dialer/preferredsim/suggestion/SuggestionProvider.java
+++ b/java/com/android/dialer/preferredsim/suggestion/SuggestionProvider.java
@@ -24,10 +24,9 @@ import android.telecom.PhoneAccountHandle;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.google.common.base.Optional;
-import java.util.ArrayList;
-import java.util.List;
/** Provides hints to the user when selecting a SIM to make a call. */
+@SuppressWarnings("Guava")
public interface SuggestionProvider {
String EXTRA_SIM_SUGGESTION_REASON = "sim_suggestion_reason";
@@ -80,35 +79,25 @@ public interface SuggestionProvider {
@NonNull Context context, @NonNull String number, @NonNull PhoneAccountHandle newAccount);
/**
- * Return a list of suggestion strings matching the list position of the {@code
- * phoneAccountHandles}. The list will contain {@code null} if the PhoneAccountHandle does not
- * have suggestions.
+ * Return the hint for {@code phoneAccountHandle}. Absent if no hint is available for the account.
*/
- @Nullable
- static List<String> buildHint(
- Context context,
- List<PhoneAccountHandle> phoneAccountHandles,
- @Nullable Suggestion suggestion) {
+ static Optional<String> getHint(
+ Context context, PhoneAccountHandle phoneAccountHandle, @Nullable Suggestion suggestion) {
if (suggestion == null) {
- return null;
+ return Optional.absent();
}
- List<String> hints = new ArrayList<>();
- for (PhoneAccountHandle phoneAccountHandle : phoneAccountHandles) {
- if (!phoneAccountHandle.equals(suggestion.phoneAccountHandle)) {
- hints.add(null);
- continue;
- }
- switch (suggestion.reason) {
- case INTRA_CARRIER:
- hints.add(context.getString(R.string.pre_call_select_phone_account_hint_intra_carrier));
- break;
- case FREQUENT:
- hints.add(context.getString(R.string.pre_call_select_phone_account_hint_frequent));
- break;
- default:
- LogUtil.w("CallingAccountSelector.buildHint", "unhandled reason " + suggestion.reason);
- }
+ if (!phoneAccountHandle.equals(suggestion.phoneAccountHandle)) {
+ return Optional.absent();
+ }
+ switch (suggestion.reason) {
+ case INTRA_CARRIER:
+ return Optional.of(
+ context.getString(R.string.pre_call_select_phone_account_hint_intra_carrier));
+ case FREQUENT:
+ return Optional.of(context.getString(R.string.pre_call_select_phone_account_hint_frequent));
+ default:
+ LogUtil.w("CallingAccountSelector.getHint", "unhandled reason " + suggestion.reason);
+ return Optional.absent();
}
- return hints;
}
}
diff --git a/java/com/android/dialer/speeddial/SpeedDialAdapter.java b/java/com/android/dialer/speeddial/SpeedDialAdapter.java
index 6f6ac5498..8a37e97dd 100644
--- a/java/com/android/dialer/speeddial/SpeedDialAdapter.java
+++ b/java/com/android/dialer/speeddial/SpeedDialAdapter.java
@@ -210,4 +210,9 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi
public void setItemTouchHelper(ItemTouchHelper itemTouchHelper) {
this.itemTouchHelper = itemTouchHelper;
}
+
+ /** Returns true if there are suggested contacts. */
+ public boolean hasFrequents() {
+ return !speedDialUiItems.isEmpty() && getItemViewType(getItemCount() - 1) == RowType.SUGGESTION;
+ }
}
diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java
index 26893a8d3..b74c06239 100644
--- a/java/com/android/dialer/speeddial/SpeedDialFragment.java
+++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java
@@ -34,6 +34,7 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.common.FragmentUtils;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.common.concurrent.SupportUiListener;
@@ -132,11 +133,6 @@ public class SpeedDialFragment extends Fragment {
return rootLayout;
}
- public boolean hasFrequents() {
- // TODO(calderwoodra)
- return false;
- }
-
@Override
public void onResume() {
super.onResume();
@@ -173,12 +169,17 @@ public class SpeedDialFragment extends Fragment {
}
private void onSpeedDialUiItemListLoaded(ImmutableList<SpeedDialUiItem> speedDialUiItems) {
+ LogUtil.enterBlock("SpeedDialFragment.onSpeedDialUiItemListLoaded");
// TODO(calderwoodra): Use DiffUtil to properly update and animate the change
adapter.setSpeedDialUiItems(
UiItemLoaderComponent.get(getContext())
.speedDialUiItemLoader()
.insertDuoChannels(getContext(), speedDialUiItems));
adapter.notifyDataSetChanged();
+ if (getActivity() != null) {
+ FragmentUtils.getParentUnsafe(this, HostInterface.class)
+ .setHasFrequents(adapter.hasFrequents());
+ }
}
@Override
@@ -359,4 +360,10 @@ public class SpeedDialFragment extends Fragment {
Contacts.CONTENT_URI, String.valueOf(speedDialUiItem.contactId()))));
}
}
+
+ /** Interface for {@link SpeedDialFragment} to communicate with its host/parent. */
+ public interface HostInterface {
+
+ void setHasFrequents(boolean hasFrequents);
+ }
}
diff --git a/java/com/android/dialer/speeddial/database/SpeedDialEntryDao.java b/java/com/android/dialer/speeddial/database/SpeedDialEntryDao.java
index ce771c3c8..4d6ac2d7f 100644
--- a/java/com/android/dialer/speeddial/database/SpeedDialEntryDao.java
+++ b/java/com/android/dialer/speeddial/database/SpeedDialEntryDao.java
@@ -17,6 +17,7 @@
package com.android.dialer.speeddial.database;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
/**
* Interface that databases support speed dial entries should implement.
@@ -32,8 +33,10 @@ public interface SpeedDialEntryDao {
* Insert new entries.
*
* <p>{@link SpeedDialEntry#id() ids} must be null.
+ *
+ * @return a map of the inserted entries to their new ids.
*/
- void insert(ImmutableList<SpeedDialEntry> entries);
+ ImmutableMap<SpeedDialEntry, Long> insert(ImmutableList<SpeedDialEntry> entries);
/**
* Insert a new entry.
@@ -59,11 +62,12 @@ public interface SpeedDialEntryDao {
/**
* Inserts, updates and deletes rows all in on transaction.
*
+ * @return a map of the inserted entries to their new ids.
* @see #insert(ImmutableList)
* @see #update(ImmutableList)
* @see #delete(ImmutableList)
*/
- void insertUpdateAndDelete(
+ ImmutableMap<SpeedDialEntry, Long> insertUpdateAndDelete(
ImmutableList<SpeedDialEntry> entriesToInsert,
ImmutableList<SpeedDialEntry> entriesToUpdate,
ImmutableList<Long> entriesToDelete);
diff --git a/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java b/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java
index 137933fbe..544bb3613 100644
--- a/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java
+++ b/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java
@@ -26,6 +26,7 @@ import com.android.dialer.common.Assert;
import com.android.dialer.common.database.Selection;
import com.android.dialer.speeddial.database.SpeedDialEntry.Channel;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.List;
@@ -132,30 +133,39 @@ public final class SpeedDialEntryDatabaseHelper extends SQLiteOpenHelper
}
@Override
- public void insert(ImmutableList<SpeedDialEntry> entries) {
+ public ImmutableMap<SpeedDialEntry, Long> insert(ImmutableList<SpeedDialEntry> entries) {
if (entries.isEmpty()) {
- return;
+ return ImmutableMap.of();
}
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
- insert(db, entries);
+ ImmutableMap<SpeedDialEntry, Long> insertedEntriesToIdsMap = insert(db, entries);
db.setTransactionSuccessful();
+ return insertedEntriesToIdsMap;
} finally {
db.endTransaction();
db.close();
}
}
- private void insert(SQLiteDatabase writeableDatabase, ImmutableList<SpeedDialEntry> entries) {
+ private ImmutableMap<SpeedDialEntry, Long> insert(
+ SQLiteDatabase writeableDatabase, ImmutableList<SpeedDialEntry> entries) {
+ ImmutableMap.Builder<SpeedDialEntry, Long> insertedEntriesToIdsMap = ImmutableMap.builder();
for (SpeedDialEntry entry : entries) {
Assert.checkArgument(entry.id() == null);
- if (writeableDatabase.insert(TABLE_NAME, null, buildContentValuesWithoutId(entry)) == -1L) {
+ long id = writeableDatabase.insert(TABLE_NAME, null, buildContentValuesWithoutId(entry));
+ if (id == -1L) {
throw Assert.createUnsupportedOperationFailException(
"Attempted to insert a row that already exists.");
}
+ // It's impossible to insert two identical entries but this is an important assumption we need
+ // to verify because there's an assumption that each entry will correspond to exactly one id.
+ // ImmutableMap#put verifies this check for us.
+ insertedEntriesToIdsMap.put(entry, id);
}
+ return insertedEntriesToIdsMap.build();
}
@Override
@@ -255,20 +265,21 @@ public final class SpeedDialEntryDatabaseHelper extends SQLiteOpenHelper
}
@Override
- public void insertUpdateAndDelete(
+ public ImmutableMap<SpeedDialEntry, Long> insertUpdateAndDelete(
ImmutableList<SpeedDialEntry> entriesToInsert,
ImmutableList<SpeedDialEntry> entriesToUpdate,
ImmutableList<Long> entriesToDelete) {
if (entriesToInsert.isEmpty() && entriesToUpdate.isEmpty() && entriesToDelete.isEmpty()) {
- return;
+ return ImmutableMap.of();
}
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
- insert(db, entriesToInsert);
+ ImmutableMap<SpeedDialEntry, Long> insertedEntriesToIdsMap = insert(db, entriesToInsert);
update(db, entriesToUpdate);
delete(db, entriesToDelete);
db.setTransactionSuccessful();
+ return insertedEntriesToIdsMap;
} finally {
db.endTransaction();
db.close();
diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java
index 24bc776e7..9bda3fb31 100644
--- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java
+++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java
@@ -136,6 +136,15 @@ public abstract class SpeedDialUiItem {
return builder.build();
}
+ public SpeedDialEntry buildSpeedDialEntry() {
+ return SpeedDialEntry.builder()
+ .setId(speedDialEntryId())
+ .setLookupKey(lookupKey())
+ .setContactId(contactId())
+ .setDefaultChannel(defaultChannel())
+ .build();
+ }
+
/**
* Returns a video channel if there is exactly one video channel or the default channel is a video
* channel.
diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
index 7107706fe..921468773 100644
--- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
+++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
@@ -44,6 +44,7 @@ import com.android.dialer.speeddial.database.SpeedDialEntry.Channel;
import com.android.dialer.speeddial.database.SpeedDialEntryDao;
import com.android.dialer.speeddial.database.SpeedDialEntryDatabaseHelper;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import java.util.ArrayList;
@@ -146,13 +147,7 @@ public final class SpeedDialUiItemLoader {
}
// Insert a new entry into the SpeedDialEntry database
- getSpeedDialEntryDao()
- .insert(
- SpeedDialEntry.builder()
- .setLookupKey(item.lookupKey())
- .setContactId(item.contactId())
- .setDefaultChannel(item.defaultChannel())
- .build());
+ getSpeedDialEntryDao().insert(item.buildSpeedDialEntry());
}
return loadSpeedDialUiItemsInternal();
}
@@ -216,23 +211,55 @@ public final class SpeedDialUiItemLoader {
contact.toBuilder().setDefaultChannel(contact.channels().get(0)).build());
} else if (speedDialUiItems.stream().noneMatch(c -> c.contactId() == contact.contactId())) {
- entriesToInsert.add(
- SpeedDialEntry.builder()
- .setLookupKey(contact.lookupKey())
- .setContactId(contact.contactId())
- .setDefaultChannel(contact.defaultChannel())
- .build());
+ entriesToInsert.add(contact.buildSpeedDialEntry());
// These are our newly starred contacts
speedDialUiItems.add(contact);
}
}
- db.insertUpdateAndDelete(
- ImmutableList.copyOf(entriesToInsert),
- ImmutableList.copyOf(entriesToUpdate),
- ImmutableList.copyOf(entriesToDelete));
- return ImmutableList.copyOf(speedDialUiItems);
+ ImmutableMap<SpeedDialEntry, Long> insertedEntriesToIdsMap =
+ db.insertUpdateAndDelete(
+ ImmutableList.copyOf(entriesToInsert),
+ ImmutableList.copyOf(entriesToUpdate),
+ ImmutableList.copyOf(entriesToDelete));
+ return speedDialUiItemsWithUpdatedIds(speedDialUiItems, insertedEntriesToIdsMap);
+ }
+
+ /**
+ * Since newly starred contacts sometimes aren't in the SpeedDialEntry database, we couldn't set
+ * their ids when we created our initial list of {@link SpeedDialUiItem speedDialUiItems}. Now
+ * that we've inserted the entries into the database and we have their ids, build a new list of
+ * speedDialUiItems with the now known ids.
+ */
+ private ImmutableList<SpeedDialUiItem> speedDialUiItemsWithUpdatedIds(
+ List<SpeedDialUiItem> speedDialUiItems,
+ ImmutableMap<SpeedDialEntry, Long> insertedEntriesToIdsMap) {
+ if (insertedEntriesToIdsMap.isEmpty()) {
+ // There were no newly inserted entries, so all entries ids are set already.
+ return ImmutableList.copyOf(speedDialUiItems);
+ }
+
+ ImmutableList.Builder<SpeedDialUiItem> updatedItems = ImmutableList.builder();
+ for (SpeedDialUiItem speedDialUiItem : speedDialUiItems) {
+ SpeedDialEntry entry = speedDialUiItem.buildSpeedDialEntry();
+ if (insertedEntriesToIdsMap.containsKey(entry)) {
+ // Get the id for newly inserted entry, update our SpeedDialUiItem and add it to our list
+ Long id = Assert.isNotNull(insertedEntriesToIdsMap.get(entry));
+ updatedItems.add(speedDialUiItem.toBuilder().setSpeedDialEntryId(id).build());
+ continue;
+ }
+
+ // Starred contacts that aren't in the map, should already have speed dial entry ids.
+ // Non-starred contacts (suggestions) aren't in the speed dial entry database, so they
+ // shouldn't have speed dial entry ids.
+ Assert.checkArgument(
+ speedDialUiItem.isStarred() == (speedDialUiItem.speedDialEntryId() != null),
+ "Contact must be starred with a speed dial entry id, or not starred with no id "
+ + "(suggested contacts)");
+ updatedItems.add(speedDialUiItem);
+ }
+ return updatedItems.build();
}
/**
diff --git a/java/com/android/dialer/theme/res/color/dialer_primary_text_color.xml b/java/com/android/dialer/theme/res/color/dialer_primary_text_color.xml
new file mode 100644
index 000000000..347db41bc
--- /dev/null
+++ b/java/com/android/dialer/theme/res/color/dialer_primary_text_color.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+<!-- Primary text color in the Phone app -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@color/dialer_disabled_text_color"/>
+ <item android:color="#212121"/>
+</selector> \ No newline at end of file
diff --git a/java/com/android/dialer/theme/res/color/dialer_secondary_text_color.xml b/java/com/android/dialer/theme/res/color/dialer_secondary_text_color.xml
new file mode 100644
index 000000000..920b46792
--- /dev/null
+++ b/java/com/android/dialer/theme/res/color/dialer_secondary_text_color.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+<!-- Secondary text color in the Phone app -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@color/dialer_disabled_text_color"/>
+ <item android:color="#636363"/>
+</selector> \ No newline at end of file
diff --git a/java/com/android/dialer/theme/res/values/colors.xml b/java/com/android/dialer/theme/res/values/colors.xml
index e80fc4b30..2185d861c 100644
--- a/java/com/android/dialer/theme/res/values/colors.xml
+++ b/java/com/android/dialer/theme/res/values/colors.xml
@@ -36,15 +36,11 @@
<color name="dialer_secondary_color">#F50057</color>
- <!-- Primary text color in the Phone app -->
- <color name="dialer_primary_text_color">#333333</color>
<color name="dialer_primary_text_color_white">#ffffff</color>
<color name="dialer_edit_text_hint_color">#DE78909C</color>
- <!-- Secondary text color in the Phone app -->
- <color name="dialer_secondary_text_color">#636363</color>
<!-- 38% opacity -->
- <color name="dialer_secondary_text_color_hiden">#61000000</color>
+ <color name="dialer_disabled_text_color">#9E9E9E</color>
<color name="dialer_link_color">#2A56C6</color>