1 /* 2 * Copyright (C) 2016 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.voicemail.impl; 18 19 import android.net.Uri; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 import android.telecom.PhoneAccountHandle; 23 import android.text.TextUtils; 24 25 /** Represents a single voicemail stored in the voicemail content provider. */ 26 public class Voicemail implements Parcelable { 27 28 private final Long mTimestamp; 29 private final String mNumber; 30 private final PhoneAccountHandle mPhoneAccount; 31 private final Long mId; 32 private final Long mDuration; 33 private final String mSource; 34 private final String mProviderData; 35 private final Uri mUri; 36 private final Boolean mIsRead; 37 private final Boolean mHasContent; 38 private final String mTranscription; 39 Voicemail( Long timestamp, String number, PhoneAccountHandle phoneAccountHandle, Long id, Long duration, String source, String providerData, Uri uri, Boolean isRead, Boolean hasContent, String transcription)40 private Voicemail( 41 Long timestamp, 42 String number, 43 PhoneAccountHandle phoneAccountHandle, 44 Long id, 45 Long duration, 46 String source, 47 String providerData, 48 Uri uri, 49 Boolean isRead, 50 Boolean hasContent, 51 String transcription) { 52 mTimestamp = timestamp; 53 mNumber = number; 54 mPhoneAccount = phoneAccountHandle; 55 mId = id; 56 mDuration = duration; 57 mSource = source; 58 mProviderData = providerData; 59 mUri = uri; 60 mIsRead = isRead; 61 mHasContent = hasContent; 62 mTranscription = transcription; 63 } 64 65 /** 66 * Create a {@link Builder} for a new {@link Voicemail} to be inserted. 67 * 68 * <p>The number and the timestamp are mandatory for insertion. 69 */ createForInsertion(long timestamp, String number)70 public static Builder createForInsertion(long timestamp, String number) { 71 return new Builder().setNumber(number).setTimestamp(timestamp); 72 } 73 74 /** 75 * Create a {@link Builder} for a {@link Voicemail} to be updated (or deleted). 76 * 77 * <p>The id and source data fields are mandatory for update - id is necessary for updating the 78 * database and source data is necessary for updating the server. 79 */ createForUpdate(long id, String sourceData)80 public static Builder createForUpdate(long id, String sourceData) { 81 return new Builder().setId(id).setSourceData(sourceData); 82 } 83 84 /** 85 * Builder pattern for creating a {@link Voicemail}. The builder must be created with the {@link 86 * #createForInsertion(long, String)} method. 87 * 88 * <p>This class is <b>not thread safe</b> 89 */ 90 public static class Builder { 91 92 private Long mBuilderTimestamp; 93 private String mBuilderNumber; 94 private PhoneAccountHandle mBuilderPhoneAccount; 95 private Long mBuilderId; 96 private Long mBuilderDuration; 97 private String mBuilderSourcePackage; 98 private String mBuilderSourceData; 99 private Uri mBuilderUri; 100 private Boolean mBuilderIsRead; 101 private boolean mBuilderHasContent; 102 private String mBuilderTranscription; 103 104 /** You should use the correct factory method to construct a builder. */ Builder()105 private Builder() {} 106 setNumber(String number)107 public Builder setNumber(String number) { 108 mBuilderNumber = number; 109 return this; 110 } 111 setTimestamp(long timestamp)112 public Builder setTimestamp(long timestamp) { 113 mBuilderTimestamp = timestamp; 114 return this; 115 } 116 setPhoneAccount(PhoneAccountHandle phoneAccount)117 public Builder setPhoneAccount(PhoneAccountHandle phoneAccount) { 118 mBuilderPhoneAccount = phoneAccount; 119 return this; 120 } 121 setId(long id)122 public Builder setId(long id) { 123 mBuilderId = id; 124 return this; 125 } 126 setDuration(long duration)127 public Builder setDuration(long duration) { 128 mBuilderDuration = duration; 129 return this; 130 } 131 setSourcePackage(String sourcePackage)132 public Builder setSourcePackage(String sourcePackage) { 133 mBuilderSourcePackage = sourcePackage; 134 return this; 135 } 136 setSourceData(String sourceData)137 public Builder setSourceData(String sourceData) { 138 mBuilderSourceData = sourceData; 139 return this; 140 } 141 setUri(Uri uri)142 public Builder setUri(Uri uri) { 143 mBuilderUri = uri; 144 return this; 145 } 146 setIsRead(boolean isRead)147 public Builder setIsRead(boolean isRead) { 148 mBuilderIsRead = isRead; 149 return this; 150 } 151 setHasContent(boolean hasContent)152 public Builder setHasContent(boolean hasContent) { 153 mBuilderHasContent = hasContent; 154 return this; 155 } 156 setTranscription(String transcription)157 public Builder setTranscription(String transcription) { 158 mBuilderTranscription = transcription; 159 return this; 160 } 161 build()162 public Voicemail build() { 163 mBuilderId = mBuilderId == null ? -1 : mBuilderId; 164 mBuilderTimestamp = mBuilderTimestamp == null ? 0 : mBuilderTimestamp; 165 mBuilderDuration = mBuilderDuration == null ? 0 : mBuilderDuration; 166 mBuilderIsRead = mBuilderIsRead == null ? false : mBuilderIsRead; 167 return new Voicemail( 168 mBuilderTimestamp, 169 mBuilderNumber, 170 mBuilderPhoneAccount, 171 mBuilderId, 172 mBuilderDuration, 173 mBuilderSourcePackage, 174 mBuilderSourceData, 175 mBuilderUri, 176 mBuilderIsRead, 177 mBuilderHasContent, 178 mBuilderTranscription); 179 } 180 } 181 182 /** 183 * The identifier of the voicemail in the content provider. 184 * 185 * <p>This may be missing in the case of a new {@link Voicemail} that we plan to insert into the 186 * content provider, since until it has been inserted we don't know what id it should have. If 187 * none is specified, we return -1. 188 */ getId()189 public long getId() { 190 return mId; 191 } 192 193 /** The number of the person leaving the voicemail, empty string if unknown, null if not set. */ getNumber()194 public String getNumber() { 195 return mNumber; 196 } 197 198 /** The phone account associated with the voicemail, null if not set. */ getPhoneAccount()199 public PhoneAccountHandle getPhoneAccount() { 200 return mPhoneAccount; 201 } 202 203 /** The timestamp the voicemail was received, in millis since the epoch, zero if not set. */ getTimestampMillis()204 public long getTimestampMillis() { 205 return mTimestamp; 206 } 207 208 /** Gets the duration of the voicemail in millis, or zero if the field is not set. */ getDuration()209 public long getDuration() { 210 return mDuration; 211 } 212 213 /** 214 * Returns the package name of the source that added this voicemail, or null if this field is not 215 * set. 216 */ getSourcePackage()217 public String getSourcePackage() { 218 return mSource; 219 } 220 221 /** 222 * Returns the application-specific data type stored with the voicemail, or null if this field is 223 * not set. 224 * 225 * <p>Source data is typically used as an identifier to uniquely identify the voicemail against 226 * the voicemail server. This is likely to be something like the IMAP UID, or some other 227 * server-generated identifying string. 228 */ getSourceData()229 public String getSourceData() { 230 return mProviderData; 231 } 232 233 /** 234 * Gets the Uri that can be used to refer to this voicemail, and to make it play. 235 * 236 * <p>Returns null if we don't know the Uri. 237 */ getUri()238 public Uri getUri() { 239 return mUri; 240 } 241 242 /** 243 * Tells us if the voicemail message has been marked as read. 244 * 245 * <p>Always returns false if this field has not been set, i.e. if hasRead() returns false. 246 */ isRead()247 public boolean isRead() { 248 return mIsRead; 249 } 250 251 /** Tells us if there is content stored at the Uri. */ hasContent()252 public boolean hasContent() { 253 return mHasContent; 254 } 255 256 /** Returns the text transcription of this voicemail, or null if this field is not set. */ getTranscription()257 public String getTranscription() { 258 return mTranscription; 259 } 260 261 @Override describeContents()262 public int describeContents() { 263 return 0; 264 } 265 266 @Override writeToParcel(Parcel dest, int flags)267 public void writeToParcel(Parcel dest, int flags) { 268 dest.writeLong(mTimestamp); 269 writeCharSequence(dest, mNumber); 270 if (mPhoneAccount == null) { 271 dest.writeInt(0); 272 } else { 273 dest.writeInt(1); 274 mPhoneAccount.writeToParcel(dest, flags); 275 } 276 dest.writeLong(mId); 277 dest.writeLong(mDuration); 278 writeCharSequence(dest, mSource); 279 writeCharSequence(dest, mProviderData); 280 if (mUri == null) { 281 dest.writeInt(0); 282 } else { 283 dest.writeInt(1); 284 mUri.writeToParcel(dest, flags); 285 } 286 if (mIsRead) { 287 dest.writeInt(1); 288 } else { 289 dest.writeInt(0); 290 } 291 if (mHasContent) { 292 dest.writeInt(1); 293 } else { 294 dest.writeInt(0); 295 } 296 writeCharSequence(dest, mTranscription); 297 } 298 299 public static final Creator<Voicemail> CREATOR = 300 new Creator<Voicemail>() { 301 @Override 302 public Voicemail createFromParcel(Parcel in) { 303 return new Voicemail(in); 304 } 305 306 @Override 307 public Voicemail[] newArray(int size) { 308 return new Voicemail[size]; 309 } 310 }; 311 Voicemail(Parcel in)312 private Voicemail(Parcel in) { 313 mTimestamp = in.readLong(); 314 mNumber = (String) readCharSequence(in); 315 if (in.readInt() > 0) { 316 mPhoneAccount = PhoneAccountHandle.CREATOR.createFromParcel(in); 317 } else { 318 mPhoneAccount = null; 319 } 320 mId = in.readLong(); 321 mDuration = in.readLong(); 322 mSource = (String) readCharSequence(in); 323 mProviderData = (String) readCharSequence(in); 324 if (in.readInt() > 0) { 325 mUri = Uri.CREATOR.createFromParcel(in); 326 } else { 327 mUri = null; 328 } 329 mIsRead = in.readInt() > 0 ? true : false; 330 mHasContent = in.readInt() > 0 ? true : false; 331 mTranscription = (String) readCharSequence(in); 332 } 333 readCharSequence(Parcel in)334 private static CharSequence readCharSequence(Parcel in) { 335 return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 336 } 337 writeCharSequence(Parcel dest, CharSequence val)338 public static void writeCharSequence(Parcel dest, CharSequence val) { 339 TextUtils.writeToParcel(val, dest, 0); 340 } 341 } 342