summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorsail <sail@google.com>2017-08-18 12:51:42 -0700
committerEric Erfanian <erfanian@google.com>2017-08-30 15:46:20 +0000
commit945b28c5d8e911f99315c97f23dad05a86c0e1bc (patch)
tree0593d4bc537e25762c85934c7b799e122ce78284 /java
parent8f136644f7ba29ee742719dcb766b49902ac3341 (diff)
Add notifications to simulator
This CL adds a new notification menu to the simulator. The menu allows the user to create the following types of notifications: - missed call notifications - voicemail notifications - "was this spam" notification - "report this as not spam" notification For misssed call and spam, we generate these notifications by creating fake incoming calls using the SimulatorConnectionService. To make it easier to use the connection serivce, it now registers as a SIM call manager. This means that the usre doesn't have to enable the connection service in system settings before using the simulator. Bug: 62937258 Test: SimulatorConnectionServiceTest, SimulatorMissedCallCreatorTest, SimulatorNotificationsTest, SimulatorSpamCallCreatorTest PiperOrigin-RevId: 165740575 Change-Id: I2c54e19c6815f151799d7e51e7c61466c3d3a767
Diffstat (limited to 'java')
-rw-r--r--java/com/android/dialer/databasepopulator/VoicemailPopulator.java32
-rw-r--r--java/com/android/dialer/notification/NotificationThrottler.java6
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorActionProvider.java5
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorConnectionService.java108
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java87
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorNotifications.java118
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorSpamCallCreator.java151
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java17
-rw-r--r--java/com/android/incallui/spam/SpamCallListListener.java10
9 files changed, 490 insertions, 44 deletions
diff --git a/java/com/android/dialer/databasepopulator/VoicemailPopulator.java b/java/com/android/dialer/databasepopulator/VoicemailPopulator.java
index 581100f03..e99f7c7d4 100644
--- a/java/com/android/dialer/databasepopulator/VoicemailPopulator.java
+++ b/java/com/android/dialer/databasepopulator/VoicemailPopulator.java
@@ -113,25 +113,26 @@ public final class VoicemailPopulator {
context.getContentResolver().insert(Status.buildSourceUri(context.getPackageName()), values);
}
+ /** Data for a single voicemail entry. */
@AutoValue
- abstract static class Voicemail {
+ public abstract static class Voicemail {
@NonNull
- abstract String getPhoneNumber();
+ public abstract String getPhoneNumber();
@NonNull
- abstract String getTranscription();
+ public abstract String getTranscription();
- abstract long getDurationSeconds();
+ public abstract long getDurationSeconds();
- abstract long getTimeMillis();
+ public abstract long getTimeMillis();
- abstract boolean getIsRead();
+ public abstract boolean getIsRead();
- static Builder builder() {
+ public static Builder builder() {
return new AutoValue_VoicemailPopulator_Voicemail.Builder();
}
- ContentValues getAsContentValues(Context context) {
+ public ContentValues getAsContentValues(Context context) {
ContentValues values = new ContentValues();
values.put(Voicemails.DATE, getTimeMillis());
values.put(Voicemails.NUMBER, getPhoneNumber());
@@ -142,19 +143,20 @@ public final class VoicemailPopulator {
return values;
}
+ /** Builder for a single voicemail entry. */
@AutoValue.Builder
- abstract static class Builder {
- abstract Builder setPhoneNumber(@NonNull String phoneNumber);
+ public abstract static class Builder {
+ public abstract Builder setPhoneNumber(@NonNull String phoneNumber);
- abstract Builder setTranscription(@NonNull String transcription);
+ public abstract Builder setTranscription(@NonNull String transcription);
- abstract Builder setDurationSeconds(long durationSeconds);
+ public abstract Builder setDurationSeconds(long durationSeconds);
- abstract Builder setTimeMillis(long timeMillis);
+ public abstract Builder setTimeMillis(long timeMillis);
- abstract Builder setIsRead(boolean isRead);
+ public abstract Builder setIsRead(boolean isRead);
- abstract Voicemail build();
+ public abstract Voicemail build();
}
}
diff --git a/java/com/android/dialer/notification/NotificationThrottler.java b/java/com/android/dialer/notification/NotificationThrottler.java
index 661dec759..9db744df6 100644
--- a/java/com/android/dialer/notification/NotificationThrottler.java
+++ b/java/com/android/dialer/notification/NotificationThrottler.java
@@ -36,7 +36,13 @@ import java.util.List;
* notification type. Once the limit is reached, older notifications are cancelled.
*/
/* package */ class NotificationThrottler {
+ /**
+ * For gropued bundled notifications, the system UI will only display the last 8. For grouped
+ * unbundled notifications, the system displays all notifications until a global maximum of 50 is
+ * reached.
+ */
private static final int MAX_NOTIFICATIONS_PER_TAG = 10;
+
private static final int HIGH_GLOBAL_NOTIFICATION_COUNT = 45;
private static boolean didLogHighGlobalNotificationCountReached;
diff --git a/java/com/android/dialer/simulator/impl/SimulatorActionProvider.java b/java/com/android/dialer/simulator/impl/SimulatorActionProvider.java
index 4efc0ee2d..96591135b 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorActionProvider.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorActionProvider.java
@@ -77,6 +77,7 @@ final class SimulatorActionProvider extends ActionProvider {
super.onPrepareSubMenu(subMenu);
LogUtil.enterBlock("SimulatorActionProvider.onPrepareSubMenu");
subMenu.clear();
+
subMenu
.add("Add call")
.setOnMenuItemClickListener(
@@ -84,6 +85,10 @@ final class SimulatorActionProvider extends ActionProvider {
SimulatorVoiceCall.addNewIncomingCall(context);
return true;
});
+
+ subMenu
+ .add("Notifiations")
+ .setActionProvider(SimulatorNotifications.getActionProvider(context));
subMenu
.add("Populate database")
.setOnMenuItemClickListener(
diff --git a/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java b/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java
index 322360786..9e107edee 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java
@@ -19,6 +19,8 @@ package com.android.dialer.simulator.impl;
import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
import android.telecom.ConnectionService;
@@ -26,20 +28,64 @@ import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
+import android.widget.Toast;
+import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import java.util.ArrayList;
import java.util.List;
/** Simple connection provider to create an incoming call. This is useful for emulators. */
-public final class SimulatorConnectionService extends ConnectionService {
+public class SimulatorConnectionService extends ConnectionService {
private static final String PHONE_ACCOUNT_ID = "SIMULATOR_ACCOUNT_ID";
+ private static final String EXTRA_IS_SIMULATOR_CONNECTION = "is_simulator_connection";
+ private static final List<Listener> listeners = new ArrayList<>();
- public static void register(Context context) {
+ private static void register(@NonNull Context context) {
LogUtil.enterBlock("SimulatorConnectionService.register");
+ Assert.isNotNull(context);
context.getSystemService(TelecomManager.class).registerPhoneAccount(buildPhoneAccount(context));
}
+ private static void unregister(@NonNull Context context) {
+ LogUtil.enterBlock("SimulatorConnectionService.unregister");
+ Assert.isNotNull(context);
+ context
+ .getSystemService(TelecomManager.class)
+ .unregisterPhoneAccount(buildPhoneAccount(context).getAccountHandle());
+ }
+
+ public static void addNewIncomingCall(
+ @NonNull Context context, @NonNull Bundle extras, @NonNull String callerId) {
+ LogUtil.enterBlock("SimulatorConnectionService.addNewIncomingCall");
+ Assert.isNotNull(context);
+ Assert.isNotNull(extras);
+ Assert.isNotNull(callerId);
+
+ register(context);
+
+ Bundle bundle = new Bundle(extras);
+ bundle.putString(TelephonyManager.EXTRA_INCOMING_NUMBER, callerId);
+ bundle.putBoolean(EXTRA_IS_SIMULATOR_CONNECTION, true);
+
+ // Use the system's phone account so that these look like regular SIM call.
+ TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
+ PhoneAccountHandle systemPhoneAccount =
+ telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
+ telecomManager.addNewIncomingCall(systemPhoneAccount, bundle);
+ }
+
+ public static void addListener(@NonNull Listener listener) {
+ Assert.isNotNull(listener);
+ listeners.add(listener);
+ }
+
+ public static void removeListener(@NonNull Listener listener) {
+ Assert.isNotNull(listener);
+ listeners.remove(listener);
+ }
+
+ @NonNull
private static PhoneAccount buildPhoneAccount(Context context) {
PhoneAccount.Builder builder =
new PhoneAccount.Builder(
@@ -48,7 +94,8 @@ public final class SimulatorConnectionService extends ConnectionService {
uriSchemes.add(PhoneAccount.SCHEME_TEL);
return builder
- .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .setCapabilities(
+ PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
.setShortDescription("Simulator Connection Service")
.setSupportedUriSchemes(uriSchemes)
.build();
@@ -67,21 +114,68 @@ public final class SimulatorConnectionService extends ConnectionService {
@Override
public Connection onCreateOutgoingConnection(
PhoneAccountHandle phoneAccount, ConnectionRequest request) {
- LogUtil.i(
- "SimulatorConnectionService.onCreateOutgoingConnection",
- "outgoing calls not supported yet");
- return null;
+ LogUtil.enterBlock("SimulatorConnectionService.onCreateOutgoingConnection");
+ if (!isSimulatorConnectionRequest(request)) {
+ LogUtil.i(
+ "SimulatorConnectionService.onCreateOutgoingConnection",
+ "outgoing call not from simulator, unregistering");
+ Toast.makeText(
+ this, "Unregistering Dialer simulator, making a real phone call", Toast.LENGTH_LONG)
+ .show();
+ unregister(this);
+ return null;
+ }
+
+ SimulatorConnection connection = new SimulatorConnection();
+ connection.setActive();
+ connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+ connection.setConnectionCapabilities(
+ Connection.CAPABILITY_MUTE | Connection.CAPABILITY_SUPPORT_HOLD);
+ connection.putExtras(request.getExtras());
+
+ for (Listener listener : listeners) {
+ listener.onNewOutgoingConnection(connection);
+ }
+ return connection;
}
@Override
public Connection onCreateIncomingConnection(
PhoneAccountHandle phoneAccount, ConnectionRequest request) {
LogUtil.enterBlock("SimulatorConnectionService.onCreateIncomingConnection");
+ if (!isSimulatorConnectionRequest(request)) {
+ LogUtil.i(
+ "SimulatorConnectionService.onCreateIncomingConnection",
+ "incoming call not from simulator, unregistering");
+ Toast.makeText(
+ this, "Unregistering Dialer simulator, got a real incoming call", Toast.LENGTH_LONG)
+ .show();
+ unregister(this);
+ return null;
+ }
+
SimulatorConnection connection = new SimulatorConnection();
connection.setRinging();
connection.setAddress(getPhoneNumber(request), TelecomManager.PRESENTATION_ALLOWED);
connection.setConnectionCapabilities(
Connection.CAPABILITY_MUTE | Connection.CAPABILITY_SUPPORT_HOLD);
+ connection.putExtras(request.getExtras());
+
+ for (Listener listener : listeners) {
+ listener.onNewIncomingConnection(connection);
+ }
return connection;
}
+
+ private static boolean isSimulatorConnectionRequest(@NonNull ConnectionRequest request) {
+ return request.getExtras() != null
+ && request.getExtras().getBoolean(EXTRA_IS_SIMULATOR_CONNECTION);
+ }
+
+ /** Callback used to notify listeners when a new connection has been added. */
+ public interface Listener {
+ void onNewOutgoingConnection(SimulatorConnection connection);
+
+ void onNewIncomingConnection(SimulatorConnection connection);
+ }
}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java b/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java
new file mode 100644
index 000000000..22eb96731
--- /dev/null
+++ b/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.simulator.impl;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.telecom.Connection;
+import android.telecom.DisconnectCause;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.ThreadUtil;
+
+/**
+ * Shows missed call notifications. Note, we explicilty create fake phone calls to trigger these
+ * notifications instead of writing to the call log directly. This makes the simulator behave more
+ * like the real application.
+ */
+final class SimulatorMissedCallCreator implements SimulatorConnectionService.Listener {
+ private static final String EXTRA_CALL_COUNT = "call_count";
+ private static final String EXTRA_IS_MISSED_CALL_CONNECTION = "is_missed_call_connection";
+ private static final int DISCONNECT_DELAY_MILLIS = 1000;
+
+ private final Context context;
+
+ SimulatorMissedCallCreator(@NonNull Context context) {
+ this.context = Assert.isNotNull(context);
+ }
+
+ public void start(int callCount) {
+ SimulatorConnectionService.addListener(this);
+ addNextIncomingCall(callCount);
+ }
+
+ @Override
+ public void onNewOutgoingConnection(@NonNull SimulatorConnection connection) {}
+
+ @Override
+ public void onNewIncomingConnection(@NonNull SimulatorConnection connection) {
+ if (!isMissedCallConnection(connection)) {
+ return;
+ }
+ ThreadUtil.postDelayedOnUiThread(
+ () -> {
+ connection.setDisconnected(new DisconnectCause(DisconnectCause.MISSED));
+ addNextIncomingCall(getCallCount(connection));
+ },
+ DISCONNECT_DELAY_MILLIS);
+ }
+
+ private void addNextIncomingCall(int callCount) {
+ if (callCount <= 0) {
+ LogUtil.i("SimulatorMissedCallCreator.addNextIncomingCall", "done adding calls");
+ SimulatorConnectionService.removeListener(this);
+ return;
+ }
+
+ String callerId = String.format("+%d", callCount);
+ Bundle extras = new Bundle();
+ extras.putInt(EXTRA_CALL_COUNT, callCount - 1);
+ extras.putBoolean(EXTRA_IS_MISSED_CALL_CONNECTION, true);
+
+ SimulatorConnectionService.addNewIncomingCall(context, extras, callerId);
+ }
+
+ private static boolean isMissedCallConnection(@NonNull Connection connection) {
+ return connection.getExtras().getBoolean(EXTRA_IS_MISSED_CALL_CONNECTION);
+ }
+
+ private static int getCallCount(@NonNull Connection connection) {
+ return connection.getExtras().getInt(EXTRA_CALL_COUNT);
+ }
+}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorNotifications.java b/java/com/android/dialer/simulator/impl/SimulatorNotifications.java
new file mode 100644
index 000000000..ebe8ecd46
--- /dev/null
+++ b/java/com/android/dialer/simulator/impl/SimulatorNotifications.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.simulator.impl;
+
+import android.content.Context;
+import android.provider.VoicemailContract.Voicemails;
+import android.support.annotation.NonNull;
+import android.view.ActionProvider;
+import android.view.MenuItem;
+import android.view.SubMenu;
+import android.view.View;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.databasepopulator.VoicemailPopulator;
+import java.util.concurrent.TimeUnit;
+
+/** Implements the simulator submenu. */
+final class SimulatorNotifications {
+ private static final int NOTIFICATION_COUNT = 12;
+
+ static ActionProvider getActionProvider(@NonNull Context context) {
+ return new NotificationsActionProvider(context);
+ }
+
+ private static class NotificationsActionProvider extends ActionProvider {
+ @NonNull private final Context context;
+
+ public NotificationsActionProvider(@NonNull Context context) {
+ super(Assert.isNotNull(context));
+ this.context = context;
+ }
+
+ @Override
+ public View onCreateActionView() {
+ return null;
+ }
+
+ @Override
+ public View onCreateActionView(MenuItem forItem) {
+ return null;
+ }
+
+ @Override
+ public boolean hasSubMenu() {
+ return true;
+ }
+
+ @Override
+ public void onPrepareSubMenu(@NonNull SubMenu subMenu) {
+ LogUtil.enterBlock("NotificationsActionProvider.onPrepareSubMenu");
+ Assert.isNotNull(subMenu);
+ super.onPrepareSubMenu(subMenu);
+
+ subMenu.clear();
+ subMenu
+ .add("Missed Calls")
+ .setOnMenuItemClickListener(
+ (item) -> {
+ new SimulatorMissedCallCreator(context).start(NOTIFICATION_COUNT);
+ return true;
+ });
+ subMenu
+ .add("Voicemails")
+ .setOnMenuItemClickListener(
+ (item) -> {
+ addVoicemailNotifications(context);
+ return true;
+ });
+ subMenu
+ .add("Non spam")
+ .setOnMenuItemClickListener(
+ (item) -> {
+ new SimulatorSpamCallCreator(context, false /* isSpam */).start(NOTIFICATION_COUNT);
+ return true;
+ });
+ subMenu
+ .add("Confirm spam")
+ .setOnMenuItemClickListener(
+ (item) -> {
+ new SimulatorSpamCallCreator(context, true /* isSpam */).start(NOTIFICATION_COUNT);
+ return true;
+ });
+ }
+ }
+
+ private static void addVoicemailNotifications(@NonNull Context context) {
+ LogUtil.enterBlock("SimulatorNotifications.addVoicemailNotifications");
+ for (int i = NOTIFICATION_COUNT; i > 0; i--) {
+ VoicemailPopulator.Voicemail voicemail =
+ VoicemailPopulator.Voicemail.builder()
+ .setPhoneNumber(String.format("+%d", i))
+ .setTranscription(String.format("Short transcript %d", i))
+ .setDurationSeconds(60)
+ .setIsRead(false)
+ .setTimeMillis(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(i))
+ .build();
+ context
+ .getContentResolver()
+ .insert(
+ Voicemails.buildSourceUri(context.getPackageName()),
+ voicemail.getAsContentValues(context));
+ }
+ }
+}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorSpamCallCreator.java b/java/com/android/dialer/simulator/impl/SimulatorSpamCallCreator.java
new file mode 100644
index 000000000..4b1d7a564
--- /dev/null
+++ b/java/com/android/dialer/simulator/impl/SimulatorSpamCallCreator.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.simulator.impl;
+
+import android.content.ContentProviderOperation;
+import android.content.Context;
+import android.content.OperationApplicationException;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.provider.CallLog;
+import android.support.annotation.NonNull;
+import android.telecom.Connection;
+import android.telecom.DisconnectCause;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.ThreadUtil;
+import com.android.dialer.spam.Spam;
+import com.android.dialer.spam.SpamBindingsStub;
+import java.util.ArrayList;
+
+/**
+ * Creates many spam call notifications by adding new incoming calls one at a time and disconnecting
+ * them.
+ */
+final class SimulatorSpamCallCreator implements SimulatorConnectionService.Listener {
+ private static final String EXTRA_CALL_COUNT = "call_count";
+ private static final String EXTRA_IS_SPAM_CALL_CONNECTION = "is_spam_call_connection";
+ private static final int DISCONNECT_DELAY_MILLIS = 1000;
+
+ private final Context context;
+ private final boolean isSpam;
+
+ SimulatorSpamCallCreator(@NonNull Context context, boolean isSpam) {
+ this.context = Assert.isNotNull(context);
+ this.isSpam = isSpam;
+ }
+
+ public void start(int callCount) {
+ Spam.setForTesting(new SimulatorSpamBindings(isSpam));
+ SimulatorConnectionService.addListener(this);
+ addNextIncomingCall(callCount);
+ }
+
+ @Override
+ public void onNewOutgoingConnection(@NonNull SimulatorConnection connection) {}
+
+ @Override
+ public void onNewIncomingConnection(@NonNull SimulatorConnection connection) {
+ if (!isSpamCallConnection(connection)) {
+ return;
+ }
+ ThreadUtil.postDelayedOnUiThread(
+ () -> {
+ LogUtil.i("SimulatorSpamCallCreator.onNewIncomingConnection", "disconnecting");
+ connection.setActive();
+ connection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
+ ThreadUtil.postDelayedOnUiThread(
+ () -> addNextIncomingCall(getCallCount(connection)), DISCONNECT_DELAY_MILLIS);
+ },
+ DISCONNECT_DELAY_MILLIS);
+ }
+
+ private void addNextIncomingCall(int callCount) {
+ if (callCount <= 0) {
+ LogUtil.i("SimulatorSpamCallCreator.addNextIncomingCall", "done adding calls");
+ SimulatorConnectionService.removeListener(this);
+ Spam.setForTesting(null);
+ return;
+ }
+
+ // Caller ID must be e.164 formatted and unique.
+ String callerId = String.format("+1-650-234%04d", callCount);
+ Bundle extras = new Bundle();
+ extras.putInt(EXTRA_CALL_COUNT, callCount - 1);
+ extras.putBoolean(EXTRA_IS_SPAM_CALL_CONNECTION, true);
+
+ // We need to clear the call log because spam notifiations are only shown for new calls.
+ clearCallLog(context);
+
+ SimulatorConnectionService.addNewIncomingCall(context, extras, callerId);
+ }
+
+ private static boolean isSpamCallConnection(@NonNull Connection connection) {
+ return connection.getExtras().getBoolean(EXTRA_IS_SPAM_CALL_CONNECTION);
+ }
+
+ private static int getCallCount(@NonNull Connection connection) {
+ return connection.getExtras().getInt(EXTRA_CALL_COUNT);
+ }
+
+ private static void clearCallLog(@NonNull Context context) {
+ try {
+ ArrayList<ContentProviderOperation> operations = new ArrayList<>();
+ operations.add(ContentProviderOperation.newDelete(CallLog.Calls.CONTENT_URI).build());
+ context.getContentResolver().applyBatch(CallLog.AUTHORITY, operations);
+ } catch (RemoteException | OperationApplicationException e) {
+ Assert.fail("failed to clear call log: " + e);
+ }
+ }
+
+ /**
+ * Custom spam bindings that allow us to override which phone numbers are considered to be spam.
+ * Also disables throttling of spam notifications.
+ */
+ private static class SimulatorSpamBindings extends SpamBindingsStub {
+ private final boolean isSpam;
+
+ SimulatorSpamBindings(boolean isSpam) {
+ this.isSpam = isSpam;
+ }
+
+ @Override
+ public boolean isSpamEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isSpamNotificationEnabled() {
+ return true;
+ }
+
+ @Override
+ public int percentOfSpamNotificationsToShow() {
+ return 100;
+ }
+
+ @Override
+ public int percentOfNonSpamNotificationsToShow() {
+ return 100;
+ }
+
+ @Override
+ public void checkSpamStatus(String number, String countryIso, Listener listener) {
+ listener.onComplete(isSpam);
+ }
+ }
+}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
index 39c1d02a5..5930dff24 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
@@ -19,28 +19,15 @@ package com.android.dialer.simulator.impl;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
-import android.telecom.TelecomManager;
-import android.telephony.TelephonyManager;
-import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
/** Utilities to simulate phone calls. */
final class SimulatorVoiceCall {
public static void addNewIncomingCall(@NonNull Context context) {
LogUtil.enterBlock("SimulatorVoiceCall.addNewIncomingCall");
- SimulatorConnectionService.register(context);
-
- Bundle bundle = new Bundle();
// Set the caller ID to the Google London office.
- bundle.putString(TelephonyManager.EXTRA_INCOMING_NUMBER, "+44 (0) 20 7031 3000");
- try {
- context
- .getSystemService(TelecomManager.class)
- .addNewIncomingCall(
- SimulatorConnectionService.getConnectionServiceHandle(context), bundle);
- } catch (SecurityException e) {
- Assert.fail("unable to add call: " + e);
- }
+ String callerId = "+44 (0) 20 7031 3000";
+ SimulatorConnectionService.addNewIncomingCall(context, new Bundle(), callerId);
}
private SimulatorVoiceCall() {}
diff --git a/java/com/android/incallui/spam/SpamCallListListener.java b/java/com/android/incallui/spam/SpamCallListListener.java
index f8bc9cebe..6b2bdcef6 100644
--- a/java/com/android/incallui/spam/SpamCallListListener.java
+++ b/java/com/android/incallui/spam/SpamCallListListener.java
@@ -53,7 +53,6 @@ import com.android.dialer.util.PermissionsUtil;
import com.android.incallui.call.CallList;
import com.android.incallui.call.DialerCall;
import com.android.incallui.call.DialerCall.CallHistoryStatus;
-import java.util.Arrays;
import java.util.Random;
/**
@@ -143,13 +142,10 @@ public class SpamCallListListener implements CallList.Listener {
return;
}
- String[] deniedPhonePermissions =
- PermissionsUtil.getPermissionsCurrentlyDenied(
- context, PermissionsUtil.allPhoneGroupPermissionsUsedInDialer);
- if (deniedPhonePermissions.length > 0) {
+ if (!PermissionsUtil.hasCallLogReadPermissions(context)) {
LogUtil.i(
- "NumberInCallHistoryWorker.submitTask",
- "Need phone permissions: " + Arrays.toString(deniedPhonePermissions));
+ "SpamCallListListener.onIncomingCall",
+ "call log permission missing, not checking if number is in call history");
return;
}