summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/simulator
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer/simulator')
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorActionProvider.java41
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorCallLog.java139
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorConnectionService.java108
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorContacts.java319
-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/dialer/simulator/impl/SimulatorVoicemail.java154
9 files changed, 497 insertions, 637 deletions
diff --git a/java/com/android/dialer/simulator/impl/SimulatorActionProvider.java b/java/com/android/dialer/simulator/impl/SimulatorActionProvider.java
index 8257d9853..f095a5993 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorActionProvider.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorActionProvider.java
@@ -30,6 +30,10 @@ import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
import com.android.dialer.common.concurrent.DialerExecutors;
+import com.android.dialer.databasepopulator.CallLogPopulator;
+import com.android.dialer.databasepopulator.ContactsPopulator;
+import com.android.dialer.databasepopulator.VoicemailPopulator;
+import com.android.dialer.enrichedcall.simulator.EnrichedCallSimulatorActivity;
import com.android.dialer.persistentlog.PersistentLogger;
/** Implements the simulator submenu. */
@@ -73,6 +77,7 @@ final class SimulatorActionProvider extends ActionProvider {
super.onPrepareSubMenu(subMenu);
LogUtil.enterBlock("SimulatorActionProvider.onPrepareSubMenu");
subMenu.clear();
+
subMenu
.add("Add call")
.setOnMenuItemClickListener(
@@ -80,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(
@@ -88,6 +97,13 @@ final class SimulatorActionProvider extends ActionProvider {
return true;
});
subMenu
+ .add("Clean database")
+ .setOnMenuItemClickListener(
+ (item) -> {
+ cleanDatabase();
+ return true;
+ });
+ subMenu
.add("Sync Voicemail")
.setOnMenuItemClickListener(
(item) -> {
@@ -114,15 +130,34 @@ final class SimulatorActionProvider extends ActionProvider {
.executeSerial(null);
return true;
});
+ subMenu
+ .add("Enriched call simulator")
+ .setOnMenuItemClickListener(
+ (item) -> {
+ context.startActivity(EnrichedCallSimulatorActivity.newIntent(context));
+ return true;
+ });
}
private void populateDatabase() {
new AsyncTask<Void, Void, Void>() {
@Override
public Void doInBackground(Void... params) {
- SimulatorContacts.populateContacts(context);
- SimulatorCallLog.populateCallLog(context);
- SimulatorVoicemail.populateVoicemail(context);
+ ContactsPopulator.populateContacts(context);
+ CallLogPopulator.populateCallLog(context);
+ VoicemailPopulator.populateVoicemail(context);
+ return null;
+ }
+ }.execute();
+ }
+
+ private void cleanDatabase() {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ public Void doInBackground(Void... params) {
+ ContactsPopulator.deleteAllContacts(context);
+ CallLogPopulator.deleteAllCallLog(context);
+ VoicemailPopulator.deleteAllVoicemail(context);
return null;
}
}.execute();
diff --git a/java/com/android/dialer/simulator/impl/SimulatorCallLog.java b/java/com/android/dialer/simulator/impl/SimulatorCallLog.java
deleted file mode 100644
index f127d5603..000000000
--- a/java/com/android/dialer/simulator/impl/SimulatorCallLog.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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.ContentValues;
-import android.content.Context;
-import android.content.OperationApplicationException;
-import android.os.RemoteException;
-import android.provider.CallLog;
-import android.provider.CallLog.Calls;
-import android.support.annotation.NonNull;
-import android.support.annotation.WorkerThread;
-import com.android.dialer.common.Assert;
-import com.google.auto.value.AutoValue;
-import java.util.ArrayList;
-import java.util.concurrent.TimeUnit;
-
-/** Populates the device database with call log entries. */
-final class SimulatorCallLog {
- // Phone numbers from https://www.google.com/about/company/facts/locations/
- private static final CallEntry.Builder[] SIMPLE_CALL_LOG = {
- CallEntry.builder().setType(Calls.MISSED_TYPE).setNumber("+1-302-6365454"),
- CallEntry.builder()
- .setType(Calls.MISSED_TYPE)
- .setNumber("")
- .setPresentation(Calls.PRESENTATION_UNKNOWN),
- CallEntry.builder().setType(Calls.REJECTED_TYPE).setNumber("+1-302-6365454"),
- CallEntry.builder().setType(Calls.INCOMING_TYPE).setNumber("+1-302-6365454"),
- CallEntry.builder()
- .setType(Calls.MISSED_TYPE)
- .setNumber("1234")
- .setPresentation(Calls.PRESENTATION_RESTRICTED),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("+1-302-6365454"),
- CallEntry.builder().setType(Calls.BLOCKED_TYPE).setNumber("+1-302-6365454"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("(425) 739-5600"),
- CallEntry.builder().setType(Calls.ANSWERED_EXTERNALLY_TYPE).setNumber("(425) 739-5600"),
- CallEntry.builder().setType(Calls.MISSED_TYPE).setNumber("+1 (425) 739-5600"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("739-5600"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("711"),
- CallEntry.builder().setType(Calls.INCOMING_TYPE).setNumber("711"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("(425) 739-5600"),
- CallEntry.builder().setType(Calls.MISSED_TYPE).setNumber("+44 (0) 20 7031 3000"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("+1-650-2530000"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("+1 303-245-0086;123,456"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("+1 303-245-0086"),
- CallEntry.builder().setType(Calls.INCOMING_TYPE).setNumber("+1-650-2530000"),
- CallEntry.builder().setType(Calls.MISSED_TYPE).setNumber("650-2530000"),
- CallEntry.builder().setType(Calls.REJECTED_TYPE).setNumber("2530000"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("+1 404-487-9000"),
- CallEntry.builder().setType(Calls.INCOMING_TYPE).setNumber("+61 2 9374 4001"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("+33 (0)1 42 68 53 00"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("972-74-746-6245"),
- CallEntry.builder().setType(Calls.INCOMING_TYPE).setNumber("+971 4 4509500"),
- CallEntry.builder().setType(Calls.INCOMING_TYPE).setNumber("+971 4 4509500"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("55-31-2128-6800"),
- CallEntry.builder().setType(Calls.MISSED_TYPE).setNumber("611"),
- CallEntry.builder().setType(Calls.OUTGOING_TYPE).setNumber("*86 512-343-5283"),
- };
-
- @WorkerThread
- public static void populateCallLog(@NonNull Context context) {
- Assert.isWorkerThread();
- ArrayList<ContentProviderOperation> operations = new ArrayList<>();
- // Do this 4 times to make the call log 4 times bigger.
- long timeMillis = System.currentTimeMillis();
- for (int i = 0; i < 4; i++) {
- for (CallEntry.Builder builder : SIMPLE_CALL_LOG) {
- CallEntry callEntry = builder.setTimeMillis(timeMillis).build();
- operations.add(
- ContentProviderOperation.newInsert(Calls.CONTENT_URI)
- .withValues(callEntry.getAsContentValues())
- .withYieldAllowed(true)
- .build());
- timeMillis -= TimeUnit.HOURS.toMillis(1);
- }
- }
- try {
- context.getContentResolver().applyBatch(CallLog.AUTHORITY, operations);
- } catch (RemoteException | OperationApplicationException e) {
- Assert.fail("error adding call entries: " + e);
- }
- }
-
- @AutoValue
- abstract static class CallEntry {
- @NonNull
- abstract String getNumber();
-
- abstract int getType();
-
- abstract int getPresentation();
-
- abstract long getTimeMillis();
-
- static Builder builder() {
- return new AutoValue_SimulatorCallLog_CallEntry.Builder()
- .setPresentation(Calls.PRESENTATION_ALLOWED);
- }
-
- ContentValues getAsContentValues() {
- ContentValues values = new ContentValues();
- values.put(Calls.TYPE, getType());
- values.put(Calls.NUMBER, getNumber());
- values.put(Calls.NUMBER_PRESENTATION, getPresentation());
- values.put(Calls.DATE, getTimeMillis());
- return values;
- }
-
- @AutoValue.Builder
- abstract static class Builder {
- abstract Builder setNumber(@NonNull String number);
-
- abstract Builder setType(int type);
-
- abstract Builder setPresentation(int presentation);
-
- abstract Builder setTimeMillis(long timeMillis);
-
- abstract CallEntry build();
- }
- }
-
- private SimulatorCallLog() {}
-}
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/SimulatorContacts.java b/java/com/android/dialer/simulator/impl/SimulatorContacts.java
deleted file mode 100644
index c5e25b357..000000000
--- a/java/com/android/dialer/simulator/impl/SimulatorContacts.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * 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.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.os.RemoteException;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.WorkerThread;
-import android.text.TextUtils;
-import com.android.dialer.common.Assert;
-import com.google.auto.value.AutoValue;
-import java.io.ByteArrayOutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/** Populates the device database with contacts. */
-final class SimulatorContacts {
- // Phone numbers from https://www.google.com/about/company/facts/locations/
- private static final Contact[] SIMPLE_CONTACTS = {
- // US, contact with e164 number.
- Contact.builder()
- .setName("Michelangelo")
- .addPhoneNumber(new PhoneNumber("+1-302-6365454", Phone.TYPE_MOBILE))
- .addEmail(new Email("m@example.com"))
- .setIsStarred(true)
- .setOrangePhoto()
- .build(),
- // US, contact with a non-e164 number.
- Contact.builder()
- .setName("Leonardo da Vinci")
- .addPhoneNumber(new PhoneNumber("(425) 739-5600", Phone.TYPE_MOBILE))
- .addEmail(new Email("l@example.com"))
- .setIsStarred(true)
- .setBluePhoto()
- .build(),
- // UK, number where the (0) should be dropped.
- Contact.builder()
- .setName("Raphael")
- .addPhoneNumber(new PhoneNumber("+44 (0) 20 7031 3000", Phone.TYPE_MOBILE))
- .addEmail(new Email("r@example.com"))
- .setIsStarred(true)
- .setRedPhoto()
- .build(),
- // US and Australia, contact with a long name and multiple phone numbers.
- Contact.builder()
- .setName("Donatello di Niccolò di Betto Bardi")
- .addPhoneNumber(new PhoneNumber("+1-650-2530000", Phone.TYPE_HOME))
- .addPhoneNumber(new PhoneNumber("+1 404-487-9000", Phone.TYPE_WORK))
- .addPhoneNumber(new PhoneNumber("+61 2 9374 4001", Phone.TYPE_FAX_HOME))
- .setIsStarred(true)
- .setPurplePhoto()
- .build(),
- // US, phone number shared with another contact and 2nd phone number with wait and pause.
- Contact.builder()
- .setName("Splinter")
- .addPhoneNumber(new PhoneNumber("+1-650-2530000", Phone.TYPE_HOME))
- .addPhoneNumber(new PhoneNumber("+1 303-245-0086;123,456", Phone.TYPE_WORK))
- .build(),
- // France, number with Japanese name.
- Contact.builder()
- .setName("スパイク・スピーゲル")
- .addPhoneNumber(new PhoneNumber("+33 (0)1 42 68 53 00", Phone.TYPE_MOBILE))
- .build(),
- // Israel, RTL name and non-e164 number.
- Contact.builder()
- .setName("עקב אריה טברסק")
- .addPhoneNumber(new PhoneNumber("+33 (0)1 42 68 53 00", Phone.TYPE_MOBILE))
- .build(),
- // UAE, RTL name.
- Contact.builder()
- .setName("سلام دنیا")
- .addPhoneNumber(new PhoneNumber("+971 4 4509500", Phone.TYPE_MOBILE))
- .build(),
- // Brazil, contact with no name.
- Contact.builder()
- .addPhoneNumber(new PhoneNumber("+55-31-2128-6800", Phone.TYPE_MOBILE))
- .build(),
- // Short number, contact with no name.
- Contact.builder().addPhoneNumber(new PhoneNumber("611", Phone.TYPE_MOBILE)).build(),
- // US, number with an anonymous prefix.
- Contact.builder()
- .setName("Anonymous")
- .addPhoneNumber(new PhoneNumber("*86 512-343-5283", Phone.TYPE_MOBILE))
- .build(),
- // None, contact with no phone number.
- Contact.builder()
- .setName("No Phone Number")
- .addEmail(new Email("no@example.com"))
- .setIsStarred(true)
- .build(),
- };
-
- @WorkerThread
- static void populateContacts(@NonNull Context context) {
- Assert.isWorkerThread();
- ArrayList<ContentProviderOperation> operations = new ArrayList<>();
- for (Contact contact : SIMPLE_CONTACTS) {
- addContact(contact, operations);
- }
- try {
- context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);
- } catch (RemoteException | OperationApplicationException e) {
- Assert.fail("error adding contacts: " + e);
- }
- }
-
- private static void addContact(Contact contact, List<ContentProviderOperation> operations) {
- int index = operations.size();
-
- operations.add(
- ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
- .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, contact.getAccountType())
- .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, contact.getAccountName())
- .withValue(ContactsContract.RawContacts.STARRED, contact.getIsStarred())
- .withYieldAllowed(true)
- .build());
-
- if (!TextUtils.isEmpty(contact.getName())) {
- operations.add(
- ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, index)
- .withValue(
- ContactsContract.Data.MIMETYPE,
- ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
- .withValue(
- ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getName())
- .build());
- }
-
- if (contact.getPhotoStream() != null) {
- operations.add(
- ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, index)
- .withValue(
- ContactsContract.Data.MIMETYPE,
- ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
- .withValue(
- ContactsContract.CommonDataKinds.Photo.PHOTO,
- contact.getPhotoStream().toByteArray())
- .build());
- }
-
- for (PhoneNumber phoneNumber : contact.getPhoneNumbers()) {
- operations.add(
- ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, index)
- .withValue(
- ContactsContract.Data.MIMETYPE,
- ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber.value)
- .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneNumber.type)
- .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, phoneNumber.label)
- .build());
- }
-
- for (Email email : contact.getEmails()) {
- operations.add(
- ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, index)
- .withValue(
- ContactsContract.Data.MIMETYPE,
- ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Email.DATA, email.value)
- .withValue(ContactsContract.CommonDataKinds.Email.TYPE, email.type)
- .withValue(ContactsContract.CommonDataKinds.Email.LABEL, email.label)
- .build());
- }
- }
-
- @AutoValue
- abstract static class Contact {
- @NonNull
- abstract String getAccountType();
-
- @NonNull
- abstract String getAccountName();
-
- @Nullable
- abstract String getName();
-
- abstract boolean getIsStarred();
-
- @Nullable
- abstract ByteArrayOutputStream getPhotoStream();
-
- @NonNull
- abstract List<PhoneNumber> getPhoneNumbers();
-
- @NonNull
- abstract List<Email> getEmails();
-
- static Builder builder() {
- return new AutoValue_SimulatorContacts_Contact.Builder()
- .setAccountType("com.google")
- .setAccountName("foo@example")
- .setIsStarred(false)
- .setPhoneNumbers(new ArrayList<>())
- .setEmails(new ArrayList<>());
- }
-
- @AutoValue.Builder
- abstract static class Builder {
- @NonNull private final List<PhoneNumber> phoneNumbers = new ArrayList<>();
- @NonNull private final List<Email> emails = new ArrayList<>();
-
- abstract Builder setAccountType(@NonNull String accountType);
-
- abstract Builder setAccountName(@NonNull String accountName);
-
- abstract Builder setName(@NonNull String name);
-
- abstract Builder setIsStarred(boolean isStarred);
-
- abstract Builder setPhotoStream(ByteArrayOutputStream photoStream);
-
- abstract Builder setPhoneNumbers(@NonNull List<PhoneNumber> phoneNumbers);
-
- abstract Builder setEmails(@NonNull List<Email> emails);
-
- abstract Contact build();
-
- Builder addPhoneNumber(PhoneNumber phoneNumber) {
- phoneNumbers.add(phoneNumber);
- return setPhoneNumbers(phoneNumbers);
- }
-
- Builder addEmail(Email email) {
- emails.add(email);
- return setEmails(emails);
- }
-
- Builder setRedPhoto() {
- setPhotoStream(getPhotoStreamWithColor(Color.rgb(0xe3, 0x33, 0x1c)));
- return this;
- }
-
- Builder setBluePhoto() {
- setPhotoStream(getPhotoStreamWithColor(Color.rgb(0x00, 0xaa, 0xe6)));
- return this;
- }
-
- Builder setOrangePhoto() {
- setPhotoStream(getPhotoStreamWithColor(Color.rgb(0xea, 0x95, 0x00)));
- return this;
- }
-
- Builder setPurplePhoto() {
- setPhotoStream(getPhotoStreamWithColor(Color.rgb(0x99, 0x5a, 0xa0)));
- return this;
- }
-
- /** Creates a contact photo with a green background and a circle of the given color. */
- private static ByteArrayOutputStream getPhotoStreamWithColor(int color) {
- int width = 300;
- int height = 300;
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- canvas.drawColor(Color.argb(0xff, 0x4c, 0x9c, 0x23));
- Paint paint = new Paint();
- paint.setColor(color);
- paint.setStyle(Paint.Style.FILL);
- canvas.drawCircle(width / 2, height / 2, width / 3, paint);
-
- ByteArrayOutputStream photoStream = new ByteArrayOutputStream();
- bitmap.compress(Bitmap.CompressFormat.PNG, 75, photoStream);
- return photoStream;
- }
- }
- }
-
- static class PhoneNumber {
- public final String value;
- public final int type;
- public final String label;
-
- PhoneNumber(String value, int type) {
- this.value = value;
- this.type = type;
- label = "simulator phone number";
- }
- }
-
- static class Email {
- public final String value;
- public final int type;
- public final String label;
-
- Email(String simpleEmail) {
- value = simpleEmail;
- type = ContactsContract.CommonDataKinds.Email.TYPE_WORK;
- label = "simulator email";
- }
- }
-
- private SimulatorContacts() {}
-}
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/dialer/simulator/impl/SimulatorVoicemail.java b/java/com/android/dialer/simulator/impl/SimulatorVoicemail.java
deleted file mode 100644
index 04de201ae..000000000
--- a/java/com/android/dialer/simulator/impl/SimulatorVoicemail.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.ComponentName;
-import android.content.ContentValues;
-import android.content.Context;
-import android.provider.VoicemailContract.Status;
-import android.provider.VoicemailContract.Voicemails;
-import android.support.annotation.NonNull;
-import android.support.annotation.WorkerThread;
-import android.telecom.PhoneAccountHandle;
-import android.telephony.TelephonyManager;
-import com.android.dialer.common.Assert;
-import com.google.auto.value.AutoValue;
-import java.util.concurrent.TimeUnit;
-
-/** Populates the device database with voicemail entries. */
-final class SimulatorVoicemail {
- private static final String ACCOUNT_ID = "ACCOUNT_ID";
-
- private static final Voicemail.Builder[] SIMPLE_VOICEMAILS = {
- // Long transcription with an embedded phone number.
- Voicemail.builder()
- .setPhoneNumber("+1-302-6365454")
- .setTranscription(
- "Hi, this is a very long voicemail. Please call me back at 650 253 0000. "
- + "I hope you listen to all of it. This is very important. "
- + "Hi, this is a very long voicemail. "
- + "I hope you listen to all of it. It's very important.")
- .setDurationSeconds(10)
- .setIsRead(false),
- // RTL transcription.
- Voicemail.builder()
- .setPhoneNumber("+1-302-6365454")
- .setTranscription("هزاران دوست کم اند و یک دشمن زیاد")
- .setDurationSeconds(60)
- .setIsRead(true),
- // Empty number.
- Voicemail.builder()
- .setPhoneNumber("")
- .setTranscription("")
- .setDurationSeconds(60)
- .setIsRead(true),
- // No duration.
- Voicemail.builder()
- .setPhoneNumber("+1-302-6365454")
- .setTranscription("")
- .setDurationSeconds(0)
- .setIsRead(true),
- // Short number.
- Voicemail.builder()
- .setPhoneNumber("711")
- .setTranscription("This is a short voicemail.")
- .setDurationSeconds(12)
- .setIsRead(true),
- };
-
- @WorkerThread
- public static void populateVoicemail(@NonNull Context context) {
- Assert.isWorkerThread();
- enableVoicemail(context);
-
- // Do this 4 times to make the voicemail database 4 times bigger.
- long timeMillis = System.currentTimeMillis();
- for (int i = 0; i < 4; i++) {
- for (Voicemail.Builder builder : SIMPLE_VOICEMAILS) {
- Voicemail voicemail = builder.setTimeMillis(timeMillis).build();
- context
- .getContentResolver()
- .insert(
- Voicemails.buildSourceUri(context.getPackageName()),
- voicemail.getAsContentValues(context));
- timeMillis -= TimeUnit.HOURS.toMillis(2);
- }
- }
- }
-
- private static void enableVoicemail(@NonNull Context context) {
- PhoneAccountHandle handle =
- new PhoneAccountHandle(new ComponentName(context, SimulatorVoicemail.class), ACCOUNT_ID);
-
- ContentValues values = new ContentValues();
- values.put(Status.SOURCE_PACKAGE, handle.getComponentName().getPackageName());
- values.put(Status.SOURCE_TYPE, TelephonyManager.VVM_TYPE_OMTP);
- values.put(Status.PHONE_ACCOUNT_COMPONENT_NAME, handle.getComponentName().flattenToString());
- values.put(Status.PHONE_ACCOUNT_ID, handle.getId());
- values.put(Status.CONFIGURATION_STATE, Status.CONFIGURATION_STATE_OK);
- values.put(Status.DATA_CHANNEL_STATE, Status.DATA_CHANNEL_STATE_OK);
- values.put(Status.NOTIFICATION_CHANNEL_STATE, Status.NOTIFICATION_CHANNEL_STATE_OK);
- context.getContentResolver().insert(Status.buildSourceUri(context.getPackageName()), values);
- }
-
- @AutoValue
- abstract static class Voicemail {
- @NonNull
- abstract String getPhoneNumber();
-
- @NonNull
- abstract String getTranscription();
-
- abstract long getDurationSeconds();
-
- abstract long getTimeMillis();
-
- abstract boolean getIsRead();
-
- static Builder builder() {
- return new AutoValue_SimulatorVoicemail_Voicemail.Builder();
- }
-
- ContentValues getAsContentValues(Context context) {
- ContentValues values = new ContentValues();
- values.put(Voicemails.DATE, getTimeMillis());
- values.put(Voicemails.NUMBER, getPhoneNumber());
- values.put(Voicemails.DURATION, getDurationSeconds());
- values.put(Voicemails.SOURCE_PACKAGE, context.getPackageName());
- values.put(Voicemails.IS_READ, getIsRead() ? 1 : 0);
- values.put(Voicemails.TRANSCRIPTION, getTranscription());
- return values;
- }
-
- @AutoValue.Builder
- abstract static class Builder {
- abstract Builder setPhoneNumber(@NonNull String phoneNumber);
-
- abstract Builder setTranscription(@NonNull String transcription);
-
- abstract Builder setDurationSeconds(long durationSeconds);
-
- abstract Builder setTimeMillis(long timeMillis);
-
- abstract Builder setIsRead(boolean isRead);
-
- abstract Voicemail build();
- }
- }
-
- private SimulatorVoicemail() {}
-}