summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2018-04-04 01:43:18 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-04-04 01:43:18 +0000
commitd5408c9423f20bef650ca838ff66bb5ecf60f818 (patch)
treed71a3bf4606c11bcf0ce9f2dc2266b5533561c0b /java
parentc81fbd75f18621d7ce68c8df65cc468efe6ffe23 (diff)
parent01b782754418aa17dbb867591642b49e473e92b1 (diff)
Merge changes I28244a72,Ic984f958,I5dc2bed7,I1be427b3,I0220a342, ...
* changes: Remove reference to RTT system setting. Fix the button style of RTT request dialog. Don't deadlock in DialerDatabaseHelper. Fix NPE for details number Per linguists' request, increase CHAR_LIMIT of "Carrier video" from 30 to 31. Fix permission Handle missed calls for new call log in old peer. Separate calls with the video feature from others when coalescing rows in the new call log. Support placing Duo calls in the new UI's bottom sheet. Turn off component generating step of RootComponentGenerato and @DialerCompoennt. Delete related tests. Implement dialog for responding RTT request.
Diffstat (limited to 'java')
-rw-r--r--java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java2
-rw-r--r--java/com/android/dialer/calllog/database/Coalescer.java35
-rw-r--r--java/com/android/dialer/calllog/ui/menu/Modules.java12
-rw-r--r--java/com/android/dialer/calllogutils/res/values/strings.xml4
-rw-r--r--java/com/android/dialer/constants/ActivityRequestCodes.java6
-rw-r--r--java/com/android/dialer/database/DialerDatabaseHelper.java38
-rw-r--r--java/com/android/dialer/duo/PlaceDuoCallNotifier.java45
-rw-r--r--java/com/android/dialer/duo/PlaceDuoCallReceiver.java77
-rw-r--r--java/com/android/dialer/historyitemactions/DuoCallModule.java80
-rw-r--r--java/com/android/dialer/historyitemactions/IntentModule.java2
-rw-r--r--java/com/android/dialer/main/impl/MainActivity.java8
-rw-r--r--java/com/android/dialer/main/impl/OldMainActivityPeer.java58
-rw-r--r--java/com/android/dialer/main/impl/bottomnav/MissedCallCountObserver.java79
-rw-r--r--java/com/android/dialer/oem/AndroidManifest.xml4
-rw-r--r--java/com/android/dialer/rootcomponentgenerator/processor/MetadataGeneratingStep.java10
-rw-r--r--java/com/android/dialer/rootcomponentgenerator/processor/RootComponentGeneratingStep.java10
-rw-r--r--java/com/android/dialer/rootcomponentgenerator/processor/RootComponentProcessor.java1
-rw-r--r--java/com/android/dialer/telecom/TelecomUtil.java6
-rw-r--r--java/com/android/incallui/CallButtonPresenter.java2
-rw-r--r--java/com/android/incallui/InCallActivity.java8
-rw-r--r--java/com/android/incallui/InCallPresenter.java7
-rw-r--r--java/com/android/incallui/RttRequestDialogFragment.java149
-rw-r--r--java/com/android/incallui/call/CallList.java13
-rw-r--r--java/com/android/incallui/call/DialerCall.java8
-rw-r--r--java/com/android/incallui/call/DialerCallListener.java2
-rw-r--r--java/com/android/incallui/res/layout/frag_rtt_request_dialog.xml81
-rw-r--r--java/com/android/incallui/res/values/strings.xml15
-rw-r--r--java/com/android/incallui/rtt/impl/res/values/strings.xml2
28 files changed, 693 insertions, 71 deletions
diff --git a/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java b/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java
index 680424a78..bca4265b6 100644
--- a/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java
+++ b/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java
@@ -279,7 +279,7 @@ public class PhoneCallDetailsHelper
return;
}
- if (PhoneNumberUtils.isEmergencyNumber(details.number.toString())) {
+ if (PhoneNumberUtils.isEmergencyNumber(details.displayNumber)) {
views.nameView.setText(R.string.emergency_number);
views.nameView.setTextDirection(View.TEXT_DIRECTION_INHERIT);
return;
diff --git a/java/com/android/dialer/calllog/database/Coalescer.java b/java/com/android/dialer/calllog/database/Coalescer.java
index ed09eea68..6b1a9e1f5 100644
--- a/java/com/android/dialer/calllog/database/Coalescer.java
+++ b/java/com/android/dialer/calllog/database/Coalescer.java
@@ -18,6 +18,7 @@ package com.android.dialer.calllog.database;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.MatrixCursor;
+import android.provider.CallLog.Calls;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
import android.telecom.PhoneAccountHandle;
@@ -151,7 +152,6 @@ public class Coalescer {
TelecomUtil.composePhoneAccountHandle(
row2.getAsString(AnnotatedCallLog.PHONE_ACCOUNT_COMPONENT_NAME),
row2.getAsString(AnnotatedCallLog.PHONE_ACCOUNT_ID));
-
if (!Objects.equals(phoneAccount1, phoneAccount2)) {
return false;
}
@@ -161,7 +161,7 @@ public class Coalescer {
return false;
}
- if (!meetsAssistedDialingCriteria(row1, row2)) {
+ if (!meetsCallFeatureCriteria(row1, row2)) {
return false;
}
@@ -185,20 +185,25 @@ public class Coalescer {
}
/**
- * Returns a boolean indicating whether or not FEATURES_ASSISTED_DIALING is mutually exclusive
- * between two rows.
+ * Returns true if column {@link AnnotatedCallLog#FEATURES} of the two given rows indicate that
+ * they can be coalesced.
*/
- private static boolean meetsAssistedDialingCriteria(ContentValues row1, ContentValues row2) {
- int row1Assisted =
- row1.getAsInteger(AnnotatedCallLog.FEATURES)
- & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING;
- int row2Assisted =
- row2.getAsInteger(AnnotatedCallLog.FEATURES)
- & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING;
-
- // FEATURES_ASSISTED_DIALING should not be combined with calls that are
- // !FEATURES_ASSISTED_DIALING
- return row1Assisted == row2Assisted;
+ private static boolean meetsCallFeatureCriteria(ContentValues row1, ContentValues row2) {
+ int row1Features = row1.getAsInteger(AnnotatedCallLog.FEATURES);
+ int row2Features = row2.getAsInteger(AnnotatedCallLog.FEATURES);
+
+ // A row with FEATURES_ASSISTED_DIALING should not be combined with one without it.
+ if ((row1Features & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING)
+ != (row2Features & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING)) {
+ return false;
+ }
+
+ // A video call should not be combined with one that is not a video call.
+ if ((row1Features & Calls.FEATURES_VIDEO) != (row2Features & Calls.FEATURES_VIDEO)) {
+ return false;
+ }
+
+ return true;
}
/**
diff --git a/java/com/android/dialer/calllog/ui/menu/Modules.java b/java/com/android/dialer/calllog/ui/menu/Modules.java
index aeb69a7a8..e316f66b5 100644
--- a/java/com/android/dialer/calllog/ui/menu/Modules.java
+++ b/java/com/android/dialer/calllog/ui/menu/Modules.java
@@ -27,8 +27,10 @@ import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.calllog.model.CoalescedRow;
import com.android.dialer.calllogutils.CallLogEntryText;
import com.android.dialer.calllogutils.NumberAttributesConverter;
+import com.android.dialer.duo.DuoConstants;
import com.android.dialer.glidephotomanager.PhotoInfo;
import com.android.dialer.historyitemactions.DividerModule;
+import com.android.dialer.historyitemactions.DuoCallModule;
import com.android.dialer.historyitemactions.HistoryItemActionModule;
import com.android.dialer.historyitemactions.IntentModule;
import com.android.dialer.historyitemactions.SharedModules;
@@ -134,9 +136,15 @@ final class Modules {
// Add a video item if (1) the call log entry is for a video call, and (2) the call is not spam.
if ((row.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO
&& !row.getNumberAttributes().getIsSpam()) {
+ boolean isDuoCall =
+ DuoConstants.PHONE_ACCOUNT_COMPONENT_NAME
+ .flattenToString()
+ .equals(row.getPhoneAccountComponentName());
modules.add(
- IntentModule.newVideoCallModule(
- context, normalizedNumber, phoneAccountHandle, CallInitiationType.Type.CALL_LOG));
+ isDuoCall
+ ? new DuoCallModule(context, normalizedNumber, CallInitiationType.Type.CALL_LOG)
+ : IntentModule.newCarrierVideoCallModule(
+ context, normalizedNumber, phoneAccountHandle, CallInitiationType.Type.CALL_LOG));
}
// TODO(zachh): Also show video option if the call log entry is for an audio call but video
diff --git a/java/com/android/dialer/calllogutils/res/values/strings.xml b/java/com/android/dialer/calllogutils/res/values/strings.xml
index bc19ce22a..1c1f31446 100644
--- a/java/com/android/dialer/calllogutils/res/values/strings.xml
+++ b/java/com/android/dialer/calllogutils/res/values/strings.xml
@@ -131,7 +131,7 @@
<!-- String to be displayed to indicate in the call log that a call just now occurred. -->
<string name="just_now">Just now</string>
- <!-- Text to show in call log for a carrier video call. [CHAR LIMIT=30] -->
+ <!-- Text to show in call log for a carrier video call. [CHAR LIMIT=31] -->
<string name="new_call_log_carrier_video">Carrier video</string>
<!-- Text to show in call log for a duo video call. [CHAR LIMIT=30] -->
@@ -145,4 +145,4 @@
<!-- String used to display calls from spam numbers in the call log. [CHAR LIMIT=30] -->
<string name="new_call_log_secondary_spam">Spam</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/java/com/android/dialer/constants/ActivityRequestCodes.java b/java/com/android/dialer/constants/ActivityRequestCodes.java
index 66c38fa64..7fd619ba9 100644
--- a/java/com/android/dialer/constants/ActivityRequestCodes.java
+++ b/java/com/android/dialer/constants/ActivityRequestCodes.java
@@ -16,8 +16,6 @@
package com.android.dialer.constants;
-import com.android.dialer.duo.Duo;
-
/**
* Class containing {@link android.app.Activity#onActivityResult(int, int, android.content.Intent)}
* request codes.
@@ -32,7 +30,9 @@ public final class ActivityRequestCodes {
/** Request code for {@link com.android.dialer.callcomposer.CallComposerActivity} intent. */
public static final int DIALTACTS_CALL_COMPOSER = 2;
- /** Request code for {@link Duo#getIntent(android.content.Context, String)}. */
+ /**
+ * Request code for {@link com.android.dialer.duo.Duo#getIntent(android.content.Context, String)}.
+ */
public static final int DIALTACTS_DUO = 3;
/** Request code for {@link com.android.dialer.calldetails.OldCallDetailsActivity} intent. */
diff --git a/java/com/android/dialer/database/DialerDatabaseHelper.java b/java/com/android/dialer/database/DialerDatabaseHelper.java
index efff11ecc..b172d7039 100644
--- a/java/com/android/dialer/database/DialerDatabaseHelper.java
+++ b/java/com/android/dialer/database/DialerDatabaseHelper.java
@@ -32,21 +32,23 @@ import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Directory;
-import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
import android.text.TextUtils;
import com.android.contacts.common.R;
import com.android.contacts.common.util.StopWatch;
import com.android.dialer.common.LogUtil;
-import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import com.android.dialer.common.concurrent.DefaultFutureCallback;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.common.concurrent.DialerFutureSerializer;
import com.android.dialer.common.database.Selection;
import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
import com.android.dialer.smartdial.util.SmartDialNameMatcher;
import com.android.dialer.smartdial.util.SmartDialPrefix;
import com.android.dialer.util.PermissionsUtil;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Objects;
@@ -85,6 +87,8 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
private static final int MAX_ENTRIES = 20;
private final Context context;
+ private final DialerFutureSerializer dialerFutureSerializer = new DialerFutureSerializer();
+
private boolean isTestInstance = false;
protected DialerDatabaseHelper(Context context, String databaseName, int dbVersion) {
@@ -344,11 +348,19 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
*/
public void startSmartDialUpdateThread(boolean forceUpdate) {
if (PermissionsUtil.hasContactsReadPermissions(context)) {
- DialerExecutorComponent.get(context)
- .dialerExecutorFactory()
- .createNonUiTaskBuilder(new UpdateSmartDialWorker())
- .build()
- .executeParallel(forceUpdate);
+ Futures.addCallback(
+ // Serialize calls to updateSmartDialDatabase. Use FutureSerializer instead of
+ // synchronizing on the method to prevent deadlocking thread pool. FutureSerializer
+ // provides the guarantee that the next AsyncCallable won't even be submitted until the
+ // ListenableFuture returned by the previous one completes. See a bug.
+ dialerFutureSerializer.submit(
+ () -> {
+ updateSmartDialDatabase(forceUpdate);
+ return null;
+ },
+ DialerExecutorComponent.get(context).backgroundExecutor()),
+ new DefaultFutureCallback<>(),
+ MoreExecutors.directExecutor());
}
}
@@ -657,7 +669,7 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
* @param forceUpdate If set to true, update the database by reloading all contacts.
*/
@WorkerThread
- public synchronized void updateSmartDialDatabase(boolean forceUpdate) {
+ public void updateSmartDialDatabase(boolean forceUpdate) {
LogUtil.enterBlock("DialerDatabaseHelper.updateSmartDialDatabase");
final SQLiteDatabase db = getWritableDatabase();
@@ -1296,14 +1308,4 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
return false;
}
}
-
- private class UpdateSmartDialWorker implements Worker<Boolean, Void> {
-
- @Nullable
- @Override
- public Void doInBackground(Boolean forceUpdate) throws Throwable {
- updateSmartDialDatabase(forceUpdate);
- return null;
- }
- }
}
diff --git a/java/com/android/dialer/duo/PlaceDuoCallNotifier.java b/java/com/android/dialer/duo/PlaceDuoCallNotifier.java
new file mode 100644
index 000000000..8fde981a0
--- /dev/null
+++ b/java/com/android/dialer/duo/PlaceDuoCallNotifier.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.duo;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v4.content.LocalBroadcastManager;
+import com.android.dialer.common.LogUtil;
+
+/** Notifies that a Duo video call should be started. */
+public final class PlaceDuoCallNotifier {
+
+ private PlaceDuoCallNotifier() {}
+
+ /**
+ * Broadcasts an intent notifying that a Duo call should be started.
+ *
+ * <p>See {@link PlaceDuoCallReceiver} for how the intent is handled.
+ *
+ * @param phoneNumber The number to start a Duo call. It can be of any format.
+ */
+ public static void notify(Context context, String phoneNumber) {
+ LogUtil.enterBlock("PlaceDuoCallNotifier.notify");
+
+ Intent intent = new Intent();
+ intent.setAction(PlaceDuoCallReceiver.ACTION_START_DUO_CALL);
+ intent.putExtra(PlaceDuoCallReceiver.EXTRA_PHONE_NUMBER, phoneNumber);
+
+ LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
+ }
+}
diff --git a/java/com/android/dialer/duo/PlaceDuoCallReceiver.java b/java/com/android/dialer/duo/PlaceDuoCallReceiver.java
new file mode 100644
index 000000000..913132c88
--- /dev/null
+++ b/java/com/android/dialer/duo/PlaceDuoCallReceiver.java
@@ -0,0 +1,77 @@
+/*
+ * 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.duo;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.constants.ActivityRequestCodes;
+
+/** A {@link BroadcastReceiver} that starts a Duo video call. */
+public final class PlaceDuoCallReceiver extends BroadcastReceiver {
+
+ static final String ACTION_START_DUO_CALL = "start_duo_call";
+ static final String EXTRA_PHONE_NUMBER = "phone_number";
+
+ /**
+ * {@link Activity} needed to launch Duo.
+ *
+ * <p>A Duo call can only be placed via {@link Activity#startActivityForResult(Intent, int)}.
+ */
+ private final Activity activity;
+
+ /** Returns an {@link IntentFilter} containing all actions accepted by this broadcast receiver. */
+ public static IntentFilter getIntentFilter() {
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_START_DUO_CALL);
+ return intentFilter;
+ }
+
+ public PlaceDuoCallReceiver(Activity activity) {
+ this.activity = activity;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ LogUtil.enterBlock("PlaceDuoCallReceiver.onReceive");
+
+ String action = intent.getAction();
+
+ switch (Assert.isNotNull(action)) {
+ case ACTION_START_DUO_CALL:
+ startDuoCall(context, intent);
+ break;
+ default:
+ throw new IllegalStateException("Unsupported action: " + action);
+ }
+ }
+
+ private void startDuoCall(Context context, Intent intent) {
+ LogUtil.enterBlock("PlaceDuoCallReceiver.startDuoCall");
+
+ Assert.checkArgument(intent.hasExtra(EXTRA_PHONE_NUMBER));
+ String phoneNumber = intent.getStringExtra(EXTRA_PHONE_NUMBER);
+
+ Duo duo = DuoComponent.get(context).getDuo();
+ activity.startActivityForResult(
+ duo.getIntent(context, phoneNumber), ActivityRequestCodes.DIALTACTS_DUO);
+ }
+}
diff --git a/java/com/android/dialer/historyitemactions/DuoCallModule.java b/java/com/android/dialer/historyitemactions/DuoCallModule.java
new file mode 100644
index 000000000..b0d6a11fc
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/DuoCallModule.java
@@ -0,0 +1,80 @@
+/*
+ * 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.historyitemactions;
+
+import android.Manifest.permission;
+import android.content.Context;
+import android.support.annotation.RequiresPermission;
+import com.android.dialer.callintent.CallInitiationType;
+import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.duo.Duo;
+import com.android.dialer.duo.DuoComponent;
+import com.android.dialer.duo.PlaceDuoCallNotifier;
+import com.android.dialer.precall.PreCall;
+
+/** {@link HistoryItemActionModule} for making a Duo call. */
+public class DuoCallModule implements HistoryItemActionModule {
+
+ private final Context context;
+ private final String phoneNumber;
+ private final CallInitiationType.Type callInitiationType;
+
+ /**
+ * Creates a module for making a Duo call.
+ *
+ * @param phoneNumber The number to start a Duo call. It can be of any format.
+ */
+ public DuoCallModule(
+ Context context, String phoneNumber, CallInitiationType.Type callInitiationType) {
+ this.context = context;
+ this.phoneNumber = phoneNumber;
+ this.callInitiationType = callInitiationType;
+ }
+
+ @Override
+ public int getStringId() {
+ return R.string.video_call;
+ }
+
+ @Override
+ public int getDrawableId() {
+ return R.drawable.quantum_ic_videocam_vd_white_24;
+ }
+
+ @Override
+ @RequiresPermission(permission.READ_PHONE_STATE)
+ public boolean onClick() {
+ if (canPlaceDuoCall(context, phoneNumber)) {
+ PlaceDuoCallNotifier.notify(context, phoneNumber);
+ } else {
+ // If a Duo call can't be placed, fall back to an IMS video call.
+ PreCall.start(
+ context, new CallIntentBuilder(phoneNumber, callInitiationType).setIsVideoCall(true));
+ }
+
+ return true; // Close the bottom sheet.
+ }
+
+ private boolean canPlaceDuoCall(Context context, String phoneNumber) {
+ Duo duo = DuoComponent.get(context).getDuo();
+
+ return duo.isInstalled(context)
+ && duo.isEnabled(context)
+ && duo.isActivated(context)
+ && duo.isReachable(context, phoneNumber);
+ }
+}
diff --git a/java/com/android/dialer/historyitemactions/IntentModule.java b/java/com/android/dialer/historyitemactions/IntentModule.java
index efb10e8bb..a5236c57a 100644
--- a/java/com/android/dialer/historyitemactions/IntentModule.java
+++ b/java/com/android/dialer/historyitemactions/IntentModule.java
@@ -77,7 +77,7 @@ public class IntentModule implements HistoryItemActionModule {
R.drawable.quantum_ic_call_white_24);
}
- public static IntentModule newVideoCallModule(
+ public static IntentModule newCarrierVideoCallModule(
Context context,
String number,
@Nullable PhoneAccountHandle phoneAccountHandle,
diff --git a/java/com/android/dialer/main/impl/MainActivity.java b/java/com/android/dialer/main/impl/MainActivity.java
index 2046b048f..3f660f56c 100644
--- a/java/com/android/dialer/main/impl/MainActivity.java
+++ b/java/com/android/dialer/main/impl/MainActivity.java
@@ -24,6 +24,7 @@ import com.android.dialer.blockreportspam.ShowBlockReportSpamDialogReceiver;
import com.android.dialer.calllog.config.CallLogConfigComponent;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.duo.PlaceDuoCallReceiver;
import com.android.dialer.interactions.PhoneNumberInteraction.DisambigDialogDismissedListener;
import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorCode;
import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorListener;
@@ -47,6 +48,9 @@ public class MainActivity extends TransactionSafeActivity
*/
private ShowBlockReportSpamDialogReceiver showBlockReportSpamDialogReceiver;
+ /** {@link android.content.BroadcastReceiver} that starts a Duo call. */
+ private PlaceDuoCallReceiver placeDuoCallReceiver;
+
public static Intent getShowCallLogIntent(Context context) {
return getShowTabIntent(context, TabIndex.CALL_LOG);
}
@@ -79,6 +83,7 @@ public class MainActivity extends TransactionSafeActivity
activePeer.onActivityCreate(savedInstanceState);
showBlockReportSpamDialogReceiver = new ShowBlockReportSpamDialogReceiver(getFragmentManager());
+ placeDuoCallReceiver = new PlaceDuoCallReceiver(/* activity = */ this);
}
protected MainActivityPeer getNewPeer() {
@@ -104,6 +109,8 @@ public class MainActivity extends TransactionSafeActivity
LocalBroadcastManager.getInstance(this)
.registerReceiver(
showBlockReportSpamDialogReceiver, ShowBlockReportSpamDialogReceiver.getIntentFilter());
+ LocalBroadcastManager.getInstance(this)
+ .registerReceiver(placeDuoCallReceiver, PlaceDuoCallReceiver.getIntentFilter());
}
@Override
@@ -118,6 +125,7 @@ public class MainActivity extends TransactionSafeActivity
activePeer.onActivityPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(showBlockReportSpamDialogReceiver);
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(placeDuoCallReceiver);
}
@Override
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index 6d78a5171..c15d7c1a8 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -68,10 +68,12 @@ import com.android.dialer.callcomposer.CallComposerActivity;
import com.android.dialer.calldetails.OldCallDetailsActivity;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.callintent.CallSpecificAppData;
+import com.android.dialer.calllog.CallLogComponent;
import com.android.dialer.calllog.config.CallLogConfigComponent;
import com.android.dialer.calllog.ui.NewCallLogFragment;
import com.android.dialer.common.FragmentUtils.FragmentUtilListener;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DefaultFutureCallback;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.common.concurrent.UiListener;
@@ -96,6 +98,7 @@ 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.main.impl.bottomnav.MissedCallCountObserver;
import com.android.dialer.main.impl.toolbar.MainToolbar;
import com.android.dialer.metrics.Metrics;
import com.android.dialer.metrics.MetricsComponent;
@@ -113,7 +116,9 @@ import com.android.dialer.voicemail.listui.error.VoicemailStatusCorruptionHandle
import com.android.dialer.voicemailstatus.VisualVoicemailEnabledChecker;
import com.android.dialer.voicemailstatus.VoicemailStatusHelper;
import com.android.voicemail.VoicemailComponent;
+import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
@@ -184,7 +189,9 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
private BottomNavBar bottomNav;
private MainBottomNavBarBottomNavTabListener bottomNavTabListener;
private View snackbarContainer;
+ private MissedCallCountObserver missedCallCountObserver;
private UiListener<String> getLastOutgoingCallListener;
+ private UiListener<Integer> missedCallObserverUiListener;
public static Intent getShowTabIntent(Context context, @TabIndex int tabIndex) {
Intent intent = new Intent(context, MainActivity.class);
@@ -219,6 +226,9 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
getLastOutgoingCallListener =
DialerExecutorComponent.get(activity)
.createUiListener(activity.getFragmentManager(), "Query last phone number");
+ missedCallObserverUiListener =
+ DialerExecutorComponent.get(activity)
+ .createUiListener(activity.getFragmentManager(), "Missed call observer");
}
private void initLayout(Bundle savedInstanceState) {
@@ -247,9 +257,13 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
boolean showVoicemailTab = canVoicemailTabBeShown(activity);
bottomNav.showVoicemail(showVoicemailTab);
+ missedCallCountObserver =
+ new MissedCallCountObserver(
+ activity.getApplicationContext(), bottomNav, missedCallObserverUiListener);
+
callLogFragmentListener =
new MainCallLogFragmentListener(
- activity, activity.getContentResolver(), bottomNav, toolbar);
+ activity, activity.getContentResolver(), bottomNav, toolbar, bottomNavTabListener);
bottomNav.addOnTabSelectedListener(callLogFragmentListener);
searchController =
@@ -471,6 +485,13 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
*/
bottomNavTabListener.ensureCorrectCallLogShown();
+ if (bottomNavTabListener.newCallLogFragmentActive()) {
+ missedCallCountObserver.onChange(false); // Set the initial value for the badge
+ activity
+ .getContentResolver()
+ .registerContentObserver(Calls.CONTENT_URI, true, missedCallCountObserver);
+ }
+
// add 1 sec delay to get memory snapshot so that dialer wont react slowly on resume.
ThreadUtil.postDelayedOnUiThread(
() ->
@@ -489,6 +510,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
public void onActivityPause() {
searchController.onActivityPause();
LocalBroadcastManager.getInstance(activity).unregisterReceiver(disableNewCallLogReceiver);
+ activity.getContentResolver().unregisterContentObserver(missedCallCountObserver);
}
@Override
@@ -819,6 +841,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
private final Context context;
private final BottomNavBar bottomNavBar;
private final Toolbar toolbar;
+ private final MainBottomNavBarBottomNavTabListener bottomNavTabListener;
private @TabIndex int currentTab = TabIndex.SPEED_DIAL;
private long timeSelected = -1;
@@ -837,11 +860,13 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
Context context,
ContentResolver contentResolver,
BottomNavBar bottomNavBar,
- Toolbar toolbar) {
+ Toolbar toolbar,
+ MainBottomNavBarBottomNavTabListener bottomNavTabListener) {
callLogQueryHandler = new CallLogQueryHandler(context, contentResolver, this);
this.context = context;
this.bottomNavBar = bottomNavBar;
this.toolbar = toolbar;
+ this.bottomNavTabListener = bottomNavTabListener;
}
private void registerVoicemailStatusContentObserver(Context context) {
@@ -953,8 +978,15 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
}
private void markMissedCallsAsReadAndRemoveNotification() {
- callLogQueryHandler.markMissedCallsAsRead();
- CallLogNotificationsService.cancelAllMissedCalls(context);
+ if (bottomNavTabListener.newCallLogFragmentActive()) {
+ Futures.addCallback(
+ CallLogComponent.get(context).getClearMissedCalls().clearAll(),
+ new DefaultFutureCallback<>(),
+ MoreExecutors.directExecutor());
+ } else {
+ callLogQueryHandler.markMissedCallsAsRead();
+ CallLogNotificationsService.cancelAllMissedCalls(context);
+ }
}
private void setCurrentTab(@TabIndex int tabIndex) {
@@ -969,7 +1001,9 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
activityIsAlive = true;
registerVoicemailStatusContentObserver(context);
callLogQueryHandler.fetchVoicemailStatus();
- callLogQueryHandler.fetchMissedCallsUnreadCount();
+ if (!bottomNavTabListener.newCallLogFragmentActive()) {
+ callLogQueryHandler.fetchMissedCallsUnreadCount();
+ }
// Reset the tab on resume to restart the timer
setCurrentTab(bottomNavBar.getSelectedTab());
}
@@ -978,7 +1012,11 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
public void onActivityStop(boolean changingConfigurations, boolean keyguardLocked) {
context.getContentResolver().unregisterContentObserver(voicemailStatusObserver);
activityIsAlive = false;
- if (viewedCallLogTabPastTimeThreshold() && !changingConfigurations && !keyguardLocked) {
+ // The new call log fragment handles this on its own.
+ if (!bottomNavTabListener.newCallLogFragmentActive()
+ && viewedCallLogTabPastTimeThreshold()
+ && !changingConfigurations
+ && !keyguardLocked) {
markMissedCallsAsReadAndRemoveNotification();
}
}
@@ -1239,6 +1277,14 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
}
}
+ boolean newCallLogFragmentActive() {
+ return supportFragmentManager.findFragmentByTag(CALL_LOG_TAG) != null
+ || (fragmentManager.findFragmentByTag(CALL_LOG_TAG) == null
+ && CallLogConfigComponent.get(activity)
+ .callLogConfig()
+ .isNewCallLogFragmentEnabled());
+ }
+
@Override
public void onContactsSelected() {
LogUtil.enterBlock("MainBottomNavBarBottomNavTabListener.onContactsSelected");
diff --git a/java/com/android/dialer/main/impl/bottomnav/MissedCallCountObserver.java b/java/com/android/dialer/main/impl/bottomnav/MissedCallCountObserver.java
new file mode 100644
index 000000000..276063474
--- /dev/null
+++ b/java/com/android/dialer/main/impl/bottomnav/MissedCallCountObserver.java
@@ -0,0 +1,79 @@
+/*
+ * 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.main.impl.bottomnav;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.provider.CallLog.Calls;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.common.concurrent.UiListener;
+import com.android.dialer.main.impl.bottomnav.BottomNavBar.TabIndex;
+import com.android.dialer.util.PermissionsUtil;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Observes the call log and updates the badge count to show the number of unread missed calls.
+ *
+ * <p>Used only when the new call log fragment is enabled.
+ */
+public final class MissedCallCountObserver extends ContentObserver {
+ private final Context appContext;
+ private final BottomNavBar bottomNavBar;
+ private final UiListener<Integer> uiListener;
+
+ public MissedCallCountObserver(
+ Context appContext, BottomNavBar bottomNavBar, UiListener<Integer> uiListener) {
+ super(null);
+ this.appContext = appContext;
+ this.bottomNavBar = bottomNavBar;
+ this.uiListener = uiListener;
+ }
+
+ @SuppressLint("MissingPermission")
+ @Override
+ public void onChange(boolean selfChange) {
+ ListenableFuture<Integer> countFuture =
+ DialerExecutorComponent.get(appContext)
+ .backgroundExecutor()
+ .submit(
+ () -> {
+ if (!PermissionsUtil.hasCallLogReadPermissions(appContext)) {
+ return 0;
+ }
+ try (Cursor cursor =
+ appContext
+ .getContentResolver()
+ .query(
+ Calls.CONTENT_URI,
+ new String[] {Calls._ID},
+ Calls.IS_READ + " = ? AND " + Calls.TYPE + " = ?",
+ new String[] {"0", Integer.toString(Calls.MISSED_TYPE)},
+ /* sortOrder= */ null)) {
+ return cursor == null ? 0 : cursor.getCount();
+ }
+ });
+ uiListener.listen(
+ appContext,
+ countFuture,
+ count -> bottomNavBar.setNotificationCount(TabIndex.CALL_LOG, count == null ? 0 : count),
+ throwable -> {
+ throw new RuntimeException(throwable);
+ });
+ }
+}
diff --git a/java/com/android/dialer/oem/AndroidManifest.xml b/java/com/android/dialer/oem/AndroidManifest.xml
index a781521c6..94cd4fcba 100644
--- a/java/com/android/dialer/oem/AndroidManifest.xml
+++ b/java/com/android/dialer/oem/AndroidManifest.xml
@@ -19,5 +19,5 @@
<uses-permission android:name="com.cequint.ecid.CALLER_ID_LOOKUP"/>
<!-- This is used by MotorolaInCallUiNotifier to send broadcasts. -->
- <uses-permission android:name="com.motorola.incallui.action.INCOMING_CALL_VISIBILITY_CHANGED"/>
-</manifest> \ No newline at end of file
+ <uses-permission android:name="com.motorola.incallui.permission.INCOMING_CALL_VISIBILITY_CHANGED"/>
+</manifest>
diff --git a/java/com/android/dialer/rootcomponentgenerator/processor/MetadataGeneratingStep.java b/java/com/android/dialer/rootcomponentgenerator/processor/MetadataGeneratingStep.java
index 70ad1b2e7..b7d31c0e9 100644
--- a/java/com/android/dialer/rootcomponentgenerator/processor/MetadataGeneratingStep.java
+++ b/java/com/android/dialer/rootcomponentgenerator/processor/MetadataGeneratingStep.java
@@ -18,7 +18,6 @@ package com.android.dialer.rootcomponentgenerator.processor;
import static javax.tools.Diagnostic.Kind.ERROR;
-import com.android.dialer.rootcomponentgenerator.annotation.DialerComponent;
import com.android.dialer.rootcomponentgenerator.annotation.InstallIn;
import com.android.dialer.rootcomponentgenerator.annotation.RootComponentGeneratorMetadata;
import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
@@ -26,6 +25,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.SetMultimap;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.TypeSpec;
+import dagger.Subcomponent;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.Set;
@@ -33,7 +33,7 @@ import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
/**
- * Genereates metadata for every type annotated by {@link InstallIn} and {@link DialerComponent}.
+ * Genereates metadata for every type annotated by {@link InstallIn} and {@link Subcomponent}.
*
* <p>The metadata has the information where the annotated types are and it is used by annotation
* processor when the processor tries to generate root component.
@@ -48,15 +48,15 @@ final class MetadataGeneratingStep implements ProcessingStep {
@Override
public Set<? extends Class<? extends Annotation>> annotations() {
- return ImmutableSet.of(DialerComponent.class, InstallIn.class);
+ return ImmutableSet.of(Subcomponent.class, InstallIn.class);
}
@Override
public Set<? extends Element> process(
SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
- for (Element element : elementsByAnnotation.get(DialerComponent.class)) {
- generateMetadataFor(DialerComponent.class, element);
+ for (Element element : elementsByAnnotation.get(Subcomponent.class)) {
+ generateMetadataFor(Subcomponent.class, element);
}
for (Element element : elementsByAnnotation.get(InstallIn.class)) {
if (element.getAnnotation(InstallIn.class).variants().length == 0) {
diff --git a/java/com/android/dialer/rootcomponentgenerator/processor/RootComponentGeneratingStep.java b/java/com/android/dialer/rootcomponentgenerator/processor/RootComponentGeneratingStep.java
index 86a030856..9b97adafd 100644
--- a/java/com/android/dialer/rootcomponentgenerator/processor/RootComponentGeneratingStep.java
+++ b/java/com/android/dialer/rootcomponentgenerator/processor/RootComponentGeneratingStep.java
@@ -20,7 +20,6 @@ import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
import static com.google.auto.common.MoreElements.getAnnotationMirror;
import static com.google.auto.common.MoreElements.isAnnotationPresent;
-import com.android.dialer.rootcomponentgenerator.annotation.DialerComponent;
import com.android.dialer.rootcomponentgenerator.annotation.DialerRootComponent;
import com.android.dialer.rootcomponentgenerator.annotation.DialerVariant;
import com.android.dialer.rootcomponentgenerator.annotation.InstallIn;
@@ -36,6 +35,7 @@ import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.TypeSpec;
import dagger.Component;
+import dagger.Subcomponent;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
@@ -90,11 +90,7 @@ final class RootComponentGeneratingStep implements ProcessingStep {
.addAnnotation(Singleton.class);
for (TypeElement componentWithSuperInterface : componentList) {
rootComponentClassBuilder.addSuperinterface(
- ClassName.get(componentWithSuperInterface)
- .peerClass(
- RootComponentUtils.GENERATED_COMPONENT_PREFIX
- + componentWithSuperInterface.getSimpleName())
- .nestedClass("HasComponent"));
+ ClassName.get(componentWithSuperInterface).nestedClass("HasComponent"));
}
AnnotationSpec.Builder componentAnnotation = AnnotationSpec.builder(Component.class);
for (TypeElement annotatedElement : componentModuleMap.get(dialerVariant)) {
@@ -108,7 +104,7 @@ final class RootComponentGeneratingStep implements ProcessingStep {
private List<TypeElement> generateComponentList() {
List<TypeElement> list = new ArrayList<>();
- extractInfoFromMetadata(DialerComponent.class, list::add);
+ extractInfoFromMetadata(Subcomponent.class, list::add);
return list;
}
diff --git a/java/com/android/dialer/rootcomponentgenerator/processor/RootComponentProcessor.java b/java/com/android/dialer/rootcomponentgenerator/processor/RootComponentProcessor.java
index 5e083d29d..56caa9ea4 100644
--- a/java/com/android/dialer/rootcomponentgenerator/processor/RootComponentProcessor.java
+++ b/java/com/android/dialer/rootcomponentgenerator/processor/RootComponentProcessor.java
@@ -29,7 +29,6 @@ public class RootComponentProcessor extends BasicAnnotationProcessor {
@Override
protected Iterable<? extends ProcessingStep> initSteps() {
return ImmutableList.of(
- new ComponentGeneratingStep(processingEnv),
new MetadataGeneratingStep(processingEnv),
new RootComponentGeneratingStep(processingEnv));
}
diff --git a/java/com/android/dialer/telecom/TelecomUtil.java b/java/com/android/dialer/telecom/TelecomUtil.java
index f05ec202d..2608cb2aa 100644
--- a/java/com/android/dialer/telecom/TelecomUtil.java
+++ b/java/com/android/dialer/telecom/TelecomUtil.java
@@ -26,7 +26,6 @@ import android.net.Uri;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.provider.CallLog.Calls;
-import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresPermission;
@@ -300,11 +299,6 @@ public abstract class TelecomUtil {
return instance.isDefaultDialer(context);
}
- public static boolean isRttEnabled(Context context) {
- return Settings.System.getInt(context.getContentResolver(), Settings.System.RTT_CALLING_MODE, 0)
- != 0;
- }
-
/** @return the other SIM based PhoneAccountHandle that is not {@code currentAccount} */
@Nullable
@RequiresPermission(permission.READ_PHONE_STATE)
diff --git a/java/com/android/incallui/CallButtonPresenter.java b/java/com/android/incallui/CallButtonPresenter.java
index 38c8da898..833460398 100644
--- a/java/com/android/incallui/CallButtonPresenter.java
+++ b/java/com/android/incallui/CallButtonPresenter.java
@@ -479,7 +479,7 @@ public class CallButtonPresenter
// Most devices cannot make calls on 2 SIMs at the same time.
&& InCallPresenter.getInstance().getCallList().getAllCalls().size() == 1;
- boolean showUpgradeToRtt = TelecomUtil.isRttEnabled(context) && call.canUpgradeToRttCall();
+ boolean showUpgradeToRtt = call.canUpgradeToRttCall();
inCallButtonUi.showButton(InCallButtonIds.BUTTON_AUDIO, true);
inCallButtonUi.showButton(InCallButtonIds.BUTTON_SWAP, showSwap);
diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java
index 1ba3683f0..65ef323fe 100644
--- a/java/com/android/incallui/InCallActivity.java
+++ b/java/com/android/incallui/InCallActivity.java
@@ -35,6 +35,7 @@ import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
+import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
@@ -1221,6 +1222,12 @@ public class InCallActivity extends TransactionSafeFragmentActivity
fragment.show(getSupportFragmentManager(), Tags.INTERNATIONAL_CALL_ON_WIFI);
}
+ public void showDialogForRttRequest(DialerCall call, int rttRequestId) {
+ LogUtil.enterBlock("InCallActivity.showDialogForRttRequest");
+ DialogFragment fragment = RttRequestDialogFragment.newInstance(call.getId(), rttRequestId);
+ fragment.show(getSupportFragmentManager(), Tags.RTT_REQUEST_DIALOG);
+ }
+
@Override
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
super.onMultiWindowModeChanged(isInMultiWindowMode);
@@ -1763,6 +1770,7 @@ public class InCallActivity extends TransactionSafeFragmentActivity
static final String RTT_CALL_SCREEN = "tag_rtt_call_screen";
static final String POST_CHAR_DIALOG_FRAGMENT = "tag_post_char_dialog_fragment";
static final String SPEAK_EASY_SCREEN = "tag_speak_easy_screen";
+ static final String RTT_REQUEST_DIALOG = "tag_rtt_request_dialog";
}
private static final class ConfigNames {
diff --git a/java/com/android/incallui/InCallPresenter.java b/java/com/android/incallui/InCallPresenter.java
index e11b376c1..6300dac75 100644
--- a/java/com/android/incallui/InCallPresenter.java
+++ b/java/com/android/incallui/InCallPresenter.java
@@ -894,6 +894,13 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud
}
@Override
+ public void onUpgradeToRtt(DialerCall call, int rttRequestId) {
+ if (inCallActivity != null) {
+ inCallActivity.showDialogForRttRequest(call, rttRequestId);
+ }
+ }
+
+ @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/RttRequestDialogFragment.java b/java/com/android/incallui/RttRequestDialogFragment.java
new file mode 100644
index 000000000..fa9b0e5db
--- /dev/null
+++ b/java/com/android/incallui/RttRequestDialogFragment.java
@@ -0,0 +1,149 @@
+/*
+ * 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.incallui;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.telephony.PhoneNumberUtils;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.TextView;
+import com.android.contacts.common.util.ContactDisplayUtils;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.incallui.ContactInfoCache.ContactCacheEntry;
+import com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
+import com.android.incallui.call.CallList;
+import com.android.incallui.call.DialerCall;
+import java.lang.ref.WeakReference;
+
+/** Dialog that shown to user when receiving RTT request mid call. */
+public class RttRequestDialogFragment extends DialogFragment {
+
+ /**
+ * Returns a new instance of {@link RttRequestDialogFragment} with the given callback.
+ *
+ * <p>Prefer this method over the default constructor.
+ */
+ public static RttRequestDialogFragment newInstance(String callId, int rttRequestId) {
+ RttRequestDialogFragment fragment = new RttRequestDialogFragment();
+ Bundle args = new Bundle();
+ args.putString(ARG_CALL_ID, Assert.isNotNull(callId));
+ args.putInt(ARG_RTT_REQUEST_ID, rttRequestId);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ /** Key in the arguments bundle for call id. */
+ private static final String ARG_CALL_ID = "call_id";
+
+ private static final String ARG_RTT_REQUEST_ID = "rtt_request_id";
+
+ private TextView detailsTextView;
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle bundle) {
+ super.onCreateDialog(bundle);
+ LogUtil.enterBlock("RttRequestDialogFragment.onCreateDialog");
+
+ View dialogView = View.inflate(getActivity(), R.layout.frag_rtt_request_dialog, null);
+ detailsTextView = dialogView.findViewById(R.id.details);
+
+ ContactInfoCache cache = ContactInfoCache.getInstance(getContext());
+ DialerCall dialerCall =
+ CallList.getInstance().getCallById(getArguments().getString(ARG_CALL_ID));
+ cache.findInfo(dialerCall, false, new ContactLookupCallback(this));
+
+ dialogView
+ .findViewById(R.id.rtt_button_decline_request)
+ .setOnClickListener(v -> onNegativeButtonClick());
+ dialogView
+ .findViewById(R.id.rtt_button_accept_request)
+ .setOnClickListener(v -> onPositiveButtonClick());
+
+ AlertDialog alertDialog =
+ new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme)
+ .setCancelable(false)
+ .setView(dialogView)
+ .setTitle(R.string.rtt_request_dialog_title)
+ .create();
+
+ alertDialog.setCanceledOnTouchOutside(false);
+ return alertDialog;
+ }
+
+ private void onPositiveButtonClick() {
+ LogUtil.enterBlock("RttRequestDialogFragment.onPositiveButtonClick");
+
+ DialerCall call = CallList.getInstance().getCallById(getArguments().getString(ARG_CALL_ID));
+ call.respondToRttRequest(true, getArguments().getInt(ARG_RTT_REQUEST_ID));
+ dismiss();
+ }
+
+ private void onNegativeButtonClick() {
+ LogUtil.enterBlock("RttRequestDialogFragment.onNegativeButtonClick");
+
+ DialerCall call = CallList.getInstance().getCallById(getArguments().getString(ARG_CALL_ID));
+ call.respondToRttRequest(false, getArguments().getInt(ARG_RTT_REQUEST_ID));
+ dismiss();
+ }
+
+ private void setNameOrNumber(CharSequence nameOrNumber) {
+ detailsTextView.setText(getString(R.string.rtt_request_dialog_details, nameOrNumber));
+ }
+
+ private static class ContactLookupCallback implements ContactInfoCacheCallback {
+ private final WeakReference<RttRequestDialogFragment> rttRequestDialogFragmentWeakReference;
+
+ private ContactLookupCallback(RttRequestDialogFragment rttRequestDialogFragment) {
+ rttRequestDialogFragmentWeakReference = new WeakReference<>(rttRequestDialogFragment);
+ }
+
+ @Override
+ public void onContactInfoComplete(String callId, ContactCacheEntry entry) {
+ RttRequestDialogFragment fragment = rttRequestDialogFragmentWeakReference.get();
+ if (fragment != null) {
+ fragment.setNameOrNumber(getNameOrNumber(entry, fragment.getContext()));
+ }
+ }
+
+ private CharSequence getNameOrNumber(ContactCacheEntry entry, Context context) {
+ String preferredName =
+ ContactDisplayUtils.getPreferredDisplayName(
+ entry.namePrimary,
+ entry.nameAlternative,
+ ContactsPreferencesFactory.newContactsPreferences(context));
+ if (TextUtils.isEmpty(preferredName)) {
+ return TextUtils.isEmpty(entry.number)
+ ? null
+ : PhoneNumberUtils.createTtsSpannable(
+ BidiFormatter.getInstance().unicodeWrap(entry.number, TextDirectionHeuristics.LTR));
+ }
+ return preferredName;
+ }
+
+ @Override
+ public void onImageLoadComplete(String callId, ContactCacheEntry entry) {}
+ }
+}
diff --git a/java/com/android/incallui/call/CallList.java b/java/com/android/incallui/call/CallList.java
index 01f3b9d29..eccdceeca 100644
--- a/java/com/android/incallui/call/CallList.java
+++ b/java/com/android/incallui/call/CallList.java
@@ -784,6 +784,12 @@ public class CallList implements DialerCallDelegate {
*/
void onUpgradeToVideo(DialerCall call);
+ /**
+ * Called when a new RTT call request comes in This is the only method that gets called for RTT
+ * requests.
+ */
+ default void onUpgradeToRtt(DialerCall call, int rttRequestId) {}
+
/** Called when the session modification state of a call changes. */
void onSessionModificationStateChange(DialerCall call);
@@ -855,6 +861,13 @@ public class CallList implements DialerCallDelegate {
public void onDialerCallLastForwardedNumberChange() {}
@Override
+ public void onDialerCallUpgradeToRtt(int rttRequestId) {
+ for (Listener listener : listeners) {
+ listener.onUpgradeToRtt(call, rttRequestId);
+ }
+ }
+
+ @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 e08c926d8..35f9481c5 100644
--- a/java/com/android/incallui/call/DialerCall.java
+++ b/java/com/android/incallui/call/DialerCall.java
@@ -282,6 +282,9 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa
@Override
public void onRttRequest(Call call, int id) {
LogUtil.v("TelecomCallCallback.onRttRequest", "id=%d", id);
+ for (DialerCallListener listener : listeners) {
+ listener.onDialerCallUpgradeToRtt(id);
+ }
}
@Override
@@ -1033,6 +1036,11 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa
getTelecomCall().sendRttRequest();
}
+ @TargetApi(28)
+ public void respondToRttRequest(boolean accept, int rttRequestId) {
+ getTelecomCall().respondToRttRequest(rttRequestId, accept);
+ }
+
public boolean hasReceivedVideoUpgradeRequest() {
return VideoUtils.hasReceivedVideoUpgradeRequest(getVideoTech().getSessionModificationState());
}
diff --git a/java/com/android/incallui/call/DialerCallListener.java b/java/com/android/incallui/call/DialerCallListener.java
index 5d24a4d4b..37c30d30c 100644
--- a/java/com/android/incallui/call/DialerCallListener.java
+++ b/java/com/android/incallui/call/DialerCallListener.java
@@ -29,6 +29,8 @@ public interface DialerCallListener {
void onDialerCallUpgradeToVideo();
+ default void onDialerCallUpgradeToRtt(int rttRequestId) {}
+
void onDialerCallSessionModificationStateChange();
void onWiFiToLteHandover();
diff --git a/java/com/android/incallui/res/layout/frag_rtt_request_dialog.xml b/java/com/android/incallui/res/layout/frag_rtt_request_dialog.xml
new file mode 100644
index 000000000..ab743eb89
--- /dev/null
+++ b/java/com/android/incallui/res/layout/frag_rtt_request_dialog.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"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/details"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="20dp"
+ android:paddingBottom="12dp"
+ android:paddingStart="24dp"
+ android:paddingEnd="24dp"
+ android:textColor="#DE000000"
+ android:textSize="16sp"/>
+
+ <TextView
+ android:id="@+id/more_information"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="16dp"
+ android:paddingStart="24dp"
+ android:paddingEnd="24dp"
+ android:text="@string/rtt_request_dialog_more_information"
+ android:textColor="#8A000000"
+ android:textSize="14sp"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:orientation="horizontal">
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"/>
+ <Button
+ android:id="@+id/rtt_button_decline_request"
+ style="@style/Widget.AppCompat.Button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:backgroundTint="@android:color/white"
+ android:fontFamily="sans-serif-medium"
+ android:stateListAnimator="@null"
+ android:text="@string/rtt_button_decline_request"
+ android:textColor="#757575"/>
+ <Button
+ android:id="@+id/rtt_button_accept_request"
+ style="@style/Widget.AppCompat.Button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ 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/rtt_button_accept_request"
+ android:textColor="@android:color/white"/>
+ </LinearLayout>
+
+</LinearLayout>
+
diff --git a/java/com/android/incallui/res/values/strings.xml b/java/com/android/incallui/res/values/strings.xml
index 15cd2e02d..c7e5677c7 100644
--- a/java/com/android/incallui/res/values/strings.xml
+++ b/java/com/android/incallui/res/values/strings.xml
@@ -202,4 +202,19 @@
<!-- Text for bubble return-to-call button -->
<string name="bubble_return_to_call">Back to call</string>
+ <!-- Title for RTT request dialog. [CHAR LIMIT=60] -->
+ <string name="rtt_request_dialog_title">Join RTT call?</string>
+
+ <!-- Details for RTT request dialog. [CHAR LIMIT=NONE] -->
+ <string name="rtt_request_dialog_details"><xliff:g id="caller">%1$s</xliff:g> wants to use messaging within your voice call.</string>
+
+ <!-- More information for RTT request dialog. [CHAR LIMIT=NONE] -->
+ <string name="rtt_request_dialog_more_information">RTT assists callers who are deaf, hard of hearing, have a speech disability, or need more than voice alone.</string>
+
+ <!-- Text for button to decline RTT request. [CHAR LIMIT=20] -->
+ <string name="rtt_button_decline_request">No thanks</string>
+
+ <!-- Text for button to accept RTT request. [CHAR LIMIT=20] -->
+ <string name="rtt_button_accept_request">Join RTT</string>
+
</resources>
diff --git a/java/com/android/incallui/rtt/impl/res/values/strings.xml b/java/com/android/incallui/rtt/impl/res/values/strings.xml
index b0ac2057e..1d09f5446 100644
--- a/java/com/android/incallui/rtt/impl/res/values/strings.xml
+++ b/java/com/android/incallui/rtt/impl/res/values/strings.xml
@@ -27,7 +27,7 @@
<!-- Text for back button. [CHAR LIMIT=20] -->
<string name="rtt_button_back">Back</string>
- <!-- Text for status banner. [CHAT LIMIT=100] -->
+ <!-- Text for status banner. [CHAR LIMIT=100] -->
<string name="rtt_status_banner_text">Waiting for <xliff:g id="name">%s</xliff:g> to join RTT call&#8230;</string>
</resources> \ No newline at end of file