diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2017-08-31 16:17:04 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-08-31 16:17:04 +0000 |
commit | c39ea3c55fac807c0b98aabdf56c70dc8a49036c (patch) | |
tree | e282668a9587cf6c1ec7b604dea860400c75c6c7 /java/com/android/dialer/databasepopulator | |
parent | 68038172793ee0e2ab3e2e56ddfbeb82879d1f58 (diff) | |
parent | 2ca4318cc1ee57dda907ba2069bd61d162b1baef (diff) |
Merge "Update Dialer source to latest internal Google revision."
Diffstat (limited to 'java/com/android/dialer/databasepopulator')
4 files changed, 706 insertions, 0 deletions
diff --git a/java/com/android/dialer/databasepopulator/AndroidManifest.xml b/java/com/android/dialer/databasepopulator/AndroidManifest.xml new file mode 100644 index 000000000..0a3728566 --- /dev/null +++ b/java/com/android/dialer/databasepopulator/AndroidManifest.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<manifest package="com.android.dialer.databasepopulator"> +</manifest>
\ No newline at end of file diff --git a/java/com/android/dialer/databasepopulator/CallLogPopulator.java b/java/com/android/dialer/databasepopulator/CallLogPopulator.java new file mode 100644 index 000000000..7c387ecd1 --- /dev/null +++ b/java/com/android/dialer/databasepopulator/CallLogPopulator.java @@ -0,0 +1,168 @@ +/* + * 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.databasepopulator; + +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.Arrays; +import java.util.concurrent.TimeUnit; + +/** Populates the device database with call log entries. */ +public final class CallLogPopulator { + // 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) { + populateCallLog(context, false); + } + + @WorkerThread + public static void populateCallLogWithoutMissed(@NonNull Context context) { + populateCallLog(context, true); + } + + @WorkerThread + public static void populateCallLog(@NonNull Context context, boolean isWithoutMissedCalls) { + 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(); + if (isWithoutMissedCalls && builder.build().getType() == Calls.MISSED_TYPE) { + continue; + } + 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); + } + } + + @WorkerThread + public static void deleteAllCallLog(@NonNull Context context) { + Assert.isWorkerThread(); + try { + context + .getContentResolver() + .applyBatch( + CallLog.AUTHORITY, + new ArrayList<>( + Arrays.asList(ContentProviderOperation.newDelete(Calls.CONTENT_URI).build()))); + } catch (RemoteException | OperationApplicationException e) { + Assert.fail("failed to delete call log: " + 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_CallLogPopulator_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 CallLogPopulator() {} +} diff --git a/java/com/android/dialer/databasepopulator/ContactsPopulator.java b/java/com/android/dialer/databasepopulator/ContactsPopulator.java new file mode 100644 index 000000000..e93c5697a --- /dev/null +++ b/java/com/android/dialer/databasepopulator/ContactsPopulator.java @@ -0,0 +1,356 @@ +/* + * 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.databasepopulator; + +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.provider.ContactsContract.RawContacts; +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.Arrays; +import java.util.List; + +/** Populates the device database with contacts. */ +public final class ContactsPopulator { + // 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) + .setPinned(1) + .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) + .setPinned(2) + .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) + .setPinned(3) + .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) + .setPinned(4) + .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)) + .setBluePhoto() + .build(), + // France, number with Japanese name. + Contact.builder() + .setName("スパイク・スピーゲル") + .addPhoneNumber(new PhoneNumber("+33 (0)1 42 68 53 00", Phone.TYPE_MOBILE)) + .setBluePhoto() + .build(), + // Israel, RTL name and non-e164 number. + Contact.builder() + .setName("עקב אריה טברסק") + .addPhoneNumber(new PhoneNumber("+33 (0)1 42 68 53 00", Phone.TYPE_MOBILE)) + .setBluePhoto() + .build(), + // UAE, RTL name. + Contact.builder() + .setName("سلام دنیا") + .addPhoneNumber(new PhoneNumber("+971 4 4509500", Phone.TYPE_MOBILE)) + .setBluePhoto() + .build(), + // Brazil, contact with no name. + Contact.builder() + .addPhoneNumber(new PhoneNumber("+55-31-2128-6800", Phone.TYPE_MOBILE)) + .setBluePhoto() + .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)) + .setBluePhoto() + .build(), + // None, contact with no phone number. + Contact.builder() + .setName("No Phone Number") + .addEmail(new Email("no@example.com")) + .setIsStarred(true) + .setBluePhoto() + .build(), + }; + + @WorkerThread + public 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); + } + } + + @WorkerThread + public static void deleteAllContacts(@NonNull Context context) { + Assert.isWorkerThread(); + try { + context + .getContentResolver() + .applyBatch( + ContactsContract.AUTHORITY, + new ArrayList<>( + Arrays.asList( + ContentProviderOperation.newDelete(RawContacts.CONTENT_URI).build()))); + } catch (RemoteException | OperationApplicationException e) { + Assert.fail("failed to delete 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() ? 1 : 0) + .withValue( + ContactsContract.RawContacts.PINNED, + contact.getIsStarred() ? contact.getPinned() : 0) + .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(); + + abstract int getPinned(); + + @Nullable + abstract ByteArrayOutputStream getPhotoStream(); + + @NonNull + abstract List<PhoneNumber> getPhoneNumbers(); + + @NonNull + abstract List<Email> getEmails(); + + static Builder builder() { + return new AutoValue_ContactsPopulator_Contact.Builder() + .setAccountType("com.google") + .setAccountName("foo@example") + .setPinned(0) + .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 setPinned(int position); + + 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 ContactsPopulator() {} +} diff --git a/java/com/android/dialer/databasepopulator/VoicemailPopulator.java b/java/com/android/dialer/databasepopulator/VoicemailPopulator.java new file mode 100644 index 000000000..e99f7c7d4 --- /dev/null +++ b/java/com/android/dialer/databasepopulator/VoicemailPopulator.java @@ -0,0 +1,164 @@ +/* + * 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.databasepopulator; + +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. */ +public final class VoicemailPopulator { + 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); + } + } + } + + @WorkerThread + public static void deleteAllVoicemail(@NonNull Context context) { + Assert.isWorkerThread(); + context + .getContentResolver() + .delete(Voicemails.buildSourceUri(context.getPackageName()), "", new String[] {}); + } + + private static void enableVoicemail(@NonNull Context context) { + PhoneAccountHandle handle = + new PhoneAccountHandle(new ComponentName(context, VoicemailPopulator.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); + } + + /** Data for a single voicemail entry. */ + @AutoValue + public abstract static class Voicemail { + @NonNull + public abstract String getPhoneNumber(); + + @NonNull + public abstract String getTranscription(); + + public abstract long getDurationSeconds(); + + public abstract long getTimeMillis(); + + public abstract boolean getIsRead(); + + public static Builder builder() { + return new AutoValue_VoicemailPopulator_Voicemail.Builder(); + } + + public 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; + } + + /** Builder for a single voicemail entry. */ + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder setPhoneNumber(@NonNull String phoneNumber); + + public abstract Builder setTranscription(@NonNull String transcription); + + public abstract Builder setDurationSeconds(long durationSeconds); + + public abstract Builder setTimeMillis(long timeMillis); + + public abstract Builder setIsRead(boolean isRead); + + public abstract Voicemail build(); + } + } + + private VoicemailPopulator() {} +} |