1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.dialer.databasepopulator; 18 19 import android.content.ComponentName; 20 import android.content.ContentValues; 21 import android.content.Context; 22 import android.os.Build.VERSION; 23 import android.os.Build.VERSION_CODES; 24 import android.provider.VoicemailContract.Status; 25 import android.provider.VoicemailContract.Voicemails; 26 import android.support.annotation.NonNull; 27 import android.support.annotation.VisibleForTesting; 28 import android.support.annotation.WorkerThread; 29 import android.telecom.PhoneAccountHandle; 30 import com.android.dialer.common.Assert; 31 import com.google.auto.value.AutoValue; 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.List; 35 import java.util.concurrent.TimeUnit; 36 37 /** Populates the device database with voicemail entries. */ 38 public final class VoicemailPopulator { 39 private static final String ACCOUNT_ID = "ACCOUNT_ID"; 40 private static String componentName = ""; 41 private static final Voicemail.Builder[] SIMPLE_VOICEMAILS = { 42 // Long transcription with an embedded phone number. 43 Voicemail.builder() 44 .setPhoneNumber("+1-302-6365454") 45 .setTranscription( 46 "Hi, this is a very long voicemail. Please call me back at 650 253 0000. " 47 + "I hope you listen to all of it. This is very important. " 48 + "Hi, this is a very long voicemail. " 49 + "I hope you listen to all of it. It's very important.") 50 .setPhoneAccountComponentName(componentName) 51 .setDurationSeconds(10) 52 .setIsRead(false), 53 // RTL transcription. 54 Voicemail.builder() 55 .setPhoneNumber("+1-302-6365454") 56 .setTranscription("هزاران دوست کم اند و یک دشمن زیاد") 57 .setDurationSeconds(60) 58 .setPhoneAccountComponentName(componentName) 59 .setIsRead(true), 60 // Empty number. 61 Voicemail.builder() 62 .setPhoneNumber("") 63 .setTranscription("") 64 .setDurationSeconds(60) 65 .setPhoneAccountComponentName(componentName) 66 .setIsRead(true), 67 // No duration. 68 Voicemail.builder() 69 .setPhoneNumber("+1-302-6365454") 70 .setTranscription("") 71 .setDurationSeconds(0) 72 .setPhoneAccountComponentName(componentName) 73 .setIsRead(true), 74 }; 75 76 @WorkerThread populateVoicemail(@onNull Context context, boolean fastMode)77 public static void populateVoicemail(@NonNull Context context, boolean fastMode) { 78 Assert.isWorkerThread(); 79 enableVoicemail(context); 80 List<Voicemail.Builder> voicemails = new ArrayList<>(); 81 if (fastMode) { 82 voicemails.add(SIMPLE_VOICEMAILS[0]); 83 } else { 84 voicemails = Arrays.asList(SIMPLE_VOICEMAILS); 85 } 86 // Do this 4 times to make the voicemail database 4 times bigger. 87 long timeMillis = System.currentTimeMillis(); 88 for (int i = 0; i < 4; i++) { 89 for (Voicemail.Builder builder : voicemails) { 90 Voicemail voicemail = builder.setTimeMillis(timeMillis).build(); 91 context 92 .getContentResolver() 93 .insert( 94 Voicemails.buildSourceUri(context.getPackageName()), 95 voicemail.getAsContentValues(context)); 96 timeMillis -= TimeUnit.HOURS.toMillis(2); 97 } 98 } 99 } 100 101 @WorkerThread populateVoicemail(@onNull Context context)102 public static void populateVoicemail(@NonNull Context context) { 103 populateVoicemail(context, false); 104 } 105 106 @WorkerThread deleteAllVoicemail(@onNull Context context)107 public static void deleteAllVoicemail(@NonNull Context context) { 108 Assert.isWorkerThread(); 109 context 110 .getContentResolver() 111 .delete(Voicemails.buildSourceUri(context.getPackageName()), null, null); 112 } 113 114 @VisibleForTesting enableVoicemail(@onNull Context context)115 public static void enableVoicemail(@NonNull Context context) { 116 PhoneAccountHandle handle = 117 new PhoneAccountHandle(new ComponentName(context, VoicemailPopulator.class), ACCOUNT_ID); 118 componentName = handle.getComponentName().toString(); 119 ContentValues values = new ContentValues(); 120 values.put(Status.SOURCE_PACKAGE, handle.getComponentName().getPackageName()); 121 if (VERSION.SDK_INT >= VERSION_CODES.N_MR1) { 122 values.put(Status.SOURCE_TYPE, "vvm_type_vvm3"); // mark populated voice mail as vvm3 123 } 124 values.put(Status.PHONE_ACCOUNT_COMPONENT_NAME, handle.getComponentName().flattenToString()); 125 values.put(Status.PHONE_ACCOUNT_ID, handle.getId()); 126 values.put(Status.CONFIGURATION_STATE, Status.CONFIGURATION_STATE_OK); 127 values.put(Status.DATA_CHANNEL_STATE, Status.DATA_CHANNEL_STATE_OK); 128 values.put(Status.NOTIFICATION_CHANNEL_STATE, Status.NOTIFICATION_CHANNEL_STATE_OK); 129 context.getContentResolver().insert(Status.buildSourceUri(context.getPackageName()), values); 130 } 131 132 /** Data for a single voicemail entry. */ 133 @AutoValue 134 public abstract static class Voicemail { 135 @NonNull getPhoneNumber()136 public abstract String getPhoneNumber(); 137 138 @NonNull getTranscription()139 public abstract String getTranscription(); 140 getDurationSeconds()141 public abstract long getDurationSeconds(); 142 getTimeMillis()143 public abstract long getTimeMillis(); 144 getIsRead()145 public abstract boolean getIsRead(); 146 getPhoneAccountComponentName()147 public abstract String getPhoneAccountComponentName(); 148 builder()149 public static Builder builder() { 150 return new AutoValue_VoicemailPopulator_Voicemail.Builder(); 151 } 152 getAsContentValues(Context context)153 public ContentValues getAsContentValues(Context context) { 154 ContentValues values = new ContentValues(); 155 values.put(Voicemails.DATE, getTimeMillis()); 156 values.put(Voicemails.NUMBER, getPhoneNumber()); 157 values.put(Voicemails.DURATION, getDurationSeconds()); 158 values.put(Voicemails.SOURCE_PACKAGE, context.getPackageName()); 159 values.put(Voicemails.IS_READ, getIsRead() ? 1 : 0); 160 values.put(Voicemails.TRANSCRIPTION, getTranscription()); 161 values.put(Voicemails.PHONE_ACCOUNT_COMPONENT_NAME, getPhoneAccountComponentName()); 162 return values; 163 } 164 165 /** Builder for a single voicemail entry. */ 166 @AutoValue.Builder 167 public abstract static class Builder { setPhoneNumber(@onNull String phoneNumber)168 public abstract Builder setPhoneNumber(@NonNull String phoneNumber); 169 setTranscription(@onNull String transcription)170 public abstract Builder setTranscription(@NonNull String transcription); 171 setDurationSeconds(long durationSeconds)172 public abstract Builder setDurationSeconds(long durationSeconds); 173 setTimeMillis(long timeMillis)174 public abstract Builder setTimeMillis(long timeMillis); 175 setIsRead(boolean isRead)176 public abstract Builder setIsRead(boolean isRead); 177 setPhoneAccountComponentName(String phoneAccountComponentName)178 public abstract Builder setPhoneAccountComponentName(String phoneAccountComponentName); 179 build()180 public abstract Voicemail build(); 181 } 182 } 183 VoicemailPopulator()184 private VoicemailPopulator() {} 185 } 186