summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/simulator
diff options
context:
space:
mode:
authorEric Erfanian <erfanian@google.com>2017-08-31 06:57:16 -0700
committerEric Erfanian <erfanian@google.com>2017-08-31 16:13:53 +0000
commit2ca4318cc1ee57dda907ba2069bd61d162b1baef (patch)
treee282668a9587cf6c1ec7b604dea860400c75c6c7 /java/com/android/dialer/simulator
parent68038172793ee0e2ab3e2e56ddfbeb82879d1f58 (diff)
Update Dialer source to latest internal Google revision.
Previously, Android's Dialer app was developed in an internal Google source control system and only exported to public during AOSP drops. The Dialer team is now switching to a public development model similar to the telephony team. This CL represents all internal Google changes that were committed to Dialer between the public O release and today's tip of tree on internal master. This CL squashes those changes into a single commit. In subsequent changes, changes will be exported on a per-commit basis. Test: make, flash install, run Merged-In: I45270eaa8ce732d71a1bd84b08c7fa0e99af3160 Change-Id: I529aaeb88535b9533c0ae4ef4e6c1222d4e0f1c8 PiperOrigin-RevId: 167068436
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() {}
-}