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/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
18 files changed, 408 insertions, 69 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)